2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/controls/scrollable/item-view/grid-layout.h>
23 #include <dali/public-api/animation/animation.h>
24 #include <dali/public-api/animation/constraint.h>
27 #include <dali-toolkit/public-api/controls/scrollable/item-view/item-view.h>
28 #include <dali-toolkit/devel-api/controls/scrollable/item-view/default-item-layout-property.h>
31 using namespace Dali::Toolkit;
33 namespace // unnamed namespace
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;
46 struct GridPositionConstraint
48 GridPositionConstraint(
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,
58 : mItemSize( itemSize ),
60 mColumnIndex( columnIndex ),
61 mNumberOfColumns( numberOfColumns ),
62 mRowSpacing( rowSpacing ),
63 mColumnSpacing( columnSpacing ),
64 mTopMargin( topMargin ),
65 mSideMargin( sideMargin ),
70 inline void Orientation0( Vector3& current, float layoutPosition, const Vector3& layoutSize )
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;
77 inline void Orientation90( Vector3& current, float layoutPosition, const Vector3& layoutSize )
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;
84 inline void Orientation180( Vector3& current, float layoutPosition, const Vector3& layoutSize )
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;
91 inline void Orientation270( Vector3& current, float layoutPosition, const Vector3& layoutSize )
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;
98 void Orientation0( Vector3& current, const PropertyInputContainer& inputs )
100 float layoutPosition = inputs[0]->GetFloat() + static_cast< float >( mItemId );
101 const Vector3& layoutSize = inputs[1]->GetVector3();
102 Orientation0( current, layoutPosition, layoutSize );
105 void Orientation90( Vector3& current, const PropertyInputContainer& inputs )
107 float layoutPosition = inputs[0]->GetFloat() + static_cast< float >( mItemId );
108 const Vector3& layoutSize = inputs[1]->GetVector3();
109 Orientation90( current, layoutPosition, layoutSize );
112 void Orientation180( Vector3& current, const PropertyInputContainer& inputs )
114 float layoutPosition = inputs[0]->GetFloat() + static_cast< float >( mItemId );
115 const Vector3& layoutSize = inputs[1]->GetVector3();
116 Orientation180( current, layoutPosition, layoutSize );
119 void Orientation270( Vector3& current, const PropertyInputContainer& inputs )
121 float layoutPosition = inputs[0]->GetFloat() + static_cast< float >( mItemId );
122 const Vector3& layoutSize = inputs[1]->GetVector3();
123 Orientation270( current, layoutPosition, layoutSize );
129 unsigned int mItemId;
130 unsigned int mColumnIndex;
131 unsigned int mNumberOfColumns;
133 float mColumnSpacing;
139 void GridRotationConstraint0( Quaternion& current, const PropertyInputContainer& /* inputs */ )
141 current = Quaternion( Radian( 0.0f ), Vector3::ZAXIS );
144 void GridRotationConstraint90( Quaternion& current, const PropertyInputContainer& /* inputs */ )
146 current = Quaternion( Radian( 1.5f * Math::PI ), Vector3::ZAXIS );
149 void GridRotationConstraint180( Quaternion& current, const PropertyInputContainer& /* inputs */ )
151 current = Quaternion( Radian( Math::PI ), Vector3::ZAXIS );
154 void GridRotationConstraint270( Quaternion& current, const PropertyInputContainer& /* inputs */ )
156 current = Quaternion( Radian( 0.5f * Math::PI ), Vector3::ZAXIS );
159 void GridColorConstraint( Vector4& current, const PropertyInputContainer& /* inputs */ )
161 current.r = current.g = current.b = 1.0f;
164 struct GridVisibilityConstraint
166 GridVisibilityConstraint(
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 ),
176 mColumnIndex( columnIndex ),
177 mNumberOfColumns( numberOfColumns ),
178 mRowSpacing( rowSpacing ),
179 mColumnSpacing( columnSpacing ),
180 mSideMargin( sideMargin )
184 void Portrait( bool& current, const PropertyInputContainer& inputs )
186 float layoutPosition = inputs[0]->GetFloat() + static_cast< float >( mItemId );
187 const Vector3& layoutSize = inputs[1]->GetVector3();
189 float row = ( layoutPosition - static_cast< float >( mColumnIndex ) ) / mNumberOfColumns;
190 int rowsPerPage = ceil( layoutSize.height / ( mItemSize.y + mRowSpacing ) );
192 current = ( row > -2.0f ) && ( row < rowsPerPage );
195 void Landscape( bool& current, const PropertyInputContainer& inputs )
197 float layoutPosition = inputs[0]->GetFloat() + static_cast< float >( mItemId );
198 const Vector3& layoutSize = inputs[1]->GetVector3();
200 float row = ( layoutPosition - static_cast< float >( mColumnIndex ) ) / mNumberOfColumns;
201 int rowsPerPage = ceil( layoutSize.width / ( mItemSize.y + mRowSpacing ) );
203 current = ( row > -2.0f ) && ( row < rowsPerPage );
209 unsigned int mItemId;
210 unsigned int mColumnIndex;
211 unsigned int mNumberOfColumns;
213 float mColumnSpacing;
217 } // unnamed namespace
228 struct GridLayout::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),
238 mScrollSpeedFactor(DEFAULT_SCROLL_SPEED_FACTOR),
239 mMaximumSwipeSpeed(DEFAULT_MAXIMUM_SWIPE_SPEED),
240 mItemFlickAnimationDuration(DEFAULT_ITEM_FLICK_ANIMATION_DURATION)
244 unsigned int mNumberOfColumns;
246 float mColumnSpacing;
252 float mScrollSpeedFactor;
253 float mMaximumSwipeSpeed;
254 float mItemFlickAnimationDuration;
257 GridLayoutPtr GridLayout::New()
259 return GridLayoutPtr(new GridLayout());
262 GridLayout::~GridLayout()
267 void GridLayout::SetNumberOfColumns(unsigned int columns)
269 mImpl->mNumberOfColumns = columns;
272 unsigned int GridLayout::GetNumberOfColumns() const
274 return mImpl->mNumberOfColumns;
277 void GridLayout::SetRowSpacing(float spacing)
279 mImpl->mRowSpacing = spacing;
282 float GridLayout::GetRowSpacing() const
284 return mImpl->mRowSpacing;
287 void GridLayout::SetColumnSpacing(float spacing)
289 mImpl->mColumnSpacing = spacing;
292 float GridLayout::GetColumnSpacing() const
294 return mImpl->mColumnSpacing;
297 void GridLayout::SetTopMargin(float margin)
299 mImpl->mTopMargin = margin;
302 float GridLayout::GetTopMargin() const
304 return mImpl->mTopMargin;
307 void GridLayout::SetBottomMargin(float margin)
309 mImpl->mBottomMargin = margin;
312 float GridLayout::GetBottomMargin() const
314 return mImpl->mBottomMargin;
317 void GridLayout::SetSideMargin(float margin)
319 mImpl->mSideMargin = margin;
322 float GridLayout::GetSideMargin() const
324 return mImpl->mSideMargin;
327 void GridLayout::SetZGap(float gap)
332 float GridLayout::GetZGap() const
337 void GridLayout::SetScrollSpeedFactor(float scrollSpeed)
339 mImpl->mScrollSpeedFactor = scrollSpeed;
342 void GridLayout::SetMaximumSwipeSpeed(float speed)
344 mImpl->mMaximumSwipeSpeed = speed;
347 void GridLayout::SetItemFlickAnimationDuration(float durationSeconds)
349 mImpl->mItemFlickAnimationDuration = durationSeconds;
352 float GridLayout::GetScrollSpeedFactor() const
354 return mImpl->mScrollSpeedFactor;
357 float GridLayout::GetMaximumSwipeSpeed() const
359 return mImpl->mMaximumSwipeSpeed;
362 float GridLayout::GetItemFlickAnimationDuration() const
364 return mImpl->mItemFlickAnimationDuration;
367 float GridLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
369 float layoutHeight = IsHorizontal( GetOrientation() ) ? layoutSize.width : layoutSize.height;
372 GetItemSize( 0, layoutSize, itemSize );
374 unsigned int itemsLastRow = numberOfItems % mImpl->mNumberOfColumns;
375 if (itemsLastRow == 0)
377 itemsLastRow = mImpl->mNumberOfColumns;
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);
383 return itemsLastPage - static_cast<float>(numberOfItems);
386 float GridLayout::GetClosestAnchorPosition(float layoutPosition) const
388 float rowIndex = static_cast<float>(round(layoutPosition / mImpl->mNumberOfColumns));
389 return rowIndex * static_cast<float>(mImpl->mNumberOfColumns);
392 float GridLayout::GetItemScrollToPosition(unsigned int itemId) const
394 float rowIndex = static_cast< float >( itemId ) / mImpl->mNumberOfColumns;
395 return -rowIndex * static_cast<float>(mImpl->mNumberOfColumns);
398 ItemRange GridLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
400 float layoutHeight = IsHorizontal( GetOrientation() ) ? layoutSize.width : layoutSize.height;
403 GetItemSize( 0, layoutSize, itemSize );
405 int itemsPerPage = mImpl->mNumberOfColumns * ceil(layoutHeight / (itemSize.y + mImpl->mRowSpacing));
406 int firstVisibleItem = -(static_cast<int>(firstItemPosition / mImpl->mNumberOfColumns)) * mImpl->mNumberOfColumns;
408 int firstItemIndex = std::max(0, firstVisibleItem - static_cast<int>(mImpl->mNumberOfColumns));
409 int lastItemIndex = std::max(0, firstVisibleItem + itemsPerPage);
411 return ItemRange(firstItemIndex, lastItemIndex);
414 float GridLayout::GetClosestOnScreenLayoutPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize)
416 Vector3 itemPosition = GetItemPosition( itemID, currentLayoutPosition, layoutSize );
418 ControlOrientation::Type orientation = GetOrientation();
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)
427 // item not within viewable area
428 float rowHeight = itemSize.y + mImpl->mRowSpacing;
429 Vector3 firstItemPosition = GetItemPosition( itemID, 0.0f, layoutSize );
431 switch( orientation )
433 case ControlOrientation::Up:
435 if(itemPosition.y > onScreenArea.y)
437 offset = ((layoutSize.y - rowHeight) * 0.5f) - firstItemPosition.y;
441 offset = ((-layoutSize.y + rowHeight) * 0.5f) - firstItemPosition.y;
445 case ControlOrientation::Down:
447 if(itemPosition.y < -onScreenArea.y)
449 offset = ((layoutSize.y - rowHeight) * 0.5f) - firstItemPosition.y;
453 offset = ((-layoutSize.y + rowHeight) * 0.5f) - firstItemPosition.y;
457 case ControlOrientation::Left:
459 if(itemPosition.x > onScreenArea.x)
461 offset = ((layoutSize.x - rowHeight) * 0.5f) - firstItemPosition.x;
465 offset = ((-layoutSize.x + rowHeight) * 0.5f) - firstItemPosition.x;
469 case ControlOrientation::Right:
471 if(itemPosition.x < -onScreenArea.x)
473 offset = ((layoutSize.x - rowHeight) * 0.5f) - firstItemPosition.x;
477 offset = ((-layoutSize.x + rowHeight) * 0.5f) - firstItemPosition.x;
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;
488 return currentLayoutPosition;
491 unsigned int GridLayout::GetReserveItemCount(Vector3 layoutSize) const
493 float layoutHeight = IsHorizontal( GetOrientation() ) ? layoutSize.width : layoutSize.height;
496 GetItemSize( 0, layoutSize, itemSize );
497 int itemsPerPage = mImpl->mNumberOfColumns * ceil(layoutHeight / (itemSize.y + mImpl->mRowSpacing));
501 void GridLayout::GetDefaultItemSize( unsigned int itemId, const Vector3& layoutSize, Vector3& itemSize ) const
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 );
507 itemSize.height = itemSize.depth = itemSize.width * 0.75f;
510 Degree GridLayout::GetScrollDirection() const
512 Degree scrollDirection(0.0f);
513 ControlOrientation::Type orientation = GetOrientation();
515 if ( orientation == ControlOrientation::Up )
517 scrollDirection = Degree( 0.0f );
519 else if ( orientation == ControlOrientation::Left )
521 scrollDirection = Degree( 90.0f );
523 else if ( orientation == ControlOrientation::Down )
525 scrollDirection = Degree( 180.0f );
527 else // orientation == ControlOrientation::Right
529 scrollDirection = Degree( 270.0f );
532 return scrollDirection;
535 void GridLayout::ApplyConstraints( Actor& actor, const int itemId, const Vector3& layoutSize, const Actor& itemViewActor )
537 if(HasLayoutChanged())
539 SetGridLayoutProperties(GetLayoutProperties());
541 // This just implements the default behaviour of constraint application.
542 // Custom layouts can override this function to apply their custom constraints.
543 Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast( itemViewActor );
547 GetItemSize( itemId, layoutSize, itemSize );
548 const unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
549 const ControlOrientation::Type orientation = GetOrientation();
551 // Position constraint
552 GridPositionConstraint positionConstraint( itemId,
554 mImpl->mNumberOfColumns,
556 mImpl->mColumnSpacing,
561 Constraint constraint;
562 if ( orientation == ControlOrientation::Up )
564 constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, positionConstraint, &GridPositionConstraint::Orientation0 );
566 else if ( orientation == ControlOrientation::Left )
568 constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, positionConstraint, &GridPositionConstraint::Orientation90 );
570 else if ( orientation == ControlOrientation::Down )
572 constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, positionConstraint, &GridPositionConstraint::Orientation180 );
574 else // orientation == ControlOrientation::Right
576 constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, positionConstraint, &GridPositionConstraint::Orientation270 );
578 constraint.AddSource( ParentSource( Toolkit::ItemView::Property::LAYOUT_POSITION ) );
579 constraint.AddSource( ParentSource( Actor::Property::SIZE ) );
582 // Rotation constraint
583 if ( orientation == ControlOrientation::Up )
585 constraint = Constraint::New< Quaternion >( actor, Actor::Property::ORIENTATION, &GridRotationConstraint0 );
587 else if ( orientation == ControlOrientation::Left )
589 constraint = Constraint::New< Quaternion >( actor, Actor::Property::ORIENTATION, &GridRotationConstraint90 );
591 else if ( orientation == ControlOrientation::Down )
593 constraint = Constraint::New< Quaternion >( actor, Actor::Property::ORIENTATION, &GridRotationConstraint180 );
595 else // orientation == ControlOrientation::Right
597 constraint = Constraint::New< Quaternion >( actor, Actor::Property::ORIENTATION, &GridRotationConstraint270 );
602 constraint = Constraint::New< Vector4 >( actor, Actor::Property::COLOR, &GridColorConstraint );
603 constraint.SetRemoveAction( Dali::Constraint::Discard );
606 // Visibility constraint
607 GridVisibilityConstraint visibilityConstraint( itemId,
609 mImpl->mNumberOfColumns,
611 mImpl->mColumnSpacing,
614 if ( IsVertical( orientation ) )
616 constraint = Constraint::New<bool>( actor, Actor::Property::VISIBLE, visibilityConstraint, &GridVisibilityConstraint::Portrait );
620 constraint = Constraint::New<bool>( actor, Actor::Property::VISIBLE, visibilityConstraint, &GridVisibilityConstraint::Landscape );
622 constraint.AddSource( ParentSource( Toolkit::ItemView::Property::LAYOUT_POSITION ) );
623 constraint.AddSource( ParentSource( Actor::Property::SIZE ) );
624 constraint.SetRemoveAction( Dali::Constraint::Discard );
629 void GridLayout::SetGridLayoutProperties(const Property::Map& properties)
631 // Set any properties specified for gridLayout.
632 for( unsigned int idx = 0, mapCount = properties.Count(); idx < mapCount; ++idx )
634 KeyValuePair propertyPair = properties.GetKeyValue( idx );
635 switch(DefaultItemLayoutProperty::Property(propertyPair.first.indexKey))
637 case DefaultItemLayoutProperty::GRID_COLUMN_NUMBER:
639 SetNumberOfColumns(propertyPair.second.Get<int>());
642 case DefaultItemLayoutProperty::GRID_ROW_SPACING:
644 SetRowSpacing(propertyPair.second.Get<float>());
647 case DefaultItemLayoutProperty::GRID_COLUMN_SPACING:
649 SetColumnSpacing(propertyPair.second.Get<float>());
652 case DefaultItemLayoutProperty::GRID_TOP_MARGIN:
654 SetTopMargin(propertyPair.second.Get<float>());
657 case DefaultItemLayoutProperty::GRID_BOTTOM_MARGIN:
659 SetBottomMargin(propertyPair.second.Get<float>());
662 case DefaultItemLayoutProperty::GRID_SIDE_MARGIN:
664 SetSideMargin(propertyPair.second.Get<float>());
667 case DefaultItemLayoutProperty::GRID_SCROLL_SPEED_FACTOR:
669 SetScrollSpeedFactor(propertyPair.second.Get<float>());
672 case DefaultItemLayoutProperty::GRID_MAXIMUM_SWIPE_SPEED:
674 SetMaximumSwipeSpeed(propertyPair.second.Get<float>());
677 case DefaultItemLayoutProperty::GRID_ITEM_FLICK_ANIMATION_DURATION:
679 SetItemFlickAnimationDuration(propertyPair.second.Get<float>());
688 ResetLayoutChangedFlag();
691 Vector3 GridLayout::GetItemPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize) const
693 Vector3 itemPosition = Vector3::ZERO;
694 const unsigned int columnIndex = itemID % mImpl->mNumberOfColumns;
695 const ControlOrientation::Type orientation = GetOrientation();
697 GetItemSize( itemID, layoutSize, itemSize );
699 GridPositionConstraint positionConstraintStruct( itemID,
701 mImpl->mNumberOfColumns,
703 mImpl->mColumnSpacing,
709 if ( orientation == ControlOrientation::Up )
711 positionConstraintStruct.Orientation0( itemPosition, currentLayoutPosition + itemID, layoutSize );
713 else if ( orientation == ControlOrientation::Left )
715 positionConstraintStruct.Orientation90( itemPosition, currentLayoutPosition + itemID, layoutSize );
717 else if ( orientation == ControlOrientation::Down )
719 positionConstraintStruct.Orientation180( itemPosition, currentLayoutPosition + itemID, layoutSize );
721 else // orientation == ControlOrientation::Right
723 positionConstraintStruct.Orientation270( itemPosition, currentLayoutPosition + itemID, layoutSize );
729 int GridLayout::GetNextFocusItemID(int itemID, int maxItems, Dali::Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
733 case Toolkit::Control::KeyboardFocus::LEFT:
738 itemID = loopEnabled ? maxItems - 1 : 0;
742 case Toolkit::Control::KeyboardFocus::UP:
744 itemID -= mImpl->mNumberOfColumns;
747 itemID = loopEnabled ? itemID + maxItems : itemID + mImpl->mNumberOfColumns;
751 case Toolkit::Control::KeyboardFocus::RIGHT:
754 if( itemID >= maxItems )
756 itemID = loopEnabled ? 0 : maxItems - 1;
760 case Toolkit::Control::KeyboardFocus::DOWN:
762 itemID += mImpl->mNumberOfColumns;
763 if( itemID >= maxItems )
765 itemID = loopEnabled ? 0 : itemID - mImpl->mNumberOfColumns;
777 GridLayout::GridLayout()
783 } // namespace Internal
785 } // namespace Toolkit