Updated all cpp files to new format
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scrollable / item-view / grid-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/grid-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             = 4;
36 const float        DEFAULT_TOP_MARGIN                    = 95.0f;
37 const float        DEFAULT_BOTTOM_MARGIN                 = 20.0f;
38 const float        DEFAULT_SIDE_MARGIN                   = 20.0f;
39 const float        DEFAULT_COLUMN_SPACING                = 20.0f;
40 const float        DEFAULT_ROW_SPACING                   = 20.0f;
41 const float        DEFAULT_SCROLL_SPEED_FACTOR           = 0.03f;
42 const float        DEFAULT_MAXIMUM_SWIPE_SPEED           = 100.0f;
43 const float        DEFAULT_ITEM_FLICK_ANIMATION_DURATION = 0.015f;
44
45 struct GridPositionConstraint
46 {
47   GridPositionConstraint(
48     unsigned int       itemId,
49     const unsigned int columnIndex,
50     const unsigned int numberOfColumns,
51     const float        rowSpacing,
52     const float        columnSpacing,
53     const float        topMargin,
54     const float        sideMargin,
55     const Vector3&     itemSize,
56     const float        gap)
57   : mItemSize(itemSize),
58     mItemId(itemId),
59     mColumnIndex(columnIndex),
60     mNumberOfColumns(numberOfColumns),
61     mRowSpacing(rowSpacing),
62     mColumnSpacing(columnSpacing),
63     mTopMargin(topMargin),
64     mSideMargin(sideMargin),
65     mZGap(gap)
66   {
67   }
68
69   inline void Orientation0(Vector3& current, float layoutPosition, const Vector3& layoutSize)
70   {
71     current.x = mSideMargin + (mColumnIndex * (mItemSize.x + mColumnSpacing)) + mItemSize.x * 0.5f - layoutSize.x * 0.5f;
72     current.y = ((mItemSize.y + mRowSpacing) * (layoutPosition - mColumnIndex)) / mNumberOfColumns - layoutSize.height * 0.5f + mItemSize.y * 0.5f + mTopMargin;
73     current.z = mColumnIndex * mZGap;
74   }
75
76   inline void Orientation90(Vector3& current, float layoutPosition, const Vector3& layoutSize)
77   {
78     current.x = ((mItemSize.y + mRowSpacing) * (layoutPosition - mColumnIndex)) / mNumberOfColumns - layoutSize.width * 0.5f + mItemSize.y * 0.5f + mTopMargin;
79     current.y = -(mSideMargin + (mColumnIndex * (mItemSize.x + mColumnSpacing)) + mItemSize.x * 0.5f - layoutSize.y * 0.5f);
80     current.z = mColumnIndex * mZGap;
81   }
82
83   inline void Orientation180(Vector3& current, float layoutPosition, const Vector3& layoutSize)
84   {
85     current.x = -(mSideMargin + (mColumnIndex * (mItemSize.x + mColumnSpacing)) + mItemSize.x * 0.5f - layoutSize.x * 0.5f);
86     current.y = -(((mItemSize.y + mRowSpacing) * (layoutPosition - mColumnIndex)) / mNumberOfColumns - layoutSize.height * 0.5f + mItemSize.y * 0.5f + mTopMargin);
87     current.z = mColumnIndex * mZGap;
88   }
89
90   inline void Orientation270(Vector3& current, float layoutPosition, const Vector3& layoutSize)
91   {
92     current.x = -(((mItemSize.y + mRowSpacing) * (layoutPosition - mColumnIndex)) / mNumberOfColumns - layoutSize.width * 0.5f + mItemSize.y * 0.5f + mTopMargin);
93     current.y = mSideMargin + (mColumnIndex * (mItemSize.x + mColumnSpacing)) + mItemSize.x * 0.5f - layoutSize.y * 0.5f;
94     current.z = mColumnIndex * mZGap;
95   }
96
97   void Orientation0(Vector3& current, const PropertyInputContainer& inputs)
98   {
99     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
100     const Vector3& layoutSize     = inputs[1]->GetVector3();
101     Orientation0(current, layoutPosition, layoutSize);
102   }
103
104   void Orientation90(Vector3& current, const PropertyInputContainer& inputs)
105   {
106     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
107     const Vector3& layoutSize     = inputs[1]->GetVector3();
108     Orientation90(current, layoutPosition, layoutSize);
109   }
110
111   void Orientation180(Vector3& current, const PropertyInputContainer& inputs)
112   {
113     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
114     const Vector3& layoutSize     = inputs[1]->GetVector3();
115     Orientation180(current, layoutPosition, layoutSize);
116   }
117
118   void Orientation270(Vector3& current, const PropertyInputContainer& inputs)
119   {
120     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
121     const Vector3& layoutSize     = inputs[1]->GetVector3();
122     Orientation270(current, layoutPosition, layoutSize);
123   }
124
125 public:
126   Vector3      mItemSize;
127   unsigned int mItemId;
128   unsigned int mColumnIndex;
129   unsigned int mNumberOfColumns;
130   float        mRowSpacing;
131   float        mColumnSpacing;
132   float        mTopMargin;
133   float        mSideMargin;
134   float        mZGap;
135 };
136
137 void GridRotationConstraint0(Quaternion& current, const PropertyInputContainer& /* inputs */)
138 {
139   current = Quaternion(Radian(0.0f), Vector3::ZAXIS);
140 }
141
142 void GridRotationConstraint90(Quaternion& current, const PropertyInputContainer& /* inputs */)
143 {
144   current = Quaternion(Radian(1.5f * Math::PI), Vector3::ZAXIS);
145 }
146
147 void GridRotationConstraint180(Quaternion& current, const PropertyInputContainer& /* inputs */)
148 {
149   current = Quaternion(Radian(Math::PI), Vector3::ZAXIS);
150 }
151
152 void GridRotationConstraint270(Quaternion& current, const PropertyInputContainer& /* inputs */)
153 {
154   current = Quaternion(Radian(0.5f * Math::PI), Vector3::ZAXIS);
155 }
156
157 void GridColorConstraint(Vector4& current, const PropertyInputContainer& /* inputs */)
158 {
159   current.r = current.g = current.b = 1.0f;
160 }
161
162 struct GridVisibilityConstraint
163 {
164   GridVisibilityConstraint(
165     unsigned int       itemId,
166     const unsigned int columnIndex,
167     const unsigned int numberOfColumns,
168     const float        rowSpacing,
169     const float        columnSpacing,
170     const float        sideMargin,
171     const Vector3&     itemSize)
172   : mItemSize(itemSize),
173     mItemId(itemId),
174     mColumnIndex(columnIndex),
175     mNumberOfColumns(numberOfColumns),
176     mRowSpacing(rowSpacing),
177     mColumnSpacing(columnSpacing),
178     mSideMargin(sideMargin)
179   {
180   }
181
182   void Portrait(bool& current, const PropertyInputContainer& inputs)
183   {
184     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
185     const Vector3& layoutSize     = inputs[1]->GetVector3();
186
187     float row         = (layoutPosition - static_cast<float>(mColumnIndex)) / mNumberOfColumns;
188     int   rowsPerPage = ceil(layoutSize.height / (mItemSize.y + mRowSpacing));
189
190     current = (row > -2.0f) && (row < rowsPerPage);
191   }
192
193   void Landscape(bool& current, const PropertyInputContainer& inputs)
194   {
195     float          layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
196     const Vector3& layoutSize     = inputs[1]->GetVector3();
197
198     float row         = (layoutPosition - static_cast<float>(mColumnIndex)) / mNumberOfColumns;
199     int   rowsPerPage = ceil(layoutSize.width / (mItemSize.y + mRowSpacing));
200
201     current = (row > -2.0f) && (row < rowsPerPage);
202   }
203
204 public:
205   Vector3      mItemSize;
206   unsigned int mItemId;
207   unsigned int mColumnIndex;
208   unsigned int mNumberOfColumns;
209   float        mRowSpacing;
210   float        mColumnSpacing;
211   float        mSideMargin;
212 };
213
214 } // unnamed namespace
215
216 namespace Dali
217 {
218 namespace Toolkit
219 {
220 namespace Internal
221 {
222 struct GridLayout::Impl
223 {
224   Impl()
225   : mNumberOfColumns(DEFAULT_NUMBER_OF_COLUMNS),
226     mRowSpacing(DEFAULT_ROW_SPACING),
227     mColumnSpacing(DEFAULT_COLUMN_SPACING),
228     mTopMargin(DEFAULT_TOP_MARGIN),
229     mBottomMargin(DEFAULT_BOTTOM_MARGIN),
230     mSideMargin(DEFAULT_SIDE_MARGIN),
231     mZGap(0.f),
232     mScrollSpeedFactor(DEFAULT_SCROLL_SPEED_FACTOR),
233     mMaximumSwipeSpeed(DEFAULT_MAXIMUM_SWIPE_SPEED),
234     mItemFlickAnimationDuration(DEFAULT_ITEM_FLICK_ANIMATION_DURATION)
235   {
236   }
237
238   unsigned int mNumberOfColumns;
239   float        mRowSpacing;
240   float        mColumnSpacing;
241   float        mTopMargin;
242   float        mBottomMargin;
243   float        mSideMargin;
244   float        mZGap;
245
246   float mScrollSpeedFactor;
247   float mMaximumSwipeSpeed;
248   float mItemFlickAnimationDuration;
249 };
250
251 GridLayoutPtr GridLayout::New()
252 {
253   return GridLayoutPtr(new GridLayout());
254 }
255
256 GridLayout::~GridLayout()
257 {
258   delete mImpl;
259 }
260
261 void GridLayout::SetNumberOfColumns(unsigned int columns)
262 {
263   mImpl->mNumberOfColumns = columns;
264 }
265
266 unsigned int GridLayout::GetNumberOfColumns() const
267 {
268   return mImpl->mNumberOfColumns;
269 }
270
271 void GridLayout::SetRowSpacing(float spacing)
272 {
273   mImpl->mRowSpacing = spacing;
274 }
275
276 float GridLayout::GetRowSpacing() const
277 {
278   return mImpl->mRowSpacing;
279 }
280
281 void GridLayout::SetColumnSpacing(float spacing)
282 {
283   mImpl->mColumnSpacing = spacing;
284 }
285
286 float GridLayout::GetColumnSpacing() const
287 {
288   return mImpl->mColumnSpacing;
289 }
290
291 void GridLayout::SetTopMargin(float margin)
292 {
293   mImpl->mTopMargin = margin;
294 }
295
296 float GridLayout::GetTopMargin() const
297 {
298   return mImpl->mTopMargin;
299 }
300
301 void GridLayout::SetBottomMargin(float margin)
302 {
303   mImpl->mBottomMargin = margin;
304 }
305
306 float GridLayout::GetBottomMargin() const
307 {
308   return mImpl->mBottomMargin;
309 }
310
311 void GridLayout::SetSideMargin(float margin)
312 {
313   mImpl->mSideMargin = margin;
314 }
315
316 float GridLayout::GetSideMargin() const
317 {
318   return mImpl->mSideMargin;
319 }
320
321 void GridLayout::SetZGap(float gap)
322 {
323   mImpl->mZGap = gap;
324 }
325
326 float GridLayout::GetZGap() const
327 {
328   return mImpl->mZGap;
329 }
330
331 void GridLayout::SetScrollSpeedFactor(float scrollSpeed)
332 {
333   mImpl->mScrollSpeedFactor = scrollSpeed;
334 }
335
336 void GridLayout::SetMaximumSwipeSpeed(float speed)
337 {
338   mImpl->mMaximumSwipeSpeed = speed;
339 }
340
341 void GridLayout::SetItemFlickAnimationDuration(float durationSeconds)
342 {
343   mImpl->mItemFlickAnimationDuration = durationSeconds;
344 }
345
346 float GridLayout::GetScrollSpeedFactor() const
347 {
348   return mImpl->mScrollSpeedFactor;
349 }
350
351 float GridLayout::GetMaximumSwipeSpeed() const
352 {
353   return mImpl->mMaximumSwipeSpeed;
354 }
355
356 float GridLayout::GetItemFlickAnimationDuration() const
357 {
358   return mImpl->mItemFlickAnimationDuration;
359 }
360
361 float GridLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
362 {
363   float layoutHeight = IsHorizontal(GetOrientation()) ? layoutSize.width : layoutSize.height;
364
365   Vector3 itemSize;
366   GetItemSize(0, layoutSize, itemSize);
367
368   unsigned int itemsLastRow = numberOfItems % mImpl->mNumberOfColumns;
369   if(itemsLastRow == 0)
370   {
371     itemsLastRow = mImpl->mNumberOfColumns;
372   }
373
374   float rowsLastPage  = (layoutHeight - mImpl->mBottomMargin - mImpl->mTopMargin + mImpl->mRowSpacing) / (itemSize.y + mImpl->mRowSpacing);
375   float itemsLastPage = (rowsLastPage - 1.0f) * static_cast<float>(mImpl->mNumberOfColumns) + static_cast<float>(itemsLastRow);
376
377   return itemsLastPage - static_cast<float>(numberOfItems);
378 }
379
380 float GridLayout::GetClosestAnchorPosition(float layoutPosition) const
381 {
382   float rowIndex = static_cast<float>(round(layoutPosition / mImpl->mNumberOfColumns));
383   return rowIndex * static_cast<float>(mImpl->mNumberOfColumns);
384 }
385
386 float GridLayout::GetItemScrollToPosition(unsigned int itemId) const
387 {
388   float rowIndex = static_cast<float>(itemId) / mImpl->mNumberOfColumns;
389   return -rowIndex * static_cast<float>(mImpl->mNumberOfColumns);
390 }
391
392 ItemRange GridLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
393 {
394   float layoutHeight = IsHorizontal(GetOrientation()) ? layoutSize.width : layoutSize.height;
395
396   Vector3 itemSize;
397   GetItemSize(0, layoutSize, itemSize);
398
399   int itemsPerPage     = mImpl->mNumberOfColumns * ceil(layoutHeight / (itemSize.y + mImpl->mRowSpacing));
400   int firstVisibleItem = -(static_cast<int>(firstItemPosition / mImpl->mNumberOfColumns)) * mImpl->mNumberOfColumns;
401
402   int firstItemIndex = std::max(0, firstVisibleItem - static_cast<int>(mImpl->mNumberOfColumns));
403   int lastItemIndex  = std::max(0, firstVisibleItem + itemsPerPage);
404
405   return ItemRange(firstItemIndex, lastItemIndex);
406 }
407
408 float GridLayout::GetClosestOnScreenLayoutPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize)
409 {
410   Vector3                  itemPosition = GetItemPosition(itemID, currentLayoutPosition, layoutSize);
411   Vector3                  itemSize;
412   ControlOrientation::Type orientation = GetOrientation();
413
414   GetItemSize(itemID, layoutSize, itemSize);
415   Vector3 onScreenArea = (layoutSize - (IsVertical(orientation) ? itemSize : Vector3(itemSize.y, itemSize.x, itemSize.z))) * 0.5f;
416   if(itemPosition.x < -onScreenArea.x || itemPosition.x > onScreenArea.x || itemPosition.y < -onScreenArea.y || itemPosition.y > onScreenArea.y)
417   {
418     // item not within viewable area
419     float   rowHeight         = itemSize.y + mImpl->mRowSpacing;
420     Vector3 firstItemPosition = GetItemPosition(itemID, 0.0f, layoutSize);
421     float   offset            = 0.0f;
422     switch(orientation)
423     {
424       case ControlOrientation::Up:
425       {
426         if(itemPosition.y > onScreenArea.y)
427         {
428           offset = ((layoutSize.y - rowHeight) * 0.5f) - firstItemPosition.y;
429         }
430         else
431         {
432           offset = ((-layoutSize.y + rowHeight) * 0.5f) - firstItemPosition.y;
433         }
434         break;
435       }
436       case ControlOrientation::Down:
437       {
438         if(itemPosition.y < -onScreenArea.y)
439         {
440           offset = ((layoutSize.y - rowHeight) * 0.5f) - firstItemPosition.y;
441         }
442         else
443         {
444           offset = ((-layoutSize.y + rowHeight) * 0.5f) - firstItemPosition.y;
445         }
446         break;
447       }
448       case ControlOrientation::Left:
449       {
450         if(itemPosition.x > onScreenArea.x)
451         {
452           offset = ((layoutSize.x - rowHeight) * 0.5f) - firstItemPosition.x;
453         }
454         else
455         {
456           offset = ((-layoutSize.x + rowHeight) * 0.5f) - firstItemPosition.x;
457         }
458         break;
459       }
460       case ControlOrientation::Right:
461       {
462         if(itemPosition.x < -onScreenArea.x)
463         {
464           offset = ((layoutSize.x - rowHeight) * 0.5f) - firstItemPosition.x;
465         }
466         else
467         {
468           offset = ((-layoutSize.x + rowHeight) * 0.5f) - firstItemPosition.x;
469         }
470         break;
471       }
472     }
473     // work out number of rows from first item position to an item aligned to bottom of screen
474     float rowDiff              = offset / rowHeight;
475     float layoutPositionOffset = rowDiff * mImpl->mNumberOfColumns;
476     float scrollTo             = GetItemScrollToPosition(itemID) + layoutPositionOffset;
477     return scrollTo;
478   }
479   return currentLayoutPosition;
480 }
481
482 unsigned int GridLayout::GetReserveItemCount(Vector3 layoutSize) const
483 {
484   float layoutHeight = IsHorizontal(GetOrientation()) ? layoutSize.width : layoutSize.height;
485
486   Vector3 itemSize;
487   GetItemSize(0, layoutSize, itemSize);
488   int itemsPerPage = mImpl->mNumberOfColumns * ceil(layoutHeight / (itemSize.y + mImpl->mRowSpacing));
489   return itemsPerPage;
490 }
491
492 void GridLayout::GetDefaultItemSize(unsigned int itemId, const Vector3& layoutSize, Vector3& itemSize) const
493 {
494   float layoutWidth = IsHorizontal(GetOrientation()) ? layoutSize.height : layoutSize.width;
495   itemSize.width    = (layoutWidth - mImpl->mSideMargin * 2.0f - mImpl->mColumnSpacing * static_cast<float>(mImpl->mNumberOfColumns - 1)) / static_cast<float>(mImpl->mNumberOfColumns);
496
497   // 4x3 aspect ratio
498   itemSize.height = itemSize.depth = itemSize.width * 0.75f;
499 }
500
501 Degree GridLayout::GetScrollDirection() const
502 {
503   Degree                   scrollDirection(0.0f);
504   ControlOrientation::Type orientation = GetOrientation();
505
506   if(orientation == ControlOrientation::Up)
507   {
508     scrollDirection = Degree(0.0f);
509   }
510   else if(orientation == ControlOrientation::Left)
511   {
512     scrollDirection = Degree(90.0f);
513   }
514   else if(orientation == ControlOrientation::Down)
515   {
516     scrollDirection = Degree(180.0f);
517   }
518   else // orientation == ControlOrientation::Right
519   {
520     scrollDirection = Degree(270.0f);
521   }
522
523   return scrollDirection;
524 }
525
526 void GridLayout::ApplyConstraints(Actor& actor, const int itemId, const Vector3& layoutSize, const Actor& itemViewActor)
527 {
528   // This just implements the default behaviour of constraint application.
529   // Custom layouts can override this function to apply their custom constraints.
530   Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast(itemViewActor);
531   if(itemView)
532   {
533     Vector3 itemSize;
534     GetItemSize(itemId, layoutSize, itemSize);
535     const unsigned int             columnIndex = itemId % mImpl->mNumberOfColumns;
536     const ControlOrientation::Type orientation = GetOrientation();
537
538     // Position constraint
539     GridPositionConstraint positionConstraint(itemId,
540                                               columnIndex,
541                                               mImpl->mNumberOfColumns,
542                                               mImpl->mRowSpacing,
543                                               mImpl->mColumnSpacing,
544                                               mImpl->mTopMargin,
545                                               mImpl->mSideMargin,
546                                               itemSize,
547                                               mImpl->mZGap);
548     Constraint             constraint;
549     if(orientation == ControlOrientation::Up)
550     {
551       constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, positionConstraint, &GridPositionConstraint::Orientation0);
552     }
553     else if(orientation == ControlOrientation::Left)
554     {
555       constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, positionConstraint, &GridPositionConstraint::Orientation90);
556     }
557     else if(orientation == ControlOrientation::Down)
558     {
559       constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, positionConstraint, &GridPositionConstraint::Orientation180);
560     }
561     else // orientation == ControlOrientation::Right
562     {
563       constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, positionConstraint, &GridPositionConstraint::Orientation270);
564     }
565     constraint.AddSource(ParentSource(Toolkit::ItemView::Property::LAYOUT_POSITION));
566     constraint.AddSource(ParentSource(Actor::Property::SIZE));
567     constraint.Apply();
568
569     // Rotation constraint
570     if(orientation == ControlOrientation::Up)
571     {
572       constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, &GridRotationConstraint0);
573     }
574     else if(orientation == ControlOrientation::Left)
575     {
576       constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, &GridRotationConstraint90);
577     }
578     else if(orientation == ControlOrientation::Down)
579     {
580       constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, &GridRotationConstraint180);
581     }
582     else // orientation == ControlOrientation::Right
583     {
584       constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, &GridRotationConstraint270);
585     }
586     constraint.Apply();
587
588     // Color constraint
589     constraint = Constraint::New<Vector4>(actor, Actor::Property::COLOR, &GridColorConstraint);
590     constraint.SetRemoveAction(Dali::Constraint::DISCARD);
591     constraint.Apply();
592
593     // Visibility constraint
594     GridVisibilityConstraint visibilityConstraint(itemId,
595                                                   columnIndex,
596                                                   mImpl->mNumberOfColumns,
597                                                   mImpl->mRowSpacing,
598                                                   mImpl->mColumnSpacing,
599                                                   mImpl->mSideMargin,
600                                                   itemSize);
601     if(IsVertical(orientation))
602     {
603       constraint = Constraint::New<bool>(actor, Actor::Property::VISIBLE, visibilityConstraint, &GridVisibilityConstraint::Portrait);
604     }
605     else // horizontal
606     {
607       constraint = Constraint::New<bool>(actor, Actor::Property::VISIBLE, visibilityConstraint, &GridVisibilityConstraint::Landscape);
608     }
609     constraint.AddSource(ParentSource(Toolkit::ItemView::Property::LAYOUT_POSITION));
610     constraint.AddSource(ParentSource(Actor::Property::SIZE));
611     constraint.SetRemoveAction(Dali::Constraint::DISCARD);
612     constraint.Apply();
613   }
614 }
615
616 void GridLayout::SetGridLayoutProperties(const Property::Map& properties)
617 {
618   // Set any properties specified for gridLayout.
619   for(unsigned int idx = 0, mapCount = properties.Count(); idx < mapCount; ++idx)
620   {
621     KeyValuePair propertyPair = properties.GetKeyValue(idx);
622     switch(DefaultItemLayoutProperty::Property(propertyPair.first.indexKey))
623     {
624       case DefaultItemLayoutProperty::GRID_COLUMN_NUMBER:
625       {
626         SetNumberOfColumns(propertyPair.second.Get<int>());
627         break;
628       }
629       case DefaultItemLayoutProperty::GRID_ROW_SPACING:
630       {
631         SetRowSpacing(propertyPair.second.Get<float>());
632         break;
633       }
634       case DefaultItemLayoutProperty::GRID_COLUMN_SPACING:
635       {
636         SetColumnSpacing(propertyPair.second.Get<float>());
637         break;
638       }
639       case DefaultItemLayoutProperty::GRID_TOP_MARGIN:
640       {
641         SetTopMargin(propertyPair.second.Get<float>());
642         break;
643       }
644       case DefaultItemLayoutProperty::GRID_BOTTOM_MARGIN:
645       {
646         SetBottomMargin(propertyPair.second.Get<float>());
647         break;
648       }
649       case DefaultItemLayoutProperty::GRID_SIDE_MARGIN:
650       {
651         SetSideMargin(propertyPair.second.Get<float>());
652         break;
653       }
654       case DefaultItemLayoutProperty::GRID_SCROLL_SPEED_FACTOR:
655       {
656         SetScrollSpeedFactor(propertyPair.second.Get<float>());
657         break;
658       }
659       case DefaultItemLayoutProperty::GRID_MAXIMUM_SWIPE_SPEED:
660       {
661         SetMaximumSwipeSpeed(propertyPair.second.Get<float>());
662         break;
663       }
664       case DefaultItemLayoutProperty::GRID_ITEM_FLICK_ANIMATION_DURATION:
665       {
666         SetItemFlickAnimationDuration(propertyPair.second.Get<float>());
667         break;
668       }
669       default:
670       {
671         break;
672       }
673     }
674   }
675 }
676
677 Vector3 GridLayout::GetItemPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize) const
678 {
679   Vector3                        itemPosition = Vector3::ZERO;
680   const unsigned int             columnIndex  = itemID % mImpl->mNumberOfColumns;
681   const ControlOrientation::Type orientation  = GetOrientation();
682   Vector3                        itemSize;
683   GetItemSize(itemID, layoutSize, itemSize);
684
685   GridPositionConstraint positionConstraintStruct(itemID,
686                                                   columnIndex,
687                                                   mImpl->mNumberOfColumns,
688                                                   mImpl->mRowSpacing,
689                                                   mImpl->mColumnSpacing,
690                                                   mImpl->mTopMargin,
691                                                   mImpl->mSideMargin,
692                                                   itemSize,
693                                                   mImpl->mZGap);
694
695   if(orientation == ControlOrientation::Up)
696   {
697     positionConstraintStruct.Orientation0(itemPosition, currentLayoutPosition + itemID, layoutSize);
698   }
699   else if(orientation == ControlOrientation::Left)
700   {
701     positionConstraintStruct.Orientation90(itemPosition, currentLayoutPosition + itemID, layoutSize);
702   }
703   else if(orientation == ControlOrientation::Down)
704   {
705     positionConstraintStruct.Orientation180(itemPosition, currentLayoutPosition + itemID, layoutSize);
706   }
707   else // orientation == ControlOrientation::Right
708   {
709     positionConstraintStruct.Orientation270(itemPosition, currentLayoutPosition + itemID, layoutSize);
710   }
711
712   return itemPosition;
713 }
714
715 int GridLayout::GetNextFocusItemID(int itemID, int maxItems, Dali::Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
716 {
717   switch(direction)
718   {
719     case Toolkit::Control::KeyboardFocus::LEFT:
720     {
721       itemID--;
722       if(itemID < 0)
723       {
724         itemID = loopEnabled ? maxItems - 1 : 0;
725       }
726       break;
727     }
728     case Toolkit::Control::KeyboardFocus::UP:
729     {
730       itemID -= mImpl->mNumberOfColumns;
731       if(itemID < 0)
732       {
733         itemID = loopEnabled ? itemID + maxItems : itemID + mImpl->mNumberOfColumns;
734       }
735       break;
736     }
737     case Toolkit::Control::KeyboardFocus::RIGHT:
738     {
739       itemID++;
740       if(itemID >= maxItems)
741       {
742         itemID = loopEnabled ? 0 : maxItems - 1;
743       }
744       break;
745     }
746     case Toolkit::Control::KeyboardFocus::DOWN:
747     {
748       itemID += mImpl->mNumberOfColumns;
749       if(itemID >= maxItems)
750       {
751         itemID = loopEnabled ? 0 : itemID - mImpl->mNumberOfColumns;
752       }
753       break;
754     }
755     default:
756     {
757       break;
758     }
759   }
760   return itemID;
761 }
762
763 GridLayout::GridLayout()
764 : mImpl(NULL)
765 {
766   mImpl = new Impl();
767 }
768
769 } // namespace Internal
770
771 } // namespace Toolkit
772
773 } // namespace Dali