Updated all cpp files to new format
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scrollable / item-view / depth-layout.cpp
1 /*
2  * Copyright (c) 2021 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/internal/controls/scrollable/item-view/depth-layout.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/animation/animation.h>
23 #include <dali/public-api/animation/constraint.h>
24 #include <algorithm>
25
26 // INTERNAL INCLUDES
27 #include <dali-toolkit/public-api/controls/scrollable/item-view/default-item-layout-property.h>
28 #include <dali-toolkit/public-api/controls/scrollable/item-view/item-view.h>
29
30 using namespace Dali;
31 using namespace Dali::Toolkit;
32
33 namespace // unnamed namespace
34 {
35 const unsigned int DEFAULT_NUMBER_OF_COLUMNS    = 3;
36 const float        DEFAULT_NUMBER_OF_ROWS       = 26.0f;
37 const float        DEFAULT_ROW_SPACING          = 55.0f;
38 const float        DEFAULT_BOTTOM_MARGIN_FACTOR = 0.2f;
39 const Radian       DEFAULT_TILT_ANGLE(Math::PI * 0.15f);
40 const Radian       DEFAULT_ITEM_TILT_ANGLE(-Math::PI * 0.025f);
41 const float        DEFAULT_SCROLL_SPEED_FACTOR           = 0.02f;
42 const float        DEFAULT_MAXIMUM_SWIPE_SPEED           = 50.0f;
43 const float        DEFAULT_ITEM_FLICK_ANIMATION_DURATION = 0.03f;
44
45 inline float GetColumnPosition(unsigned int numberOfColumns, unsigned int columnNumber, const Vector3& itemSize, float layoutWidth)
46 {
47   // Share the available space between margins & column spacings
48   float availableSpace = std::max(0.0f, (layoutWidth - itemSize.width * numberOfColumns));
49
50   float leftMargin = availableSpace / numberOfColumns * 0.5f;
51
52   float columnPosition = leftMargin + itemSize.width * 0.5f + columnNumber * (itemSize.width + availableSpace / numberOfColumns);
53
54   return columnPosition - layoutWidth * 0.5f;
55 }
56
57 struct DepthPositionConstraint
58 {
59   DepthPositionConstraint(unsigned int   itemId,
60                           unsigned int   numberOfColumns,
61                           unsigned int   columnNumber,
62                           const Vector3& itemSize,
63                           float          heightScale,
64                           float          depthScale)
65   : mItemSize(itemSize),
66     mItemId(itemId),
67     mNumberOfColumns(numberOfColumns),
68     mColumnNumber(columnNumber),
69     mHeightScale(heightScale),
70     mDepthScale(depthScale)
71   {
72   }
73
74   inline void Orientation0(Vector3& current, float layoutPosition, const Vector3& layoutSize)
75   {
76     float rowLayoutPositon = layoutPosition - static_cast<float>(mColumnNumber);
77
78     current.x = GetColumnPosition(mNumberOfColumns, mColumnNumber, mItemSize, layoutSize.width);
79     current.y = rowLayoutPositon * mHeightScale + layoutSize.height * 0.5f - DEFAULT_BOTTOM_MARGIN_FACTOR * layoutSize.height - mItemSize.height * 0.5f;
80     current.z = -rowLayoutPositon * mDepthScale;
81   }
82
83   inline void Orientation90(Vector3& current, float layoutPosition, const Vector3& layoutSize)
84   {
85     float rowLayoutPositon = layoutPosition - static_cast<float>(mColumnNumber) + mNumberOfColumns * 0.5f;
86
87     current.x = rowLayoutPositon * mHeightScale + layoutSize.width * 0.5f - DEFAULT_BOTTOM_MARGIN_FACTOR * layoutSize.width - mItemSize.height * 0.5f;
88     current.y = -GetColumnPosition(mNumberOfColumns, mColumnNumber, mItemSize, layoutSize.height);
89     current.z = -rowLayoutPositon * mDepthScale;
90   }
91
92   inline void Orientation180(Vector3& current, float layoutPosition, const Vector3& layoutSize)
93   {
94     float rowLayoutPositon = layoutPosition - static_cast<float>(mColumnNumber);
95
96     current.x = -GetColumnPosition(mNumberOfColumns, mColumnNumber, mItemSize, layoutSize.width);
97     current.y = -(rowLayoutPositon * mHeightScale + layoutSize.height * 0.5f - DEFAULT_BOTTOM_MARGIN_FACTOR * layoutSize.height - mItemSize.height * 0.5f);
98     current.z = -rowLayoutPositon * mDepthScale;
99   }
100
101   inline void Orientation270(Vector3& current, float layoutPosition, const Vector3& layoutSize)
102   {
103     float rowLayoutPositon = layoutPosition - static_cast<float>(mColumnNumber) + mNumberOfColumns * 0.5f;
104
105     current.x = -(rowLayoutPositon * mHeightScale + layoutSize.width * 0.5f - DEFAULT_BOTTOM_MARGIN_FACTOR * layoutSize.width - mItemSize.height * 0.5f);
106     current.y = GetColumnPosition(mNumberOfColumns, mColumnNumber, mItemSize, layoutSize.height);
107     current.z = -rowLayoutPositon * mDepthScale;
108   }
109
110   void Orientation0(Vector3& current, const PropertyInputContainer& inputs)
111   {
112     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
113     const Vector3& layoutSize     = inputs[1]->GetVector3();
114     Orientation0(current, layoutPosition, layoutSize);
115   }
116
117   void Orientation90(Vector3& current, const PropertyInputContainer& inputs)
118   {
119     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
120     const Vector3& layoutSize     = inputs[1]->GetVector3();
121     Orientation90(current, layoutPosition, layoutSize);
122   }
123
124   void Orientation180(Vector3& current, const PropertyInputContainer& inputs)
125   {
126     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
127     const Vector3& layoutSize     = inputs[1]->GetVector3();
128     Orientation180(current, layoutPosition, layoutSize);
129   }
130
131   void Orientation270(Vector3& current, const PropertyInputContainer& inputs)
132   {
133     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
134     const Vector3& layoutSize     = inputs[1]->GetVector3();
135     Orientation270(current, layoutPosition, layoutSize);
136   }
137
138   Vector3      mItemSize;
139   unsigned int mItemId;
140   unsigned int mNumberOfColumns;
141   unsigned int mColumnNumber;
142   float        mHeightScale;
143   float        mDepthScale;
144 };
145
146 struct DepthRotationConstraint
147 {
148   DepthRotationConstraint(Radian angleRadians, ControlOrientation::Type orientation)
149   : mTiltAngle(angleRadians),
150     mMultiplier(0.0f)
151   {
152     if(orientation == ControlOrientation::Up)
153     {
154       mMultiplier = 0.0f;
155     }
156     else if(orientation == ControlOrientation::Left)
157     {
158       mMultiplier = 1.5f;
159     }
160     else if(orientation == ControlOrientation::Down)
161     {
162       mMultiplier = -1.0f;
163     }
164     else // orientation == ControlOrientation::Right
165     {
166       mMultiplier = 0.5f;
167     }
168   }
169
170   void operator()(Quaternion& current, const PropertyInputContainer& /* inputs */)
171   {
172     current = Quaternion(Radian(mMultiplier * Math::PI), Vector3::ZAXIS) * Quaternion(mTiltAngle, Vector3::XAXIS);
173   }
174
175   Radian mTiltAngle;
176   float  mMultiplier;
177 };
178
179 struct DepthColorConstraint
180 {
181   DepthColorConstraint(unsigned int itemId, unsigned int numberOfColumns, float numberOfRows, unsigned int columnNumber)
182   : mItemId(itemId),
183     mNumberOfColumns(numberOfColumns),
184     mNumberOfRows(numberOfRows),
185     mColumnNumber(columnNumber)
186   {
187   }
188
189   void operator()(Vector4& current, const Dali::PropertyInputContainer& inputs)
190   {
191     float layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
192     float row            = (layoutPosition - static_cast<float>(mColumnNumber)) / mNumberOfColumns;
193
194     float darkness(1.0f);
195     float alpha(1.0f);
196
197     if(row < 0.0f)
198     {
199       darkness = alpha = std::max(0.0f, 1.0f + row);
200     }
201     else
202     {
203       if(row > mNumberOfRows)
204       {
205         darkness = 0.0f;
206       }
207       else
208       {
209         darkness = 1.0f - (1.0f * (row / mNumberOfRows));
210       }
211
212       if(row > (mNumberOfRows - 1.0f))
213       {
214         alpha = std::max(0.0f, 1.0f - (row - (mNumberOfRows - 1.0f)));
215       }
216     }
217
218     current.r = current.g = current.b = darkness;
219     current.a *= alpha;
220   }
221
222   unsigned int mItemId;
223   unsigned int mNumberOfColumns;
224   float        mNumberOfRows;
225   unsigned int mColumnNumber;
226 };
227
228 struct DepthVisibilityConstraint
229 {
230   DepthVisibilityConstraint(unsigned int itemId, unsigned int numberOfColumns, float numberOfRows, unsigned int columnNumber)
231   : mItemId(itemId),
232     mNumberOfColumns(numberOfColumns),
233     mNumberOfRows(numberOfRows),
234     mColumnNumber(columnNumber)
235   {
236   }
237
238   void operator()(bool& current, const Dali::PropertyInputContainer& inputs)
239   {
240     float layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
241     float row            = (layoutPosition - static_cast<float>(mColumnNumber)) / mNumberOfColumns;
242
243     current = (row > -1.0f) && (row < mNumberOfRows);
244   }
245
246   unsigned int mItemId;
247   unsigned int mNumberOfColumns;
248   float        mNumberOfRows;
249   unsigned int mColumnNumber;
250 };
251
252 } // unnamed namespace
253
254 namespace Dali
255 {
256 namespace Toolkit
257 {
258 namespace Internal
259 {
260 struct DepthLayout::Impl
261 {
262   Impl()
263   : mNumberOfColumns(DEFAULT_NUMBER_OF_COLUMNS),
264     mNumberOfRows(DEFAULT_NUMBER_OF_ROWS),
265     mRowSpacing(DEFAULT_ROW_SPACING),
266     mTiltAngle(DEFAULT_TILT_ANGLE),
267     mItemTiltAngle(DEFAULT_ITEM_TILT_ANGLE),
268     mScrollSpeedFactor(DEFAULT_SCROLL_SPEED_FACTOR),
269     mMaximumSwipeSpeed(DEFAULT_MAXIMUM_SWIPE_SPEED),
270     mItemFlickAnimationDuration(DEFAULT_ITEM_FLICK_ANIMATION_DURATION)
271   {
272   }
273
274   unsigned int mNumberOfColumns;
275   unsigned int mNumberOfRows;
276
277   float mRowSpacing;
278
279   Radian mTiltAngle;
280   Radian mItemTiltAngle;
281
282   float mScrollSpeedFactor;
283   float mMaximumSwipeSpeed;
284   float mItemFlickAnimationDuration;
285 };
286
287 DepthLayoutPtr DepthLayout::New()
288 {
289   return DepthLayoutPtr(new DepthLayout());
290 }
291
292 DepthLayout::~DepthLayout()
293 {
294   delete mImpl;
295 }
296
297 void DepthLayout::SetNumberOfColumns(unsigned int columns)
298 {
299   mImpl->mNumberOfColumns = columns;
300 }
301
302 unsigned int DepthLayout::GetNumberOfColumns() const
303 {
304   return mImpl->mNumberOfColumns;
305 }
306
307 void DepthLayout::SetNumberOfRows(unsigned int rows)
308 {
309   mImpl->mNumberOfRows = rows;
310 }
311
312 unsigned int DepthLayout::GetNumberOfRows() const
313 {
314   return mImpl->mNumberOfRows;
315 }
316
317 void DepthLayout::SetRowSpacing(float spacing)
318 {
319   mImpl->mRowSpacing = spacing;
320 }
321
322 float DepthLayout::GetRowSpacing() const
323 {
324   return mImpl->mRowSpacing;
325 }
326
327 void DepthLayout::SetTiltAngle(Degree angle)
328 {
329   mImpl->mTiltAngle = Degree(Clamp(angle, -45.0f, 45.0f));
330 }
331
332 Degree DepthLayout::GetTiltAngle() const
333 {
334   return Degree(mImpl->mTiltAngle);
335 }
336
337 void DepthLayout::SetItemTiltAngle(Degree angle)
338 {
339   mImpl->mItemTiltAngle = angle;
340 }
341
342 Degree DepthLayout::GetItemTiltAngle() const
343 {
344   return Degree(mImpl->mItemTiltAngle);
345 }
346
347 void DepthLayout::SetScrollSpeedFactor(float scrollSpeed)
348 {
349   mImpl->mScrollSpeedFactor = scrollSpeed;
350 }
351
352 void DepthLayout::SetMaximumSwipeSpeed(float speed)
353 {
354   mImpl->mMaximumSwipeSpeed = speed;
355 }
356
357 void DepthLayout::SetItemFlickAnimationDuration(float durationSeconds)
358 {
359   mImpl->mItemFlickAnimationDuration = durationSeconds;
360 }
361
362 float DepthLayout::GetScrollSpeedFactor() const
363 {
364   return mImpl->mScrollSpeedFactor;
365 }
366
367 float DepthLayout::GetMaximumSwipeSpeed() const
368 {
369   return mImpl->mMaximumSwipeSpeed;
370 }
371
372 float DepthLayout::GetItemFlickAnimationDuration() const
373 {
374   return mImpl->mItemFlickAnimationDuration;
375 }
376
377 float DepthLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
378 {
379   return static_cast<float>(mImpl->mNumberOfColumns) - static_cast<float>(numberOfItems);
380 }
381
382 float DepthLayout::GetClosestAnchorPosition(float layoutPosition) const
383 {
384   float rowIndex = static_cast<float>(round(layoutPosition / mImpl->mNumberOfColumns));
385   return rowIndex * static_cast<float>(mImpl->mNumberOfColumns);
386 }
387
388 float DepthLayout::GetItemScrollToPosition(unsigned int itemId) const
389 {
390   float rowIndex = static_cast<float>(itemId) / mImpl->mNumberOfColumns;
391   return -rowIndex * static_cast<float>(mImpl->mNumberOfColumns);
392 }
393
394 ItemRange DepthLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
395 {
396   float firstRow = -(firstItemPosition / mImpl->mNumberOfColumns);
397   float lastRow  = firstRow + mImpl->mNumberOfRows * 0.5f;
398
399   unsigned int firstItem = static_cast<unsigned int>(std::max(0.0f, firstRow * mImpl->mNumberOfColumns));
400   unsigned int lastItem  = static_cast<unsigned int>(std::max(0.0f, lastRow * mImpl->mNumberOfColumns));
401
402   return ItemRange(firstItem, lastItem + 1);
403 }
404
405 unsigned int DepthLayout::GetReserveItemCount(Vector3 layoutSize) const
406 {
407   float itemsWithinLayout = (layoutSize.depth * mImpl->mNumberOfColumns) / (cosf(mImpl->mTiltAngle) * mImpl->mRowSpacing);
408
409   return static_cast<unsigned int>(itemsWithinLayout);
410 }
411
412 void DepthLayout::GetDefaultItemSize(unsigned int itemId, const Vector3& layoutSize, Vector3& itemSize) const
413 {
414   // 1x1 aspect ratio
415   itemSize.width = itemSize.height = itemSize.depth = (IsVertical(GetOrientation()) ? layoutSize.width : layoutSize.height) / static_cast<float>(mImpl->mNumberOfColumns + 1);
416 }
417
418 Degree DepthLayout::GetScrollDirection() const
419 {
420   Degree                   scrollDirection(0.0f);
421   ControlOrientation::Type orientation = GetOrientation();
422
423   if(orientation == ControlOrientation::Up)
424   {
425     scrollDirection = Degree(180.0f);
426   }
427   else if(orientation == ControlOrientation::Left)
428   {
429     scrollDirection = Degree(270.0f);
430   }
431   else if(orientation == ControlOrientation::Down)
432   {
433     scrollDirection = Degree(0.0f);
434   }
435   else // orientation == ControlOrientation::Right
436   {
437     scrollDirection = Degree(90.0f);
438   }
439
440   return scrollDirection;
441 }
442
443 void DepthLayout::ApplyConstraints(Actor& actor, const int itemId, const Vector3& layoutSize, const Actor& itemViewActor)
444 {
445   Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast(itemViewActor);
446   if(itemView)
447   {
448     Vector3 itemSize;
449     GetItemSize(itemId, layoutSize, itemSize);
450
451     ControlOrientation::Type orientation = GetOrientation();
452
453     // Position constraint
454     Constraint              constraint;
455     DepthPositionConstraint depthPositionStruct(itemId,
456                                                 mImpl->mNumberOfColumns,
457                                                 itemId % mImpl->mNumberOfColumns,
458                                                 itemSize,
459                                                 -sinf(mImpl->mTiltAngle) * mImpl->mRowSpacing,
460                                                 cosf(mImpl->mTiltAngle) * mImpl->mRowSpacing);
461     if(orientation == ControlOrientation::Up)
462     {
463       constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, depthPositionStruct, &DepthPositionConstraint::Orientation0);
464     }
465     else if(orientation == ControlOrientation::Left)
466     {
467       constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, depthPositionStruct, &DepthPositionConstraint::Orientation90);
468     }
469     else if(orientation == ControlOrientation::Down)
470     {
471       constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, depthPositionStruct, &DepthPositionConstraint::Orientation180);
472     }
473     else // orientation == ControlOrientation::Right
474     {
475       constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, depthPositionStruct, &DepthPositionConstraint::Orientation270);
476     }
477     constraint.AddSource(ParentSource(Toolkit::ItemView::Property::LAYOUT_POSITION));
478     constraint.AddSource(ParentSource(Actor::Property::SIZE));
479     constraint.Apply();
480
481     // Rotation constraint
482     constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, DepthRotationConstraint(mImpl->mItemTiltAngle, orientation));
483     constraint.Apply();
484
485     // Color constraint
486     constraint = Constraint::New<Vector4>(actor, Actor::Property::COLOR, DepthColorConstraint(itemId, mImpl->mNumberOfColumns, mImpl->mNumberOfRows * 0.5f, itemId % mImpl->mNumberOfColumns));
487     constraint.AddSource(ParentSource(Toolkit::ItemView::Property::LAYOUT_POSITION));
488     constraint.SetRemoveAction(Dali::Constraint::DISCARD);
489     constraint.Apply();
490
491     // Visibility constraint
492     constraint = Constraint::New<bool>(actor, Actor::Property::VISIBLE, DepthVisibilityConstraint(itemId, mImpl->mNumberOfColumns, mImpl->mNumberOfRows * 0.5f, itemId % mImpl->mNumberOfColumns));
493     constraint.AddSource(ParentSource(Toolkit::ItemView::Property::LAYOUT_POSITION));
494     constraint.SetRemoveAction(Dali::Constraint::DISCARD);
495     constraint.Apply();
496   }
497 }
498
499 void DepthLayout::SetDepthLayoutProperties(const Property::Map& properties)
500 {
501   // Set any properties specified for DepthLayout.
502   for(unsigned int idx = 0, mapCount = properties.Count(); idx < mapCount; ++idx)
503   {
504     KeyValuePair propertyPair = properties.GetKeyValue(idx);
505     switch(DefaultItemLayoutProperty::Property(propertyPair.first.indexKey))
506     {
507       case DefaultItemLayoutProperty::DEPTH_COLUMN_NUMBER:
508       {
509         SetNumberOfColumns(propertyPair.second.Get<int>());
510         break;
511       }
512       case DefaultItemLayoutProperty::DEPTH_ROW_NUMBER:
513       {
514         SetNumberOfRows(propertyPair.second.Get<int>());
515         break;
516       }
517       case DefaultItemLayoutProperty::DEPTH_ROW_SPACING:
518       {
519         SetRowSpacing(propertyPair.second.Get<float>());
520         break;
521       }
522       case DefaultItemLayoutProperty::DEPTH_MAXIMUM_SWIPE_SPEED:
523       {
524         SetMaximumSwipeSpeed(propertyPair.second.Get<float>());
525         break;
526       }
527       case DefaultItemLayoutProperty::DEPTH_SCROLL_SPEED_FACTOR:
528       {
529         SetScrollSpeedFactor(propertyPair.second.Get<float>());
530         break;
531       }
532       case DefaultItemLayoutProperty::DEPTH_TILT_ANGLE:
533       {
534         SetTiltAngle(Degree(Radian(propertyPair.second.Get<float>())));
535         break;
536       }
537       case DefaultItemLayoutProperty::DEPTH_ITEM_TILT_ANGLE:
538       {
539         SetItemTiltAngle(Degree(Radian(propertyPair.second.Get<float>())));
540         break;
541       }
542       case DefaultItemLayoutProperty::DEPTH_ITEM_FLICK_ANIMATION_DURATION:
543       {
544         SetItemFlickAnimationDuration(propertyPair.second.Get<float>());
545         break;
546       }
547       default:
548       {
549         break;
550       }
551     }
552   }
553 }
554
555 Vector3 DepthLayout::GetItemPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize) const
556 {
557   Vector3 itemPosition = Vector3::ZERO;
558
559   const float heightScale = -sinf(mImpl->mTiltAngle) * mImpl->mRowSpacing;
560   const float depthScale  = cosf(mImpl->mTiltAngle) * mImpl->mRowSpacing;
561
562   Vector3 itemSize;
563   GetItemSize(itemID, layoutSize, itemSize);
564   DepthPositionConstraint  positionFunctor = DepthPositionConstraint(itemID,
565                                                                     mImpl->mNumberOfColumns,
566                                                                     itemID % mImpl->mNumberOfColumns,
567                                                                     itemSize,
568                                                                     heightScale,
569                                                                     depthScale);
570   ControlOrientation::Type orientation     = GetOrientation();
571   if(orientation == ControlOrientation::Up)
572   {
573     positionFunctor.Orientation0(itemPosition, currentLayoutPosition + itemID, layoutSize);
574   }
575   else if(orientation == ControlOrientation::Left)
576   {
577     positionFunctor.Orientation90(itemPosition, currentLayoutPosition + itemID, layoutSize);
578   }
579   else if(orientation == ControlOrientation::Down)
580   {
581     positionFunctor.Orientation180(itemPosition, currentLayoutPosition + itemID, layoutSize);
582   }
583   else // orientation == ControlOrientation::Right
584   {
585     positionFunctor.Orientation270(itemPosition, currentLayoutPosition + itemID, layoutSize);
586   }
587
588   return itemPosition;
589 }
590
591 DepthLayout::DepthLayout()
592 : mImpl(NULL)
593 {
594   mImpl = new Impl();
595 }
596
597 float DepthLayout::GetClosestOnScreenLayoutPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize)
598 {
599   float scrollTo = currentLayoutPosition;
600   float row      = (currentLayoutPosition + itemID - static_cast<float>(itemID % mImpl->mNumberOfColumns)) / mImpl->mNumberOfColumns;
601
602   // Check whether item is not within viewable area
603   if(row <= -1.0f)
604   {
605     scrollTo = GetItemScrollToPosition(itemID);
606   }
607   else if(row > mImpl->mNumberOfRows * 0.5f - 1.0f)
608   {
609     scrollTo = GetItemScrollToPosition(itemID) + (mImpl->mNumberOfRows - 1.0f) * 0.5f * mImpl->mNumberOfColumns;
610   }
611
612   return scrollTo;
613 }
614
615 int DepthLayout::GetNextFocusItemID(int itemID, int maxItems, Dali::Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
616 {
617   switch(direction)
618   {
619     case Toolkit::Control::KeyboardFocus::LEFT:
620     {
621       itemID--;
622       if(itemID < 0)
623       {
624         itemID = loopEnabled ? maxItems - 1 : 0;
625       }
626       break;
627     }
628     case Toolkit::Control::KeyboardFocus::UP:
629     {
630       itemID += mImpl->mNumberOfColumns;
631       if(itemID >= maxItems)
632       {
633         itemID = loopEnabled ? 0 : itemID - mImpl->mNumberOfColumns;
634       }
635       break;
636     }
637     case Toolkit::Control::KeyboardFocus::RIGHT:
638     {
639       itemID++;
640       if(itemID >= maxItems)
641       {
642         itemID = loopEnabled ? 0 : maxItems - 1;
643       }
644       break;
645     }
646     case Toolkit::Control::KeyboardFocus::DOWN:
647     {
648       itemID -= mImpl->mNumberOfColumns;
649       if(itemID < 0)
650       {
651         itemID = loopEnabled ? itemID + maxItems : itemID + mImpl->mNumberOfColumns;
652       }
653       break;
654     }
655     default:
656     {
657       break;
658     }
659   }
660   return itemID;
661 }
662
663 } // namespace Internal
664
665 } // namespace Toolkit
666
667 } // namespace Dali