Updated all cpp files to new format
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scrollable / item-view / spiral-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/spiral-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 float DEFAULT_ITEMS_PER_SPIRAL_TURN = 9.5f;
36 const float DEFAULT_ITEM_SPACING_RADIANS  = Math::PI * 2.0f / DEFAULT_ITEMS_PER_SPIRAL_TURN;
37
38 const float DEFAULT_REVOLUTION_DISTANCE = 190.0f;
39 const float DEFAULT_ITEM_DESCENT        = DEFAULT_REVOLUTION_DISTANCE / DEFAULT_ITEMS_PER_SPIRAL_TURN;
40
41 const float DEFAULT_TOP_ITEM_ALIGNMENT = -0.125f;
42
43 const float DEFAULT_SCROLL_SPEED_FACTOR           = 0.01f;
44 const float DEFAULT_MAXIMUM_SWIPE_SPEED           = 30.0f;
45 const float DEFAULT_ITEM_FLICK_ANIMATION_DURATION = 0.1f;
46
47 float GetDefaultSpiralRadiusFunction(const Vector3& layoutSize)
48 {
49   return layoutSize.width * 0.4f;
50 }
51
52 struct SpiralPositionConstraint
53 {
54   SpiralPositionConstraint(unsigned int itemId, float spiralRadius, float itemSpacingRadians, float itemDescent, float topItemAlignment)
55   : mItemId(itemId),
56     mSpiralRadius(spiralRadius),
57     mItemSpacingRadians(itemSpacingRadians),
58     mItemDescent(itemDescent),
59     mTopItemAlignment(topItemAlignment)
60   {
61   }
62
63   inline void OrientationUp(Vector3& current, float layoutPosition, const Vector3& layoutSize)
64   {
65     float angle = -Math::PI * 0.5f + mItemSpacingRadians * layoutPosition;
66
67     current.x = -mSpiralRadius * cosf(angle);
68     current.y = (mItemDescent * layoutPosition) + layoutSize.height * mTopItemAlignment;
69     current.z = -mSpiralRadius * sinf(angle);
70   }
71
72   inline void OrientationLeft(Vector3& current, float layoutPosition, const Vector3& layoutSize)
73   {
74     float angle = Math::PI * 0.5f + mItemSpacingRadians * layoutPosition;
75
76     current.x = (mItemDescent * layoutPosition) + layoutSize.width * mTopItemAlignment;
77     current.y = -mSpiralRadius * cosf(angle);
78     current.z = mSpiralRadius * sinf(angle);
79   }
80
81   inline void OrientationDown(Vector3& current, float layoutPosition, const Vector3& layoutSize)
82   {
83     float angle = Math::PI * 0.5f + mItemSpacingRadians * layoutPosition;
84
85     current.x = -mSpiralRadius * cosf(angle);
86     current.y = (-mItemDescent * layoutPosition) - layoutSize.height * mTopItemAlignment;
87     current.z = mSpiralRadius * sinf(angle);
88   }
89
90   inline void OrientationRight(Vector3& current, float layoutPosition, const Vector3& layoutSize)
91   {
92     float angle = -Math::PI * 0.5f + mItemSpacingRadians * layoutPosition;
93
94     current.x = (-mItemDescent * layoutPosition) - layoutSize.width * mTopItemAlignment;
95     current.y = -mSpiralRadius * cosf(angle);
96     current.z = -mSpiralRadius * sinf(angle);
97   }
98
99   void OrientationUp(Vector3& current, const PropertyInputContainer& inputs)
100   {
101     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
102     const Vector3& layoutSize     = inputs[1]->GetVector3();
103     OrientationUp(current, layoutPosition, layoutSize);
104   }
105
106   void OrientationLeft(Vector3& current, const PropertyInputContainer& inputs)
107   {
108     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
109     const Vector3& layoutSize     = inputs[1]->GetVector3();
110     OrientationLeft(current, layoutPosition, layoutSize);
111   }
112
113   void OrientationDown(Vector3& current, const PropertyInputContainer& inputs)
114   {
115     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
116     const Vector3& layoutSize     = inputs[1]->GetVector3();
117     OrientationDown(current, layoutPosition, layoutSize);
118   }
119
120   void OrientationRight(Vector3& current, const PropertyInputContainer& inputs)
121   {
122     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
123     const Vector3& layoutSize     = inputs[1]->GetVector3();
124     OrientationRight(current, layoutPosition, layoutSize);
125   }
126
127   unsigned int mItemId;
128   float        mSpiralRadius;
129   float        mItemSpacingRadians;
130   float        mItemDescent;
131   float        mTopItemAlignment;
132 };
133
134 struct SpiralRotationConstraint
135 {
136   SpiralRotationConstraint(unsigned int itemId, float itemSpacingRadians)
137   : mItemId(itemId),
138     mItemSpacingRadians(itemSpacingRadians)
139   {
140   }
141
142   void OrientationUp(Quaternion& current, const PropertyInputContainer& inputs)
143   {
144     float layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
145     float angle          = -mItemSpacingRadians * layoutPosition;
146
147     current = Quaternion(Radian(angle), Vector3::YAXIS);
148   }
149
150   void OrientationLeft(Quaternion& current, const PropertyInputContainer& inputs)
151   {
152     float layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
153     float angle          = -mItemSpacingRadians * layoutPosition;
154
155     current = Quaternion(Radian(-Math::PI * 0.5f), Vector3::ZAXIS) * Quaternion(Radian(angle), Vector3::YAXIS);
156   }
157
158   void OrientationDown(Quaternion& current, const PropertyInputContainer& inputs)
159   {
160     float layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
161     float angle          = -mItemSpacingRadians * layoutPosition;
162
163     current = Quaternion(Radian(-Math::PI), Vector3::ZAXIS) * Quaternion(Radian(angle), Vector3::YAXIS);
164   }
165
166   void OrientationRight(Quaternion& current, const PropertyInputContainer& inputs)
167   {
168     float layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
169     float angle          = -mItemSpacingRadians * layoutPosition;
170
171     current = Quaternion(Radian(-Math::PI * 1.5f), Vector3::ZAXIS) * Quaternion(Radian(angle), Vector3::YAXIS);
172   }
173
174   unsigned int mItemId;
175   float        mItemSpacingRadians;
176 };
177
178 struct SpiralColorConstraint
179 {
180   SpiralColorConstraint(unsigned int itemId, float itemSpacingRadians)
181   : mItemId(itemId),
182     mItemSpacingRadians(itemSpacingRadians)
183   {
184   }
185
186   void operator()(Vector4& current, const PropertyInputContainer& inputs)
187   {
188     float  layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
189     Radian angle(mItemSpacingRadians * fabsf(layoutPosition) / Dali::ANGLE_360);
190
191     float progress = angle - floorf(angle); // take fractional bit only to get between 0.0 - 1.0
192     progress       = (progress > 0.5f) ? 2.0f * (1.0f - progress) : progress * 2.0f;
193
194     float darkness(1.0f);
195     {
196       const float startMarker = 0.10f; // The progress at which darkening starts
197       const float endMarker   = 0.35f; // The progress at which darkening ends
198       const float minDarkness = 0.15f; // The darkness at end marker
199
200       if(progress > endMarker)
201       {
202         darkness = minDarkness;
203       }
204       else if(progress > startMarker)
205       {
206         darkness = 1.0f - ((1.0f - minDarkness) * ((progress - startMarker) / (endMarker - startMarker)));
207       }
208     }
209
210     current.r = current.g = current.b = darkness;
211   }
212
213   unsigned int mItemId;
214   float        mItemSpacingRadians;
215 };
216
217 struct SpiralVisibilityConstraint
218 {
219   SpiralVisibilityConstraint(unsigned int itemId, float itemSpacingRadians, float itemDescent, float topItemAlignment)
220   : mItemId(itemId),
221     mItemSpacingRadians(itemSpacingRadians),
222     mItemDescent(itemDescent),
223     mTopItemAlignment(topItemAlignment)
224   {
225   }
226
227   void Portrait(bool& current, const PropertyInputContainer& inputs)
228   {
229     float          layoutPosition           = inputs[0]->GetFloat() + static_cast<float>(mItemId);
230     const Vector3& layoutSize               = inputs[1]->GetVector3();
231     float          itemsCachedBeforeTopItem = layoutSize.height * (mTopItemAlignment + 0.5f) / mItemDescent;
232     current                                 = (layoutPosition >= -itemsCachedBeforeTopItem - 1.0f && layoutPosition <= (layoutSize.height / mItemDescent) + 1.0f);
233   }
234
235   void Landscape(bool& current, const PropertyInputContainer& inputs)
236   {
237     float          layoutPosition           = inputs[0]->GetFloat() + static_cast<float>(mItemId);
238     const Vector3& layoutSize               = inputs[1]->GetVector3();
239     float          itemsCachedBeforeTopItem = layoutSize.width * (mTopItemAlignment + 0.5f) / mItemDescent;
240     current                                 = (layoutPosition >= -itemsCachedBeforeTopItem - 1.0f && layoutPosition <= (layoutSize.width / mItemDescent) + 1.0f);
241   }
242
243   unsigned int mItemId;
244   float        mItemSpacingRadians;
245   float        mItemDescent;
246   float        mTopItemAlignment;
247 };
248
249 } // unnamed namespace
250
251 namespace Dali
252 {
253 namespace Toolkit
254 {
255 namespace Internal
256 {
257 struct SpiralLayout::Impl
258 {
259   Impl()
260   : mItemSpacingRadians(DEFAULT_ITEM_SPACING_RADIANS),
261     mRevolutionDistance(DEFAULT_REVOLUTION_DISTANCE),
262     mItemDescent(DEFAULT_ITEM_DESCENT),
263     mTopItemAlignment(DEFAULT_TOP_ITEM_ALIGNMENT),
264     mScrollSpeedFactor(DEFAULT_SCROLL_SPEED_FACTOR),
265     mMaximumSwipeSpeed(DEFAULT_MAXIMUM_SWIPE_SPEED),
266     mItemFlickAnimationDuration(DEFAULT_ITEM_FLICK_ANIMATION_DURATION)
267   {
268   }
269
270   float mItemSpacingRadians;
271   float mRevolutionDistance;
272   float mItemDescent;
273   float mTopItemAlignment;
274   float mScrollSpeedFactor;
275   float mMaximumSwipeSpeed;
276   float mItemFlickAnimationDuration;
277 };
278
279 SpiralLayoutPtr SpiralLayout::New()
280 {
281   return SpiralLayoutPtr(new SpiralLayout());
282 }
283
284 SpiralLayout::~SpiralLayout()
285 {
286   delete mImpl;
287 }
288
289 void SpiralLayout::SetItemSpacing(Radian itemSpacing)
290 {
291   mImpl->mItemSpacingRadians = itemSpacing;
292
293   float itemsPerSpiral = std::max(1.0f, (2.0f * (float)Math::PI) / mImpl->mItemSpacingRadians);
294   mImpl->mItemDescent  = mImpl->mRevolutionDistance / itemsPerSpiral;
295 }
296
297 Radian SpiralLayout::GetItemSpacing() const
298 {
299   return Radian(mImpl->mItemSpacingRadians);
300 }
301
302 void SpiralLayout::SetRevolutionDistance(float distance)
303 {
304   mImpl->mRevolutionDistance = distance;
305
306   float itemsPerSpiral = std::max(1.0f, (2.0f * (float)Math::PI) / mImpl->mItemSpacingRadians);
307   mImpl->mItemDescent  = mImpl->mRevolutionDistance / itemsPerSpiral;
308 }
309
310 float SpiralLayout::GetRevolutionDistance() const
311 {
312   return mImpl->mRevolutionDistance;
313 }
314
315 void SpiralLayout::SetTopItemAlignment(float alignment)
316 {
317   mImpl->mTopItemAlignment = alignment;
318 }
319
320 float SpiralLayout::GetTopItemAlignment() const
321 {
322   return mImpl->mTopItemAlignment;
323 }
324
325 void SpiralLayout::SetScrollSpeedFactor(float scrollSpeed)
326 {
327   mImpl->mScrollSpeedFactor = scrollSpeed;
328 }
329
330 void SpiralLayout::SetMaximumSwipeSpeed(float speed)
331 {
332   mImpl->mMaximumSwipeSpeed = speed;
333 }
334
335 void SpiralLayout::SetItemFlickAnimationDuration(float durationSeconds)
336 {
337   mImpl->mItemFlickAnimationDuration = durationSeconds;
338 }
339
340 float SpiralLayout::GetScrollSpeedFactor() const
341 {
342   return mImpl->mScrollSpeedFactor;
343 }
344
345 float SpiralLayout::GetMaximumSwipeSpeed() const
346 {
347   return mImpl->mMaximumSwipeSpeed;
348 }
349
350 float SpiralLayout::GetItemFlickAnimationDuration() const
351 {
352   return mImpl->mItemFlickAnimationDuration;
353 }
354
355 float SpiralLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
356 {
357   return 1.0f - static_cast<float>(numberOfItems);
358 }
359
360 float SpiralLayout::GetClosestAnchorPosition(float layoutPosition) const
361 {
362   return round(layoutPosition);
363 }
364
365 float SpiralLayout::GetItemScrollToPosition(unsigned int itemId) const
366 {
367   return -(static_cast<float>(itemId));
368 }
369
370 ItemRange SpiralLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
371 {
372   float layoutHeight             = IsHorizontal(GetOrientation()) ? layoutSize.width : layoutSize.height;
373   float itemsPerSpiral           = layoutHeight / mImpl->mItemDescent;
374   float itemsCachedBeforeTopItem = layoutHeight * (mImpl->mTopItemAlignment + 0.5f) / mImpl->mItemDescent;
375   float itemsViewable            = std::min(itemsPerSpiral, itemsPerSpiral - itemsCachedBeforeTopItem - firstItemPosition + 1.0f);
376
377   unsigned int firstItem = static_cast<unsigned int>(std::max(0.0f, -firstItemPosition - itemsCachedBeforeTopItem - 1.0f));
378   unsigned int lastItem  = static_cast<unsigned int>(std::max(0.0f, firstItem + itemsViewable));
379
380   return ItemRange(firstItem, lastItem + 1);
381 }
382
383 unsigned int SpiralLayout::GetReserveItemCount(Vector3 layoutSize) const
384 {
385   float layoutHeight = IsHorizontal(GetOrientation()) ? layoutSize.width : layoutSize.height;
386   return static_cast<unsigned int>(layoutHeight / mImpl->mItemDescent);
387 }
388
389 void SpiralLayout::GetDefaultItemSize(unsigned int itemId, const Vector3& layoutSize, Vector3& itemSize) const
390 {
391   itemSize.width = layoutSize.width * 0.25f;
392
393   // 4x3 aspect ratio
394   itemSize.height = itemSize.depth = (itemSize.width / 4.0f) * 3.0f;
395 }
396
397 Degree SpiralLayout::GetScrollDirection() const
398 {
399   Degree                         scrollDirection(0);
400   const ControlOrientation::Type orientation = GetOrientation();
401
402   if(orientation == ControlOrientation::Up)
403   {
404     scrollDirection = Degree(-45.0f); // Allow swiping horizontally & vertically
405   }
406   else if(orientation == ControlOrientation::Left)
407   {
408     scrollDirection = Degree(45.0f);
409   }
410   else if(orientation == ControlOrientation::Down)
411   {
412     scrollDirection = Degree(180.0f - 45.0f);
413   }
414   else // orientation == ControlOrientation::Right
415   {
416     scrollDirection = Degree(270.0f - 45.0f);
417   }
418
419   return scrollDirection;
420 }
421
422 void SpiralLayout::ApplyConstraints(Actor& actor, const int itemId, const Vector3& layoutSize, const Actor& itemViewActor)
423 {
424   // This just implements the default behaviour of constraint application.
425   // Custom layouts can override this function to apply their custom constraints.
426   Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast(itemViewActor);
427   if(itemView)
428   {
429     const ControlOrientation::Type orientation = GetOrientation();
430
431     // Position constraint
432     SpiralPositionConstraint positionConstraint(itemId, GetDefaultSpiralRadiusFunction(layoutSize), mImpl->mItemSpacingRadians, mImpl->mItemDescent, mImpl->mTopItemAlignment);
433     Constraint               constraint;
434     if(orientation == ControlOrientation::Up)
435     {
436       constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, positionConstraint, &SpiralPositionConstraint::OrientationUp);
437     }
438     else if(orientation == ControlOrientation::Left)
439     {
440       constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, positionConstraint, &SpiralPositionConstraint::OrientationLeft);
441     }
442     else if(orientation == ControlOrientation::Down)
443     {
444       constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, positionConstraint, &SpiralPositionConstraint::OrientationDown);
445     }
446     else // orientation == ControlOrientation::Right
447     {
448       constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, positionConstraint, &SpiralPositionConstraint::OrientationRight);
449     }
450     constraint.AddSource(ParentSource(Toolkit::ItemView::Property::LAYOUT_POSITION));
451     constraint.AddSource(ParentSource(Actor::Property::SIZE));
452     constraint.Apply();
453
454     // Rotation constraint
455     SpiralRotationConstraint rotationConstraint(itemId, mImpl->mItemSpacingRadians);
456     if(orientation == ControlOrientation::Up)
457     {
458       constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, rotationConstraint, &SpiralRotationConstraint::OrientationUp);
459     }
460     else if(orientation == ControlOrientation::Left)
461     {
462       constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, rotationConstraint, &SpiralRotationConstraint::OrientationLeft);
463     }
464     else if(orientation == ControlOrientation::Down)
465     {
466       constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, rotationConstraint, &SpiralRotationConstraint::OrientationDown);
467     }
468     else // orientation == ControlOrientation::Right
469     {
470       constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, rotationConstraint, &SpiralRotationConstraint::OrientationRight);
471     }
472     constraint.AddSource(ParentSource(Toolkit::ItemView::Property::LAYOUT_POSITION));
473     constraint.Apply();
474
475     // Color constraint
476     constraint = Constraint::New<Vector4>(actor, Actor::Property::COLOR, SpiralColorConstraint(itemId, mImpl->mItemSpacingRadians));
477     constraint.AddSource(ParentSource(Toolkit::ItemView::Property::LAYOUT_POSITION));
478     constraint.SetRemoveAction(Dali::Constraint::DISCARD);
479     constraint.Apply();
480
481     // Visibility constraint
482     SpiralVisibilityConstraint visibilityConstraint(itemId, mImpl->mItemSpacingRadians, mImpl->mItemDescent, mImpl->mTopItemAlignment);
483     if(IsVertical(orientation))
484     {
485       constraint = Constraint::New<bool>(actor, Actor::Property::VISIBLE, visibilityConstraint, &SpiralVisibilityConstraint::Portrait);
486     }
487     else // horizontal
488     {
489       constraint = Constraint::New<bool>(actor, Actor::Property::VISIBLE, visibilityConstraint, &SpiralVisibilityConstraint::Landscape);
490     }
491     constraint.AddSource(ParentSource(Toolkit::ItemView::Property::LAYOUT_POSITION));
492     constraint.AddSource(ParentSource(Actor::Property::SIZE));
493     constraint.SetRemoveAction(Dali::Constraint::DISCARD);
494     constraint.Apply();
495   }
496 }
497
498 void SpiralLayout::SetSpiralLayoutProperties(const Property::Map& properties)
499 {
500   // Set any properties specified for SpiralLayout.
501   for(unsigned int idx = 0, mapCount = properties.Count(); idx < mapCount; ++idx)
502   {
503     KeyValuePair propertyPair = properties.GetKeyValue(idx);
504     switch(DefaultItemLayoutProperty::Property(propertyPair.first.indexKey))
505     {
506       case DefaultItemLayoutProperty::SPIRAL_ITEM_SPACING:
507       {
508         SetItemSpacing(Radian(propertyPair.second.Get<float>()));
509         break;
510       }
511       case DefaultItemLayoutProperty::SPIRAL_MAXIMUM_SWIPE_SPEED:
512       {
513         SetMaximumSwipeSpeed(propertyPair.second.Get<float>());
514         break;
515       }
516       case DefaultItemLayoutProperty::SPIRAL_TOP_ITEM_ALIGNMENT:
517       {
518         SetTopItemAlignment(propertyPair.second.Get<float>());
519         break;
520       }
521       case DefaultItemLayoutProperty::SPIRAL_SCROLL_SPEED_FACTOR:
522       {
523         SetScrollSpeedFactor(propertyPair.second.Get<float>());
524         break;
525       }
526       case DefaultItemLayoutProperty::SPIRAL_REVOLUTION_DISTANCE:
527       {
528         SetRevolutionDistance(propertyPair.second.Get<float>());
529         break;
530       }
531       case DefaultItemLayoutProperty::SPIRAL_ITEM_FLICK_ANIMATION_DURATION:
532       {
533         SetItemFlickAnimationDuration(propertyPair.second.Get<float>());
534         break;
535       }
536       default:
537       {
538         break;
539       }
540     }
541   }
542 }
543
544 Vector3 SpiralLayout::GetItemPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize) const
545 {
546   Vector3                        itemPosition = Vector3::ZERO;
547   const ControlOrientation::Type orientation  = GetOrientation();
548
549   SpiralPositionConstraint positionConstraint(itemID, GetDefaultSpiralRadiusFunction(layoutSize), mImpl->mItemSpacingRadians, mImpl->mItemDescent, mImpl->mTopItemAlignment);
550
551   if(orientation == ControlOrientation::Up)
552   {
553     positionConstraint.OrientationUp(itemPosition, currentLayoutPosition + itemID, layoutSize);
554   }
555   else if(orientation == ControlOrientation::Left)
556   {
557     positionConstraint.OrientationLeft(itemPosition, currentLayoutPosition + itemID, layoutSize);
558   }
559   else if(orientation == ControlOrientation::Down)
560   {
561     positionConstraint.OrientationDown(itemPosition, currentLayoutPosition + itemID, layoutSize);
562   }
563   else //orientation == ControlOrientation::Right
564   {
565     positionConstraint.OrientationRight(itemPosition, currentLayoutPosition + itemID, layoutSize);
566   }
567
568   return itemPosition;
569 }
570
571 SpiralLayout::SpiralLayout()
572 : mImpl(NULL)
573 {
574   mImpl = new Impl();
575 }
576
577 float SpiralLayout::GetClosestOnScreenLayoutPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize)
578 {
579   return GetItemScrollToPosition(itemID);
580 }
581
582 } // namespace Internal
583
584 } // namespace Toolkit
585
586 } // namespace Dali