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