Conversion to Apache 2.0 license
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / public-api / controls / scrollable / item-view / depth-layout.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <algorithm>
19
20 #include <dali-toolkit/public-api/controls/scrollable/item-view/depth-layout.h>
21
22 using namespace Dali;
23 using namespace Dali::Toolkit;
24 using namespace std;
25
26 namespace // unnamed namespace
27 {
28
29 const unsigned int DEFAULT_NUMBER_OF_COLUMNS    = 3;
30 const float        DEFAULT_NUMBER_OF_ROWS       = 20.0f;
31 const float        DEFAULT_ROW_SPACING          = 55.0f;
32 const float        DEFAULT_BOTTOM_MARGIN_FACTOR = 0.1f;
33 const Radian       DEFAULT_TILT_ANGLE           ( Math::PI*0.12f );
34 const Radian       DEFAULT_ITEM_TILT_ANGLE      ( -Math::PI*0.025f );
35 const float        DEFAULT_SCROLL_SPEED_FACTOR  = 0.02f;
36 const float        DEFAULT_MAXIMUM_SWIPE_SPEED  = 50.0f;
37 const float        DEFAULT_ITEM_FLICK_ANIMATION_DURATION = 0.03f;
38
39 static Vector3 GetItemSizeDefaultFunction(unsigned int numberOfColumns, float layoutWidth)
40 {
41   float width = layoutWidth / static_cast<float>(numberOfColumns + 1);
42
43   // 1x1 aspect ratio
44   return Vector3(width, width, width);
45 }
46
47 static float GetBottomMarginDefaultFunction(float layoutHeight)
48 {
49   return layoutHeight * DEFAULT_BOTTOM_MARGIN_FACTOR;
50 }
51
52 struct GetColumnPositionDefaultFunction
53 {
54   float operator()(unsigned int numberOfColumns,
55                    unsigned int columnNumber,
56                    const Vector3& itemSize,
57                    float layoutWidth)
58   {
59     // Share the available space between margins & column spacings
60     float availableSpace = max(0.0f, (layoutWidth - itemSize.width*numberOfColumns));
61
62     float leftMargin = availableSpace/numberOfColumns * 0.5f;
63
64     float columnPosition = leftMargin + itemSize.width*0.5f + columnNumber*(itemSize.width + availableSpace/numberOfColumns);
65
66     return columnPosition - layoutWidth*0.5f;
67   }
68 };
69
70 struct DepthPositionConstraint0
71 {
72   DepthPositionConstraint0(unsigned int numberOfColumns,
73                            unsigned int columnNumber,
74                            DepthLayout::ItemSizeFunction itemSizeFunction,
75                            DepthLayout::BottomMarginFunction bottomMarginFunction,
76                            DepthLayout::ColumnPositionFunction columnPositionFunction,
77                            float heightScale,
78                            float depthScale)
79   : mNumberOfColumns(numberOfColumns),
80     mColumnNumber(columnNumber),
81     mItemSizeFunction(itemSizeFunction),
82     mBottomMarginFunction(bottomMarginFunction),
83     mColumnPositionFunction(columnPositionFunction),
84     mHeightScale(heightScale),
85     mDepthScale(depthScale)
86   {
87   }
88
89   Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
90   {
91     Vector3 itemSize = mItemSizeFunction(mNumberOfColumns, layoutSize.width);
92
93     float rowLayoutPositon = layoutPosition - static_cast<float>(mColumnNumber);
94
95     return Vector3(  mColumnPositionFunction(mNumberOfColumns, mColumnNumber, itemSize, layoutSize.width),
96                      rowLayoutPositon*mHeightScale + layoutSize.height*0.5f - mBottomMarginFunction(layoutSize.height) - itemSize.height * 0.5f,
97                     -rowLayoutPositon*mDepthScale );
98   }
99
100   unsigned int mNumberOfColumns;
101   unsigned int mColumnNumber;
102
103   DepthLayout::ItemSizeFunction       mItemSizeFunction;
104   DepthLayout::BottomMarginFunction   mBottomMarginFunction;
105   DepthLayout::ColumnPositionFunction mColumnPositionFunction;
106
107   float mHeightScale;
108   float mDepthScale;
109 };
110
111 struct DepthPositionConstraint90
112 {
113   DepthPositionConstraint90(unsigned int numberOfColumns,
114                             unsigned int columnNumber,
115                             DepthLayout::ItemSizeFunction itemSizeFunction,
116                             DepthLayout::BottomMarginFunction bottomMarginFunction,
117                             DepthLayout::ColumnPositionFunction columnPositionFunction,
118                             float heightScale,
119                             float depthScale)
120   : mNumberOfColumns(numberOfColumns),
121     mColumnNumber(columnNumber),
122     mItemSizeFunction(itemSizeFunction),
123     mBottomMarginFunction(bottomMarginFunction),
124     mColumnPositionFunction(columnPositionFunction),
125     mHeightScale(heightScale),
126     mDepthScale(depthScale)
127   {
128   }
129
130   Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
131   {
132     Vector3 itemSize = mItemSizeFunction(mNumberOfColumns, layoutSize.height);
133
134     float rowLayoutPositon = layoutPosition - static_cast<float>(mColumnNumber) + mNumberOfColumns*0.5f;
135
136     return Vector3(  rowLayoutPositon*mHeightScale + layoutSize.width*0.5f - mBottomMarginFunction(layoutSize.width) - itemSize.height * 0.5f,
137                      -mColumnPositionFunction(mNumberOfColumns, mColumnNumber, itemSize, layoutSize.height),
138                     -rowLayoutPositon*mDepthScale );
139   }
140
141   unsigned int mNumberOfColumns;
142   unsigned int mColumnNumber;
143
144   DepthLayout::ItemSizeFunction       mItemSizeFunction;
145   DepthLayout::BottomMarginFunction   mBottomMarginFunction;
146   DepthLayout::ColumnPositionFunction mColumnPositionFunction;
147
148   float mHeightScale;
149   float mDepthScale;
150 };
151
152 struct DepthPositionConstraint180
153 {
154   DepthPositionConstraint180(unsigned int numberOfColumns,
155                              unsigned int columnNumber,
156                              DepthLayout::ItemSizeFunction itemSizeFunction,
157                              DepthLayout::BottomMarginFunction bottomMarginFunction,
158                              DepthLayout::ColumnPositionFunction columnPositionFunction,
159                              float heightScale,
160                              float depthScale)
161   : mNumberOfColumns(numberOfColumns),
162     mColumnNumber(columnNumber),
163     mItemSizeFunction(itemSizeFunction),
164     mBottomMarginFunction(bottomMarginFunction),
165     mColumnPositionFunction(columnPositionFunction),
166     mHeightScale(heightScale),
167     mDepthScale(depthScale)
168   {
169   }
170
171   Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
172   {
173     Vector3 itemSize = mItemSizeFunction(mNumberOfColumns, layoutSize.width);
174
175     float rowLayoutPositon = layoutPosition - static_cast<float>(mColumnNumber);
176
177     return Vector3( -mColumnPositionFunction(mNumberOfColumns, mColumnNumber, itemSize, layoutSize.width),
178                     -(rowLayoutPositon*mHeightScale + layoutSize.height*0.5f - mBottomMarginFunction(layoutSize.height) - itemSize.height * 0.5f),
179                     -rowLayoutPositon*mDepthScale );
180   }
181
182   unsigned int mNumberOfColumns;
183   unsigned int mColumnNumber;
184
185   DepthLayout::ItemSizeFunction       mItemSizeFunction;
186   DepthLayout::BottomMarginFunction   mBottomMarginFunction;
187   DepthLayout::ColumnPositionFunction mColumnPositionFunction;
188
189   float mHeightScale;
190   float mDepthScale;
191 };
192
193 struct DepthPositionConstraint270
194 {
195   DepthPositionConstraint270(unsigned int numberOfColumns,
196                              unsigned int columnNumber,
197                              DepthLayout::ItemSizeFunction itemSizeFunction,
198                              DepthLayout::BottomMarginFunction bottomMarginFunction,
199                              DepthLayout::ColumnPositionFunction columnPositionFunction,
200                              float heightScale,
201                              float depthScale)
202   : mNumberOfColumns(numberOfColumns),
203     mColumnNumber(columnNumber),
204     mItemSizeFunction(itemSizeFunction),
205     mBottomMarginFunction(bottomMarginFunction),
206     mColumnPositionFunction(columnPositionFunction),
207     mHeightScale(heightScale),
208     mDepthScale(depthScale)
209   {
210   }
211
212   Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
213   {
214     Vector3 itemSize = mItemSizeFunction(mNumberOfColumns, layoutSize.height);
215
216     float rowLayoutPositon = layoutPosition - static_cast<float>(mColumnNumber) + mNumberOfColumns*0.5f;
217
218     return Vector3( -(rowLayoutPositon*mHeightScale + layoutSize.width*0.5f - mBottomMarginFunction(layoutSize.width) - itemSize.height * 0.5f),
219                     mColumnPositionFunction(mNumberOfColumns, mColumnNumber, itemSize, layoutSize.height),
220                     -rowLayoutPositon*mDepthScale );
221   }
222
223   unsigned int mNumberOfColumns;
224   unsigned int mColumnNumber;
225
226   DepthLayout::ItemSizeFunction       mItemSizeFunction;
227   DepthLayout::BottomMarginFunction   mBottomMarginFunction;
228   DepthLayout::ColumnPositionFunction mColumnPositionFunction;
229
230   float mHeightScale;
231   float mDepthScale;
232 };
233
234 struct DepthRotationConstraint0
235 {
236   DepthRotationConstraint0(float angleRadians)
237   : mTiltAngle(angleRadians)
238   {
239   }
240
241   Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
242   {
243     return Quaternion(0.0f, Vector3::ZAXIS) * Quaternion(mTiltAngle, Vector3::XAXIS);
244   }
245
246   float mTiltAngle;
247 };
248
249 struct DepthRotationConstraint90
250 {
251   DepthRotationConstraint90(float angleRadians)
252   : mTiltAngle(angleRadians)
253   {
254   }
255
256   Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
257   {
258     return Quaternion(1.5f * Math::PI, Vector3::ZAXIS) * Quaternion(mTiltAngle, Vector3::XAXIS);
259   }
260
261   float mTiltAngle;
262 };
263
264 struct DepthRotationConstraint180
265 {
266   DepthRotationConstraint180(float angleRadians)
267   : mTiltAngle(angleRadians)
268   {
269   }
270
271   Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
272   {
273     return Quaternion(-Math::PI, Vector3::ZAXIS) * Quaternion(mTiltAngle, Vector3::XAXIS);
274   }
275
276   float mTiltAngle;
277 };
278
279 struct DepthRotationConstraint270
280 {
281   DepthRotationConstraint270(float angleRadians)
282   : mTiltAngle(angleRadians)
283   {
284   }
285
286   Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
287   {
288     return Quaternion(0.5f * Math::PI, Vector3::ZAXIS) * Quaternion(mTiltAngle, Vector3::XAXIS);
289   }
290
291   float mTiltAngle;
292 };
293
294 struct DepthColorConstraint
295 {
296   DepthColorConstraint(unsigned int numberOfColumns, float numberOfRows, unsigned int columnNumber)
297   : mNumberOfColumns(numberOfColumns),
298     mNumberOfRows(numberOfRows),
299     mColumnNumber(columnNumber)
300   {
301   }
302
303   Vector4 operator()(const Vector4& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
304   {
305     float row = (layoutPosition - static_cast<float>(mColumnNumber)) / mNumberOfColumns;
306
307     float darkness(1.0f);
308     float alpha(1.0f);
309
310     if (row < 0.0f)
311     {
312       darkness = alpha = max(0.0f, 1.0f + row);
313     }
314     else
315     {
316       if (row > mNumberOfRows)
317       {
318         darkness = 0.0f;
319       }
320       else
321       {
322         darkness = 1.0f - ( 1.0f * (row / mNumberOfRows) );
323       }
324
325       if (row > (mNumberOfRows-1.0f))
326       {
327         alpha = max(0.0f, 1.0f - (row-(mNumberOfRows-1.0f)));
328       }
329     }
330
331     return Vector4( darkness, darkness, darkness, current.a * alpha );
332   }
333
334   unsigned int mNumberOfColumns;
335   float mNumberOfRows;
336   unsigned int mColumnNumber;
337 };
338
339 struct DepthVisibilityConstraint
340 {
341   DepthVisibilityConstraint(unsigned int numberOfColumns, float numberOfRows, unsigned int columnNumber)
342   : mNumberOfColumns(numberOfColumns),
343     mNumberOfRows(numberOfRows),
344     mColumnNumber(columnNumber)
345   {
346   }
347
348   bool operator()(const bool& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
349   {
350     float row = (layoutPosition - static_cast<float>(mColumnNumber)) / mNumberOfColumns;
351     return (row > -1.0f) && (row < mNumberOfRows);
352   }
353
354   unsigned int mNumberOfColumns;
355   float mNumberOfRows;
356   unsigned int mColumnNumber;
357 };
358
359 } // unnamed namespace
360
361 namespace Dali
362 {
363
364 namespace Toolkit
365 {
366
367 struct PositionConstraintSet
368 {
369   ItemLayout::Vector3Function mOrientation0;
370   ItemLayout::Vector3Function mOrientation90;
371   ItemLayout::Vector3Function mOrientation180;
372   ItemLayout::Vector3Function mOrientation270;
373 };
374
375 struct DepthLayout::Impl
376 {
377   Impl()
378   : mNumberOfColumns(DEFAULT_NUMBER_OF_COLUMNS),
379     mNumberOfRows(DEFAULT_NUMBER_OF_ROWS),
380     mRowSpacing(DEFAULT_ROW_SPACING),
381     mTiltAngle(DEFAULT_TILT_ANGLE),
382     mItemTiltAngle(DEFAULT_ITEM_TILT_ANGLE),
383     mScrollSpeedFactor(DEFAULT_SCROLL_SPEED_FACTOR),
384     mMaximumSwipeSpeed(DEFAULT_MAXIMUM_SWIPE_SPEED),
385     mItemFlickAnimationDuration(DEFAULT_ITEM_FLICK_ANIMATION_DURATION),
386     mItemSizeFunction(GetItemSizeDefaultFunction),
387     mBottomMarginFunction(GetBottomMarginDefaultFunction),
388     mColumnPositionFunction(GetColumnPositionDefaultFunction())
389   {
390   }
391
392   unsigned int mNumberOfColumns;
393   unsigned int mNumberOfRows;
394
395   float mRowSpacing;
396
397   Radian mTiltAngle;
398   Radian mItemTiltAngle;
399
400   float mScrollSpeedFactor;
401   float mMaximumSwipeSpeed;
402   float mItemFlickAnimationDuration;
403
404   ItemSizeFunction        mItemSizeFunction;
405   BottomMarginFunction    mBottomMarginFunction;
406   ColumnPositionFunction  mColumnPositionFunction;
407 };
408
409 DepthLayoutPtr DepthLayout::New()
410 {
411   return DepthLayoutPtr(new DepthLayout());
412 }
413
414 DepthLayout::~DepthLayout()
415 {
416   delete mImpl;
417 }
418
419 void DepthLayout::SetNumberOfColumns(unsigned int columns)
420 {
421   mImpl->mNumberOfColumns = columns;
422 }
423
424 unsigned int DepthLayout::GetNumberOfColumns() const
425 {
426   return mImpl->mNumberOfColumns;
427 }
428
429 void DepthLayout::SetNumberOfRows(unsigned int rows)
430 {
431   mImpl->mNumberOfRows = rows;
432 }
433
434 unsigned int DepthLayout::GetNumberOfRows() const
435 {
436   return mImpl->mNumberOfRows;
437 }
438
439 void DepthLayout::SetRowSpacing(float spacing)
440 {
441   mImpl->mRowSpacing = spacing;
442 }
443
444 float DepthLayout::GetRowSpacing() const
445 {
446   return mImpl->mRowSpacing;
447 }
448
449 void DepthLayout::SetTiltAngle(Degree angle)
450 {
451   mImpl->mTiltAngle = Degree( Clamp<float>(angle, -45.0f, 45.0f) );
452 }
453
454 Degree DepthLayout::GetTiltAngle() const
455 {
456   return mImpl->mTiltAngle;
457 }
458
459 void DepthLayout::SetItemSizeFunction(ItemSizeFunction function)
460 {
461   mImpl->mItemSizeFunction = function;
462 }
463
464 DepthLayout::ItemSizeFunction DepthLayout::GetItemSizeFunction() const
465 {
466   return mImpl->mItemSizeFunction;
467 }
468
469 void DepthLayout::SetBottomMarginFunction(BottomMarginFunction function)
470 {
471   mImpl->mBottomMarginFunction = function;
472 }
473
474 DepthLayout::BottomMarginFunction DepthLayout::GetBottomMarginFunction() const
475 {
476   return mImpl->mBottomMarginFunction;
477 }
478
479 void DepthLayout::SetItemTiltAngle(Degree angle)
480 {
481   mImpl->mItemTiltAngle = angle;
482 }
483
484 Degree DepthLayout::GetItemTiltAngle() const
485 {
486   return mImpl->mItemTiltAngle;
487 }
488
489 void DepthLayout::SetColumnPositionFunction(ColumnPositionFunction function)
490 {
491   mImpl->mColumnPositionFunction = function;
492 }
493
494 DepthLayout::ColumnPositionFunction DepthLayout::GetColumnPositionFunction() const
495 {
496   return mImpl->mColumnPositionFunction;
497 }
498
499 void DepthLayout::SetScrollSpeedFactor(float scrollSpeed)
500 {
501   mImpl->mScrollSpeedFactor = scrollSpeed;
502 }
503
504 void DepthLayout::SetMaximumSwipeSpeed(float speed)
505 {
506   mImpl->mMaximumSwipeSpeed = speed;
507 }
508
509 void DepthLayout::SetItemFlickAnimationDuration(float durationSeconds)
510 {
511   mImpl->mItemFlickAnimationDuration = durationSeconds;
512 }
513
514 float DepthLayout::GetScrollSpeedFactor() const
515 {
516   return mImpl->mScrollSpeedFactor;
517 }
518
519 float DepthLayout::GetMaximumSwipeSpeed() const
520 {
521   return mImpl->mMaximumSwipeSpeed;
522 }
523
524 float DepthLayout::GetItemFlickAnimationDuration() const
525 {
526   return mImpl->mItemFlickAnimationDuration;
527 }
528
529 float DepthLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
530 {
531   return static_cast<float>(mImpl->mNumberOfColumns) - static_cast<float>(numberOfItems);
532 }
533
534 float DepthLayout::GetClosestAnchorPosition(float layoutPosition) const
535 {
536   float rowIndex = static_cast<float>(round(layoutPosition / mImpl->mNumberOfColumns));
537   return rowIndex * static_cast<float>(mImpl->mNumberOfColumns);
538 }
539
540 float DepthLayout::GetItemScrollToPosition(unsigned int itemId) const
541 {
542   float rowIndex = static_cast<float>(itemId / mImpl->mNumberOfColumns);
543   return -rowIndex * static_cast<float>(mImpl->mNumberOfColumns);
544 }
545
546 ItemRange DepthLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
547 {
548   float firstRow = -(firstItemPosition/mImpl->mNumberOfColumns);
549   float lastRow = firstRow + mImpl->mNumberOfRows * 0.5f;
550
551   unsigned int firstItem = static_cast<unsigned int>(max(0.0f, firstRow * mImpl->mNumberOfColumns));
552   unsigned int lastItem  = static_cast<unsigned int>(max(0.0f, lastRow  * mImpl->mNumberOfColumns));
553
554   return ItemRange(firstItem, lastItem+1);
555 }
556
557 unsigned int DepthLayout::GetReserveItemCount(Vector3 layoutSize) const
558 {
559   float itemsWithinLayout = (layoutSize.depth * mImpl->mNumberOfColumns) / (cosf(mImpl->mTiltAngle) * mImpl->mRowSpacing);
560
561   return static_cast<unsigned int>(itemsWithinLayout);
562 }
563
564 bool DepthLayout::GetItemSize(unsigned int itemId, Vector3 layoutSize, Vector3& itemSize) const
565 {
566   // Note: itemId is not checked, since every item has the same size
567
568   itemSize = mImpl->mItemSizeFunction( mImpl->mNumberOfColumns, (IsVertical(mOrientation) ? layoutSize.width : layoutSize.height) );
569   return true;
570 }
571
572 void DepthLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 size, float durationSeconds) const
573 {
574   if(animation)
575   {
576     animation.Resize(actor, size);
577   }
578 }
579
580 bool DepthLayout::GetPositionConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
581 {
582   float heightScale = -sinf(mImpl->mTiltAngle) * mImpl->mRowSpacing;
583   float depthScale  =  cosf(mImpl->mTiltAngle) * mImpl->mRowSpacing;
584
585   if (mOrientation == ControlOrientation::Up)
586   {
587     constraint = DepthPositionConstraint0( mImpl->mNumberOfColumns,
588                                            itemId % mImpl->mNumberOfColumns,
589                                            mImpl->mItemSizeFunction,
590                                            mImpl->mBottomMarginFunction,
591                                            mImpl->mColumnPositionFunction,
592                                            heightScale,
593                                            depthScale );
594   }
595   else if (mOrientation == ControlOrientation::Left)
596   {
597     constraint = DepthPositionConstraint90( mImpl->mNumberOfColumns,
598                                             itemId % mImpl->mNumberOfColumns,
599                                             mImpl->mItemSizeFunction,
600                                             mImpl->mBottomMarginFunction,
601                                             mImpl->mColumnPositionFunction,
602                                             heightScale,
603                                             depthScale );
604   }
605   else if (mOrientation == ControlOrientation::Down)
606   {
607     constraint = DepthPositionConstraint180( mImpl->mNumberOfColumns,
608                                              itemId % mImpl->mNumberOfColumns,
609                                              mImpl->mItemSizeFunction,
610                                              mImpl->mBottomMarginFunction,
611                                              mImpl->mColumnPositionFunction,
612                                              heightScale,
613                                              depthScale );
614   }
615   else // mOrientation == ControlOrientation::Right
616   {
617     constraint = DepthPositionConstraint270( mImpl->mNumberOfColumns,
618                                              itemId % mImpl->mNumberOfColumns,
619                                              mImpl->mItemSizeFunction,
620                                              mImpl->mBottomMarginFunction,
621                                              mImpl->mColumnPositionFunction,
622                                              heightScale,
623                                              depthScale );
624   }
625
626   return true;
627 }
628
629 bool DepthLayout::GetRotationConstraint(unsigned int itemId, ItemLayout::QuaternionFunction& constraint) const
630 {
631   if (mOrientation == ControlOrientation::Up)
632   {
633     constraint = DepthRotationConstraint0(mImpl->mItemTiltAngle);
634   }
635   else if (mOrientation == ControlOrientation::Left)
636   {
637     constraint = DepthRotationConstraint90(mImpl->mItemTiltAngle);
638   }
639   else if (mOrientation == ControlOrientation::Down)
640   {
641     constraint = DepthRotationConstraint180(mImpl->mItemTiltAngle);
642   }
643   else // mOrientation == ControlOrientation::Right
644   {
645     constraint = DepthRotationConstraint270(mImpl->mItemTiltAngle);
646   }
647
648   return true;
649 }
650
651 bool DepthLayout::GetScaleConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
652 {
653   return false; // No scaling
654 }
655
656 bool DepthLayout::GetColorConstraint(unsigned int itemId, ItemLayout::Vector4Function& constraint) const
657 {
658   constraint = DepthColorConstraint(mImpl->mNumberOfColumns, mImpl->mNumberOfRows*0.5f, itemId % mImpl->mNumberOfColumns);
659   return true;
660 }
661
662 bool DepthLayout::GetVisibilityConstraint(unsigned int itemId, ItemLayout::BoolFunction& constraint) const
663 {
664   constraint = DepthVisibilityConstraint(mImpl->mNumberOfColumns, mImpl->mNumberOfRows*0.5f, itemId % mImpl->mNumberOfColumns);
665   return true;
666 }
667
668 Degree DepthLayout::GetScrollDirection() const
669 {
670   Degree scrollDirection(0.0f);
671
672   if (mOrientation == ControlOrientation::Up)
673   {
674     scrollDirection = 180.0f;
675   }
676   else if (mOrientation == ControlOrientation::Left)
677   {
678     scrollDirection = 270.0f;
679   }
680   else if (mOrientation == ControlOrientation::Down)
681   {
682     scrollDirection = 0.0f;
683   }
684   else // mOrientation == ControlOrientation::Right
685   {
686     scrollDirection = 90.0f;
687   }
688
689   return scrollDirection;
690 }
691
692 DepthLayout::DepthLayout()
693 : mImpl(NULL)
694 {
695   mImpl = new Impl();
696 }
697
698 float DepthLayout::GetClosestOnScreenLayoutPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize)
699 {
700   float scrollTo = currentLayoutPosition;
701   float row = (currentLayoutPosition + itemID - static_cast<float>(itemID % mImpl->mNumberOfColumns)) / mImpl->mNumberOfColumns;
702
703   // Check whether item is not within viewable area
704   if(row <= -1.0f)
705   {
706     scrollTo = GetItemScrollToPosition(itemID);
707   }
708   else if(row > mImpl->mNumberOfRows * 0.5f - 1.0f)
709   {
710     scrollTo = GetItemScrollToPosition(itemID) + (mImpl->mNumberOfRows - 1.0f) * 0.5f * mImpl->mNumberOfColumns;
711   }
712
713   return scrollTo;
714 }
715
716 int DepthLayout::GetNextFocusItemID(int itemID, int maxItems, Dali::Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
717 {
718   switch( direction )
719   {
720     case Control::Left:
721     {
722       itemID--;
723       if( itemID < 0 )
724       {
725         itemID = loopEnabled ? maxItems - 1 : 0;
726       }
727       break;
728     }
729     case Control::Up:
730     {
731       itemID += mImpl->mNumberOfColumns;
732       if( itemID >= maxItems )
733       {
734         itemID = loopEnabled ? 0 : itemID - mImpl->mNumberOfColumns;
735       }
736       break;
737     }
738     case Control::Right:
739     {
740       itemID++;
741       if( itemID >= maxItems )
742       {
743         itemID = loopEnabled ? 0 : maxItems - 1;
744       }
745       break;
746     }
747     case Control::Down:
748     {
749       itemID -= mImpl->mNumberOfColumns;
750       if( itemID < 0 )
751       {
752         itemID = loopEnabled ? itemID + maxItems : itemID + mImpl->mNumberOfColumns;
753       }
754       break;
755     }
756   }
757   return itemID;
758 }
759
760 } // namespace Toolkit
761
762 } // namespace Dali