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