Merge "Update keyboard focus direction enum for Control" into tizen
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scrollable / item-view / depth-layout.cpp
1 /*
2  * Copyright (c) 2015 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 <algorithm>
23 #include <dali/public-api/animation/animation.h>
24 #include <dali/public-api/animation/constraint.h>
25
26 // INTERNAL INCLUDES
27 #include <dali-toolkit/public-api/controls/scrollable/item-view/item-view.h>
28
29 using namespace Dali;
30 using namespace Dali::Toolkit;
31
32 namespace // unnamed namespace
33 {
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
257 namespace Toolkit
258 {
259
260 namespace Internal
261 {
262
263 struct DepthLayout::Impl
264 {
265   Impl()
266   : mNumberOfColumns(DEFAULT_NUMBER_OF_COLUMNS),
267     mNumberOfRows(DEFAULT_NUMBER_OF_ROWS),
268     mRowSpacing(DEFAULT_ROW_SPACING),
269     mTiltAngle(DEFAULT_TILT_ANGLE),
270     mItemTiltAngle(DEFAULT_ITEM_TILT_ANGLE),
271     mScrollSpeedFactor(DEFAULT_SCROLL_SPEED_FACTOR),
272     mMaximumSwipeSpeed(DEFAULT_MAXIMUM_SWIPE_SPEED),
273     mItemFlickAnimationDuration(DEFAULT_ITEM_FLICK_ANIMATION_DURATION)
274   {
275   }
276
277   unsigned int mNumberOfColumns;
278   unsigned int mNumberOfRows;
279
280   float mRowSpacing;
281
282   Radian mTiltAngle;
283   Radian mItemTiltAngle;
284
285   float mScrollSpeedFactor;
286   float mMaximumSwipeSpeed;
287   float mItemFlickAnimationDuration;
288 };
289
290 DepthLayoutPtr DepthLayout::New()
291 {
292   return DepthLayoutPtr(new DepthLayout());
293 }
294
295 DepthLayout::~DepthLayout()
296 {
297   delete mImpl;
298 }
299
300 void DepthLayout::SetNumberOfColumns(unsigned int columns)
301 {
302   mImpl->mNumberOfColumns = columns;
303 }
304
305 unsigned int DepthLayout::GetNumberOfColumns() const
306 {
307   return mImpl->mNumberOfColumns;
308 }
309
310 void DepthLayout::SetNumberOfRows(unsigned int rows)
311 {
312   mImpl->mNumberOfRows = rows;
313 }
314
315 unsigned int DepthLayout::GetNumberOfRows() const
316 {
317   return mImpl->mNumberOfRows;
318 }
319
320 void DepthLayout::SetRowSpacing(float spacing)
321 {
322   mImpl->mRowSpacing = spacing;
323 }
324
325 float DepthLayout::GetRowSpacing() const
326 {
327   return mImpl->mRowSpacing;
328 }
329
330 void DepthLayout::SetTiltAngle(Degree angle)
331 {
332   mImpl->mTiltAngle = Degree( Clamp( angle, -45.0f, 45.0f ) );
333 }
334
335 Degree DepthLayout::GetTiltAngle() const
336 {
337   return Degree( mImpl->mTiltAngle );
338 }
339
340 void DepthLayout::SetItemTiltAngle(Degree angle)
341 {
342   mImpl->mItemTiltAngle = angle;
343 }
344
345 Degree DepthLayout::GetItemTiltAngle() const
346 {
347   return Degree( mImpl->mItemTiltAngle );
348 }
349
350 void DepthLayout::SetScrollSpeedFactor(float scrollSpeed)
351 {
352   mImpl->mScrollSpeedFactor = scrollSpeed;
353 }
354
355 void DepthLayout::SetMaximumSwipeSpeed(float speed)
356 {
357   mImpl->mMaximumSwipeSpeed = speed;
358 }
359
360 void DepthLayout::SetItemFlickAnimationDuration(float durationSeconds)
361 {
362   mImpl->mItemFlickAnimationDuration = durationSeconds;
363 }
364
365 float DepthLayout::GetScrollSpeedFactor() const
366 {
367   return mImpl->mScrollSpeedFactor;
368 }
369
370 float DepthLayout::GetMaximumSwipeSpeed() const
371 {
372   return mImpl->mMaximumSwipeSpeed;
373 }
374
375 float DepthLayout::GetItemFlickAnimationDuration() const
376 {
377   return mImpl->mItemFlickAnimationDuration;
378 }
379
380 float DepthLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
381 {
382   return static_cast<float>(mImpl->mNumberOfColumns) - static_cast<float>(numberOfItems);
383 }
384
385 float DepthLayout::GetClosestAnchorPosition(float layoutPosition) const
386 {
387   float rowIndex = static_cast<float>(round(layoutPosition / mImpl->mNumberOfColumns));
388   return rowIndex * static_cast<float>(mImpl->mNumberOfColumns);
389 }
390
391 float DepthLayout::GetItemScrollToPosition(unsigned int itemId) const
392 {
393   float rowIndex = static_cast<float>(itemId / mImpl->mNumberOfColumns);
394   return -rowIndex * static_cast<float>(mImpl->mNumberOfColumns);
395 }
396
397 ItemRange DepthLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
398 {
399   float firstRow = -(firstItemPosition/mImpl->mNumberOfColumns);
400   float lastRow = firstRow + mImpl->mNumberOfRows * 0.5f;
401
402   unsigned int firstItem = static_cast<unsigned int>(std::max(0.0f, firstRow * mImpl->mNumberOfColumns));
403   unsigned int lastItem  = static_cast<unsigned int>(std::max(0.0f, lastRow  * mImpl->mNumberOfColumns));
404
405   return ItemRange(firstItem, lastItem+1);
406 }
407
408 unsigned int DepthLayout::GetReserveItemCount(Vector3 layoutSize) const
409 {
410   float itemsWithinLayout = (layoutSize.depth * mImpl->mNumberOfColumns) / (cosf(mImpl->mTiltAngle) * mImpl->mRowSpacing);
411
412   return static_cast<unsigned int>(itemsWithinLayout);
413 }
414
415 void DepthLayout::GetDefaultItemSize( unsigned int itemId, const Vector3& layoutSize, Vector3& itemSize ) const
416 {
417   // 1x1 aspect ratio
418   itemSize.width = itemSize.height = itemSize.depth = ( IsVertical( GetOrientation() ) ? layoutSize.width : layoutSize.height ) / static_cast<float>( mImpl->mNumberOfColumns + 1 );
419 }
420
421 void DepthLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 size, float durationSeconds) const
422 {
423   if(animation)
424   {
425     animation.AnimateTo( Property( actor, Actor::Property::SIZE ), size );
426   }
427 }
428
429 Degree DepthLayout::GetScrollDirection() const
430 {
431   Degree scrollDirection(0.0f);
432   ControlOrientation::Type orientation = GetOrientation();
433
434   if ( orientation == ControlOrientation::Up )
435   {
436     scrollDirection = Degree( 180.0f );
437   }
438   else if ( orientation == ControlOrientation::Left )
439   {
440     scrollDirection = Degree( 270.0f );
441   }
442   else if ( orientation == ControlOrientation::Down )
443   {
444     scrollDirection = Degree( 0.0f );
445   }
446   else // orientation == ControlOrientation::Right
447   {
448     scrollDirection = Degree( 90.0f );
449   }
450
451   return scrollDirection;
452 }
453
454 void DepthLayout::ApplyConstraints( Actor& actor, const int itemId, const Vector3& layoutSize, const Actor& itemViewActor )
455 {
456   Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast( itemViewActor );
457   if( itemView )
458   {
459     Vector3 itemSize;
460     GetItemSize( itemId, layoutSize, itemSize );
461
462     ControlOrientation::Type orientation = GetOrientation();
463
464     // Position constraint
465     Constraint constraint;
466     DepthPositionConstraint depthPositionStruct( itemId,
467                                                  mImpl->mNumberOfColumns,
468                                                  itemId % mImpl->mNumberOfColumns,
469                                                  itemSize,
470                                                  -sinf( mImpl->mTiltAngle ) * mImpl->mRowSpacing,
471                                                  cosf( mImpl->mTiltAngle ) * mImpl->mRowSpacing );
472     if ( orientation == ControlOrientation::Up )
473     {
474       constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, depthPositionStruct, &DepthPositionConstraint::Orientation0 );
475     }
476     else if ( orientation == ControlOrientation::Left )
477     {
478       constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, depthPositionStruct, &DepthPositionConstraint::Orientation90 );
479     }
480     else if ( orientation == ControlOrientation::Down )
481     {
482       constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, depthPositionStruct, &DepthPositionConstraint::Orientation180 );
483     }
484     else // orientation == ControlOrientation::Right
485     {
486       constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, depthPositionStruct, &DepthPositionConstraint::Orientation270 );
487     }
488     constraint.AddSource( ParentSource( Toolkit::ItemView::Property::LAYOUT_POSITION ) );
489     constraint.AddSource( ParentSource( Actor::Property::SIZE ) );
490     constraint.Apply();
491
492     // Rotation constraint
493     constraint = Constraint::New< Quaternion >( actor, Actor::Property::ORIENTATION, DepthRotationConstraint( mImpl->mItemTiltAngle, orientation ) );
494     constraint.Apply();
495
496     // Color constraint
497     constraint = Constraint::New< Vector4 >( actor, Actor::Property::COLOR, DepthColorConstraint( itemId, mImpl->mNumberOfColumns, mImpl->mNumberOfRows*0.5f, itemId % mImpl->mNumberOfColumns ) );
498     constraint.AddSource( ParentSource( Toolkit::ItemView::Property::LAYOUT_POSITION ) );
499     constraint.SetRemoveAction( Dali::Constraint::Discard );
500     constraint.Apply();
501
502     // Visibility constraint
503     constraint = Constraint::New< bool >( actor, Actor::Property::VISIBLE, DepthVisibilityConstraint( itemId, mImpl->mNumberOfColumns, mImpl->mNumberOfRows*0.5f, itemId % mImpl->mNumberOfColumns ) );
504     constraint.AddSource( ParentSource( Toolkit::ItemView::Property::LAYOUT_POSITION ) );
505     constraint.SetRemoveAction( Dali::Constraint::Discard );
506     constraint.Apply();
507   }
508 }
509
510 Vector3 DepthLayout::GetItemPosition( int itemID, float currentLayoutPosition, const Vector3& layoutSize ) const
511 {
512   Vector3 itemPosition = Vector3::ZERO;
513
514   const float heightScale = -sinf( mImpl->mTiltAngle ) * mImpl->mRowSpacing;
515   const float depthScale  =  cosf( mImpl->mTiltAngle ) * mImpl->mRowSpacing;
516
517   Vector3 itemSize;
518   GetItemSize( itemID, layoutSize, itemSize );
519   DepthPositionConstraint positionFunctor = DepthPositionConstraint( itemID,
520                                                                      mImpl->mNumberOfColumns,
521                                                                      itemID % mImpl->mNumberOfColumns,
522                                                                      itemSize,
523                                                                      heightScale,
524                                                                      depthScale );
525   ControlOrientation::Type orientation = GetOrientation();
526   if ( orientation == ControlOrientation::Up )
527   {
528     positionFunctor.Orientation0( itemPosition, currentLayoutPosition + itemID, layoutSize );
529   }
530   else if ( orientation == ControlOrientation::Left )
531   {
532     positionFunctor.Orientation90( itemPosition, currentLayoutPosition + itemID, layoutSize );
533   }
534   else if ( orientation == ControlOrientation::Down )
535   {
536     positionFunctor.Orientation180( itemPosition, currentLayoutPosition + itemID, layoutSize );
537   }
538   else // orientation == ControlOrientation::Right
539   {
540     positionFunctor.Orientation270( itemPosition, currentLayoutPosition + itemID, layoutSize );
541   }
542
543   return itemPosition;
544 }
545
546 DepthLayout::DepthLayout()
547 : mImpl(NULL)
548 {
549   mImpl = new Impl();
550 }
551
552 float DepthLayout::GetClosestOnScreenLayoutPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize)
553 {
554   float scrollTo = currentLayoutPosition;
555   float row = (currentLayoutPosition + itemID - static_cast<float>(itemID % mImpl->mNumberOfColumns)) / mImpl->mNumberOfColumns;
556
557   // Check whether item is not within viewable area
558   if(row <= -1.0f)
559   {
560     scrollTo = GetItemScrollToPosition(itemID);
561   }
562   else if(row > mImpl->mNumberOfRows * 0.5f - 1.0f)
563   {
564     scrollTo = GetItemScrollToPosition(itemID) + (mImpl->mNumberOfRows - 1.0f) * 0.5f * mImpl->mNumberOfColumns;
565   }
566
567   return scrollTo;
568 }
569
570 int DepthLayout::GetNextFocusItemID(int itemID, int maxItems, Dali::Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
571 {
572   switch( direction )
573   {
574     case Toolkit::Control::KeyboardFocus::LEFT:
575     {
576       itemID--;
577       if( itemID < 0 )
578       {
579         itemID = loopEnabled ? maxItems - 1 : 0;
580       }
581       break;
582     }
583     case Toolkit::Control::KeyboardFocus::UP:
584     {
585       itemID += mImpl->mNumberOfColumns;
586       if( itemID >= maxItems )
587       {
588         itemID = loopEnabled ? 0 : itemID - mImpl->mNumberOfColumns;
589       }
590       break;
591     }
592     case Toolkit::Control::KeyboardFocus::RIGHT:
593     {
594       itemID++;
595       if( itemID >= maxItems )
596       {
597         itemID = loopEnabled ? 0 : maxItems - 1;
598       }
599       break;
600     }
601     case Toolkit::Control::KeyboardFocus::DOWN:
602     {
603       itemID -= mImpl->mNumberOfColumns;
604       if( itemID < 0 )
605       {
606         itemID = loopEnabled ? itemID + maxItems : itemID + mImpl->mNumberOfColumns;
607       }
608       break;
609     }
610   }
611   return itemID;
612 }
613
614 } // namespace Internal
615
616 } // namespace Toolkit
617
618 } // namespace Dali