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