2 * Copyright (c) 2021 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>
22 #include <dali/public-api/animation/animation.h>
23 #include <dali/public-api/animation/constraint.h>
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>
31 using namespace Dali::Toolkit;
33 namespace // unnamed namespace
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;
45 struct GridPositionConstraint
47 GridPositionConstraint(
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,
57 : mItemSize(itemSize),
59 mColumnIndex(columnIndex),
60 mNumberOfColumns(numberOfColumns),
61 mRowSpacing(rowSpacing),
62 mColumnSpacing(columnSpacing),
63 mTopMargin(topMargin),
64 mSideMargin(sideMargin),
69 inline void Orientation0(Vector3& current, float layoutPosition, const Vector3& layoutSize)
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;
76 inline void Orientation90(Vector3& current, float layoutPosition, const Vector3& layoutSize)
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;
83 inline void Orientation180(Vector3& current, float layoutPosition, const Vector3& layoutSize)
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;
90 inline void Orientation270(Vector3& current, float layoutPosition, const Vector3& layoutSize)
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;
97 void Orientation0(Vector3& current, const PropertyInputContainer& inputs)
99 float layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
100 const Vector3& layoutSize = inputs[1]->GetVector3();
101 Orientation0(current, layoutPosition, layoutSize);
104 void Orientation90(Vector3& current, const PropertyInputContainer& inputs)
106 float layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
107 const Vector3& layoutSize = inputs[1]->GetVector3();
108 Orientation90(current, layoutPosition, layoutSize);
111 void Orientation180(Vector3& current, const PropertyInputContainer& inputs)
113 float layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
114 const Vector3& layoutSize = inputs[1]->GetVector3();
115 Orientation180(current, layoutPosition, layoutSize);
118 void Orientation270(Vector3& current, const PropertyInputContainer& inputs)
120 float layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
121 const Vector3& layoutSize = inputs[1]->GetVector3();
122 Orientation270(current, layoutPosition, layoutSize);
127 unsigned int mItemId;
128 unsigned int mColumnIndex;
129 unsigned int mNumberOfColumns;
131 float mColumnSpacing;
137 void GridRotationConstraint0(Quaternion& current, const PropertyInputContainer& /* inputs */)
139 current = Quaternion(Radian(0.0f), Vector3::ZAXIS);
142 void GridRotationConstraint90(Quaternion& current, const PropertyInputContainer& /* inputs */)
144 current = Quaternion(Radian(1.5f * Math::PI), Vector3::ZAXIS);
147 void GridRotationConstraint180(Quaternion& current, const PropertyInputContainer& /* inputs */)
149 current = Quaternion(Radian(Math::PI), Vector3::ZAXIS);
152 void GridRotationConstraint270(Quaternion& current, const PropertyInputContainer& /* inputs */)
154 current = Quaternion(Radian(0.5f * Math::PI), Vector3::ZAXIS);
157 void GridColorConstraint(Vector4& current, const PropertyInputContainer& /* inputs */)
159 current.r = current.g = current.b = 1.0f;
162 struct GridVisibilityConstraint
164 GridVisibilityConstraint(
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),
174 mColumnIndex(columnIndex),
175 mNumberOfColumns(numberOfColumns),
176 mRowSpacing(rowSpacing),
177 mColumnSpacing(columnSpacing),
178 mSideMargin(sideMargin)
182 void Portrait(bool& current, const PropertyInputContainer& inputs)
184 float layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
185 const Vector3& layoutSize = inputs[1]->GetVector3();
187 float row = (layoutPosition - static_cast<float>(mColumnIndex)) / mNumberOfColumns;
188 int rowsPerPage = ceil(layoutSize.height / (mItemSize.y + mRowSpacing));
190 current = (row > -2.0f) && (row < rowsPerPage);
193 void Landscape(bool& current, const PropertyInputContainer& inputs)
195 float layoutPosition = inputs[0]->GetFloat() + static_cast<float>(mItemId);
196 const Vector3& layoutSize = inputs[1]->GetVector3();
198 float row = (layoutPosition - static_cast<float>(mColumnIndex)) / mNumberOfColumns;
199 int rowsPerPage = ceil(layoutSize.width / (mItemSize.y + mRowSpacing));
201 current = (row > -2.0f) && (row < rowsPerPage);
206 unsigned int mItemId;
207 unsigned int mColumnIndex;
208 unsigned int mNumberOfColumns;
210 float mColumnSpacing;
214 } // unnamed namespace
222 struct GridLayout::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),
232 mScrollSpeedFactor(DEFAULT_SCROLL_SPEED_FACTOR),
233 mMaximumSwipeSpeed(DEFAULT_MAXIMUM_SWIPE_SPEED),
234 mItemFlickAnimationDuration(DEFAULT_ITEM_FLICK_ANIMATION_DURATION)
238 unsigned int mNumberOfColumns;
240 float mColumnSpacing;
246 float mScrollSpeedFactor;
247 float mMaximumSwipeSpeed;
248 float mItemFlickAnimationDuration;
251 GridLayoutPtr GridLayout::New()
253 return GridLayoutPtr(new GridLayout());
256 GridLayout::~GridLayout()
261 void GridLayout::SetNumberOfColumns(unsigned int columns)
263 mImpl->mNumberOfColumns = columns;
266 unsigned int GridLayout::GetNumberOfColumns() const
268 return mImpl->mNumberOfColumns;
271 void GridLayout::SetRowSpacing(float spacing)
273 mImpl->mRowSpacing = spacing;
276 float GridLayout::GetRowSpacing() const
278 return mImpl->mRowSpacing;
281 void GridLayout::SetColumnSpacing(float spacing)
283 mImpl->mColumnSpacing = spacing;
286 float GridLayout::GetColumnSpacing() const
288 return mImpl->mColumnSpacing;
291 void GridLayout::SetTopMargin(float margin)
293 mImpl->mTopMargin = margin;
296 float GridLayout::GetTopMargin() const
298 return mImpl->mTopMargin;
301 void GridLayout::SetBottomMargin(float margin)
303 mImpl->mBottomMargin = margin;
306 float GridLayout::GetBottomMargin() const
308 return mImpl->mBottomMargin;
311 void GridLayout::SetSideMargin(float margin)
313 mImpl->mSideMargin = margin;
316 float GridLayout::GetSideMargin() const
318 return mImpl->mSideMargin;
321 void GridLayout::SetZGap(float gap)
326 float GridLayout::GetZGap() const
331 void GridLayout::SetScrollSpeedFactor(float scrollSpeed)
333 mImpl->mScrollSpeedFactor = scrollSpeed;
336 void GridLayout::SetMaximumSwipeSpeed(float speed)
338 mImpl->mMaximumSwipeSpeed = speed;
341 void GridLayout::SetItemFlickAnimationDuration(float durationSeconds)
343 mImpl->mItemFlickAnimationDuration = durationSeconds;
346 float GridLayout::GetScrollSpeedFactor() const
348 return mImpl->mScrollSpeedFactor;
351 float GridLayout::GetMaximumSwipeSpeed() const
353 return mImpl->mMaximumSwipeSpeed;
356 float GridLayout::GetItemFlickAnimationDuration() const
358 return mImpl->mItemFlickAnimationDuration;
361 float GridLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
363 float layoutHeight = IsHorizontal(GetOrientation()) ? layoutSize.width : layoutSize.height;
366 GetItemSize(0, layoutSize, itemSize);
368 unsigned int itemsLastRow = numberOfItems % mImpl->mNumberOfColumns;
369 if(itemsLastRow == 0)
371 itemsLastRow = mImpl->mNumberOfColumns;
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);
377 return itemsLastPage - static_cast<float>(numberOfItems);
380 float GridLayout::GetClosestAnchorPosition(float layoutPosition) const
382 float rowIndex = static_cast<float>(round(layoutPosition / mImpl->mNumberOfColumns));
383 return rowIndex * static_cast<float>(mImpl->mNumberOfColumns);
386 float GridLayout::GetItemScrollToPosition(unsigned int itemId) const
388 float rowIndex = static_cast<float>(itemId) / mImpl->mNumberOfColumns;
389 return -rowIndex * static_cast<float>(mImpl->mNumberOfColumns);
392 ItemRange GridLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
394 float layoutHeight = IsHorizontal(GetOrientation()) ? layoutSize.width : layoutSize.height;
397 GetItemSize(0, layoutSize, itemSize);
399 int itemsPerPage = mImpl->mNumberOfColumns * ceil(layoutHeight / (itemSize.y + mImpl->mRowSpacing));
400 int firstVisibleItem = -(static_cast<int>(firstItemPosition / mImpl->mNumberOfColumns)) * mImpl->mNumberOfColumns;
402 int firstItemIndex = std::max(0, firstVisibleItem - static_cast<int>(mImpl->mNumberOfColumns));
403 int lastItemIndex = std::max(0, firstVisibleItem + itemsPerPage);
405 return ItemRange(firstItemIndex, lastItemIndex);
408 float GridLayout::GetClosestOnScreenLayoutPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize)
410 Vector3 itemPosition = GetItemPosition(itemID, currentLayoutPosition, layoutSize);
412 ControlOrientation::Type orientation = GetOrientation();
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)
418 // item not within viewable area
419 float rowHeight = itemSize.y + mImpl->mRowSpacing;
420 Vector3 firstItemPosition = GetItemPosition(itemID, 0.0f, layoutSize);
424 case ControlOrientation::Up:
426 if(itemPosition.y > onScreenArea.y)
428 offset = ((layoutSize.y - rowHeight) * 0.5f) - firstItemPosition.y;
432 offset = ((-layoutSize.y + rowHeight) * 0.5f) - firstItemPosition.y;
436 case ControlOrientation::Down:
438 if(itemPosition.y < -onScreenArea.y)
440 offset = ((layoutSize.y - rowHeight) * 0.5f) - firstItemPosition.y;
444 offset = ((-layoutSize.y + rowHeight) * 0.5f) - firstItemPosition.y;
448 case ControlOrientation::Left:
450 if(itemPosition.x > onScreenArea.x)
452 offset = ((layoutSize.x - rowHeight) * 0.5f) - firstItemPosition.x;
456 offset = ((-layoutSize.x + rowHeight) * 0.5f) - firstItemPosition.x;
460 case ControlOrientation::Right:
462 if(itemPosition.x < -onScreenArea.x)
464 offset = ((layoutSize.x - rowHeight) * 0.5f) - firstItemPosition.x;
468 offset = ((-layoutSize.x + rowHeight) * 0.5f) - firstItemPosition.x;
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;
479 return currentLayoutPosition;
482 unsigned int GridLayout::GetReserveItemCount(Vector3 layoutSize) const
484 float layoutHeight = IsHorizontal(GetOrientation()) ? layoutSize.width : layoutSize.height;
487 GetItemSize(0, layoutSize, itemSize);
488 int itemsPerPage = mImpl->mNumberOfColumns * ceil(layoutHeight / (itemSize.y + mImpl->mRowSpacing));
492 void GridLayout::GetDefaultItemSize(unsigned int itemId, const Vector3& layoutSize, Vector3& itemSize) const
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);
498 itemSize.height = itemSize.depth = itemSize.width * 0.75f;
501 Degree GridLayout::GetScrollDirection() const
503 Degree scrollDirection(0.0f);
504 ControlOrientation::Type orientation = GetOrientation();
506 if(orientation == ControlOrientation::Up)
508 scrollDirection = Degree(0.0f);
510 else if(orientation == ControlOrientation::Left)
512 scrollDirection = Degree(90.0f);
514 else if(orientation == ControlOrientation::Down)
516 scrollDirection = Degree(180.0f);
518 else // orientation == ControlOrientation::Right
520 scrollDirection = Degree(270.0f);
523 return scrollDirection;
526 void GridLayout::ApplyConstraints(Actor& actor, const int itemId, const Vector3& layoutSize, const Actor& itemViewActor)
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);
534 GetItemSize(itemId, layoutSize, itemSize);
535 const unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
536 const ControlOrientation::Type orientation = GetOrientation();
538 // Position constraint
539 GridPositionConstraint positionConstraint(itemId,
541 mImpl->mNumberOfColumns,
543 mImpl->mColumnSpacing,
548 Constraint constraint;
549 if(orientation == ControlOrientation::Up)
551 constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, positionConstraint, &GridPositionConstraint::Orientation0);
553 else if(orientation == ControlOrientation::Left)
555 constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, positionConstraint, &GridPositionConstraint::Orientation90);
557 else if(orientation == ControlOrientation::Down)
559 constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, positionConstraint, &GridPositionConstraint::Orientation180);
561 else // orientation == ControlOrientation::Right
563 constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, positionConstraint, &GridPositionConstraint::Orientation270);
565 constraint.AddSource(ParentSource(Toolkit::ItemView::Property::LAYOUT_POSITION));
566 constraint.AddSource(ParentSource(Actor::Property::SIZE));
569 // Rotation constraint
570 if(orientation == ControlOrientation::Up)
572 constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, &GridRotationConstraint0);
574 else if(orientation == ControlOrientation::Left)
576 constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, &GridRotationConstraint90);
578 else if(orientation == ControlOrientation::Down)
580 constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, &GridRotationConstraint180);
582 else // orientation == ControlOrientation::Right
584 constraint = Constraint::New<Quaternion>(actor, Actor::Property::ORIENTATION, &GridRotationConstraint270);
589 constraint = Constraint::New<Vector4>(actor, Actor::Property::COLOR, &GridColorConstraint);
590 constraint.SetRemoveAction(Dali::Constraint::DISCARD);
593 // Visibility constraint
594 GridVisibilityConstraint visibilityConstraint(itemId,
596 mImpl->mNumberOfColumns,
598 mImpl->mColumnSpacing,
601 if(IsVertical(orientation))
603 constraint = Constraint::New<bool>(actor, Actor::Property::VISIBLE, visibilityConstraint, &GridVisibilityConstraint::Portrait);
607 constraint = Constraint::New<bool>(actor, Actor::Property::VISIBLE, visibilityConstraint, &GridVisibilityConstraint::Landscape);
609 constraint.AddSource(ParentSource(Toolkit::ItemView::Property::LAYOUT_POSITION));
610 constraint.AddSource(ParentSource(Actor::Property::SIZE));
611 constraint.SetRemoveAction(Dali::Constraint::DISCARD);
616 void GridLayout::SetGridLayoutProperties(const Property::Map& properties)
618 // Set any properties specified for gridLayout.
619 for(unsigned int idx = 0, mapCount = properties.Count(); idx < mapCount; ++idx)
621 KeyValuePair propertyPair = properties.GetKeyValue(idx);
622 switch(DefaultItemLayoutProperty::Property(propertyPair.first.indexKey))
624 case DefaultItemLayoutProperty::GRID_COLUMN_NUMBER:
626 SetNumberOfColumns(propertyPair.second.Get<int>());
629 case DefaultItemLayoutProperty::GRID_ROW_SPACING:
631 SetRowSpacing(propertyPair.second.Get<float>());
634 case DefaultItemLayoutProperty::GRID_COLUMN_SPACING:
636 SetColumnSpacing(propertyPair.second.Get<float>());
639 case DefaultItemLayoutProperty::GRID_TOP_MARGIN:
641 SetTopMargin(propertyPair.second.Get<float>());
644 case DefaultItemLayoutProperty::GRID_BOTTOM_MARGIN:
646 SetBottomMargin(propertyPair.second.Get<float>());
649 case DefaultItemLayoutProperty::GRID_SIDE_MARGIN:
651 SetSideMargin(propertyPair.second.Get<float>());
654 case DefaultItemLayoutProperty::GRID_SCROLL_SPEED_FACTOR:
656 SetScrollSpeedFactor(propertyPair.second.Get<float>());
659 case DefaultItemLayoutProperty::GRID_MAXIMUM_SWIPE_SPEED:
661 SetMaximumSwipeSpeed(propertyPair.second.Get<float>());
664 case DefaultItemLayoutProperty::GRID_ITEM_FLICK_ANIMATION_DURATION:
666 SetItemFlickAnimationDuration(propertyPair.second.Get<float>());
677 Vector3 GridLayout::GetItemPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize) const
679 Vector3 itemPosition = Vector3::ZERO;
680 const unsigned int columnIndex = itemID % mImpl->mNumberOfColumns;
681 const ControlOrientation::Type orientation = GetOrientation();
683 GetItemSize(itemID, layoutSize, itemSize);
685 GridPositionConstraint positionConstraintStruct(itemID,
687 mImpl->mNumberOfColumns,
689 mImpl->mColumnSpacing,
695 if(orientation == ControlOrientation::Up)
697 positionConstraintStruct.Orientation0(itemPosition, currentLayoutPosition + itemID, layoutSize);
699 else if(orientation == ControlOrientation::Left)
701 positionConstraintStruct.Orientation90(itemPosition, currentLayoutPosition + itemID, layoutSize);
703 else if(orientation == ControlOrientation::Down)
705 positionConstraintStruct.Orientation180(itemPosition, currentLayoutPosition + itemID, layoutSize);
707 else // orientation == ControlOrientation::Right
709 positionConstraintStruct.Orientation270(itemPosition, currentLayoutPosition + itemID, layoutSize);
715 int GridLayout::GetNextFocusItemID(int itemID, int maxItems, Dali::Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
719 case Toolkit::Control::KeyboardFocus::LEFT:
724 itemID = loopEnabled ? maxItems - 1 : 0;
728 case Toolkit::Control::KeyboardFocus::UP:
730 itemID -= mImpl->mNumberOfColumns;
733 itemID = loopEnabled ? itemID + maxItems : itemID + mImpl->mNumberOfColumns;
737 case Toolkit::Control::KeyboardFocus::RIGHT:
740 if(itemID >= maxItems)
742 itemID = loopEnabled ? 0 : maxItems - 1;
746 case Toolkit::Control::KeyboardFocus::DOWN:
748 itemID += mImpl->mNumberOfColumns;
749 if(itemID >= maxItems)
751 itemID = loopEnabled ? 0 : itemID - mImpl->mNumberOfColumns;
763 GridLayout::GridLayout()
769 } // namespace Internal
771 } // namespace Toolkit