2 * Copyright (c) 2014 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.
20 #include <dali-toolkit/public-api/controls/scrollable/item-view/navigation-layout.h>
22 using namespace Dali::Toolkit;
24 namespace // unnamed namespace
26 const unsigned int DEFAULT_NUMBER_OF_COLUMNS = 3;
27 const float DEFAULT_TOP_MARGIN = 0.3f;
28 const float DEFAULT_BOTTOM_MARGIN = 0.3f;
29 const float DEFAULT_SIDE_MARGIN = 0.2f;
30 const float DEFAULT_COLUMN_SPACING = 20.0f;
31 const float DEFAULT_ROW_SPACING = 20.0f;
32 const float DEFAULT_SCROLL_SPEED_FACTOR = 0.01f;
33 const float DEFAULT_MAXIMUM_SWIPE_SPEED = 3.0f;
34 const float DEFAULT_ITEM_FLICK_ANIMATION_DURATION = 0.05f;
35 const float DEFAULT_SIZE_EXTEND = 1.4f;
36 const float DEFAULT_HEIGHT_FACTOR = 0.6f;
38 // 4 orientations are supported
39 struct NavigationPositionConstraintUp
41 NavigationPositionConstraintUp(const unsigned int columnIndex,
42 const unsigned int numberOfColumns,
43 const float columnSpacing,
44 const float sizeExtend,
45 const float bottomMargin,
46 const float topMargin)
47 : mColumnIndex(columnIndex),
48 mNumberOfColumns(numberOfColumns),
49 mColumnSpacing(columnSpacing),
50 mSizeExtend(sizeExtend),
51 mBottomMargin(bottomMargin),
56 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
58 float itemWidth = (layoutSize.width * mSizeExtend- mColumnSpacing * (mNumberOfColumns - 1))/( mNumberOfColumns );
62 float z = (sinf((layoutPosition + 1.0f) * Math::PI *0.5f) - 1.0f) * itemWidth * 2.0f;
64 itemPosition = Vector3( (layoutPosition + 1.0f) * (itemWidth + mColumnSpacing) + itemWidth * 0.5f - layoutSize.width * mSizeExtend * 0.5f,
65 (- mBottomMargin + mTopMargin) * layoutSize.width * 0.5f ,
71 unsigned int mColumnIndex;
72 unsigned int mNumberOfColumns;
79 struct NavigationPositionConstraintLeft
81 NavigationPositionConstraintLeft(const unsigned int columnIndex,
82 const unsigned int numberOfColumns,
83 const float columnSpacing,
84 const float sizeExtend,
85 const float bottomMargin,
86 const float topMargin)
87 : mColumnIndex(columnIndex),
88 mNumberOfColumns(numberOfColumns),
89 mColumnSpacing(columnSpacing),
90 mSizeExtend(sizeExtend),
91 mBottomMargin(bottomMargin),
96 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
98 float itemWidth = (DEFAULT_HEIGHT_FACTOR * layoutSize.height * mSizeExtend- mColumnSpacing * (mNumberOfColumns - 1))/( mNumberOfColumns );
100 float z = (sinf((layoutPosition + 1.0f) * Math::PI *0.5f) - 1.0f) * itemWidth * 1.5f;
101 itemPosition = Vector3( (- mBottomMargin + mTopMargin) * 0.5f * layoutSize.width ,
102 -((layoutPosition+ 1.0) * (itemWidth + mColumnSpacing) + itemWidth * 0.5f - DEFAULT_HEIGHT_FACTOR * layoutSize.height * mSizeExtend * 0.5f ),
108 unsigned int mColumnIndex;
109 unsigned int mNumberOfColumns;
110 float mColumnSpacing;
116 struct NavigationPositionConstraintDown
118 NavigationPositionConstraintDown(const unsigned int columnIndex,
119 const unsigned int numberOfColumns,
120 const float columnSpacing,
121 const float sizeExtend,
122 const float bottomMargin,
123 const float topMargin)
124 : mColumnIndex(columnIndex),
125 mNumberOfColumns(numberOfColumns),
126 mColumnSpacing(columnSpacing),
127 mSizeExtend(sizeExtend),
128 mBottomMargin(bottomMargin),
129 mTopMargin(topMargin)
133 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
135 float itemWidth = (layoutSize.width * mSizeExtend- mColumnSpacing * (mNumberOfColumns - 1))/( mNumberOfColumns );
136 Vector3 itemPosition;
138 float z = (sinf((layoutPosition + 1.0f ) * Math::PI *0.5f) - 1.0f) * itemWidth * 2.0f;
139 itemPosition = Vector3( -((layoutPosition + 1.0f) * (itemWidth + mColumnSpacing) + itemWidth * 0.5f - layoutSize.width * mSizeExtend * 0.5f),
140 (- mBottomMargin + mTopMargin)* layoutSize.width * 0.5f,
146 unsigned int mColumnIndex;
147 unsigned int mNumberOfColumns;
148 float mColumnSpacing;
154 struct NavigationPositionConstraintRight
156 NavigationPositionConstraintRight(const unsigned int columnIndex,
157 const unsigned int numberOfColumns,
158 const float columnSpacing,
159 const float sizeExtend,
160 const float bottomMargin,
161 const float topMargin)
162 : mColumnIndex(columnIndex),
163 mNumberOfColumns(numberOfColumns),
164 mColumnSpacing(columnSpacing),
165 mSizeExtend(sizeExtend),
166 mBottomMargin(bottomMargin),
167 mTopMargin(topMargin)
171 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
173 float itemWidth = (DEFAULT_HEIGHT_FACTOR * layoutSize.height * mSizeExtend- mColumnSpacing * (mNumberOfColumns - 1))/( mNumberOfColumns );
174 Vector3 itemPosition;
175 float z = (sinf((layoutPosition + 1.0f) * Math::PI *0.5f) - 1.0f) * itemWidth * 1.5f;
176 itemPosition = Vector3( (- mBottomMargin + mTopMargin) * layoutSize.width * 0.5f,
177 ((layoutPosition + 1.0f) * (itemWidth + mColumnSpacing) + itemWidth * 0.5f - DEFAULT_HEIGHT_FACTOR * layoutSize.height * mSizeExtend *0.5f ),
183 unsigned int mColumnIndex;
184 unsigned int mNumberOfColumns;
185 float mColumnSpacing;
191 struct NavigationRotationConstraintUp
193 Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
196 float _layoutPosition = layoutPosition + 1.0f;
197 if(_layoutPosition >= 1.0f)
199 angle = - sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
203 angle = sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
205 return Quaternion(angle, Vector3::YAXIS);
210 struct NavigationRotationConstraintLeft
212 Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
215 float _layoutPosition = layoutPosition + 1.0f;
216 if(_layoutPosition >= 1.0f)
218 angle = - sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
222 angle = sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
224 return Quaternion(Math::PI * 0.5f, Vector3::ZAXIS) * Quaternion(angle, Vector3::YAXIS);
228 struct NavigationRotationConstraintDown
230 Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
233 float _layoutPosition = layoutPosition + 1.0f;
234 if(_layoutPosition >= 1.0f)//right side
236 //rotation angle by z axis
237 angle = - sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
241 angle = sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
243 return Quaternion(Math::PI, Vector3::ZAXIS) * Quaternion(angle, Vector3::YAXIS);
247 struct NavigationRotationConstraintRight
249 Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
252 float _layoutPosition = layoutPosition + 1.0f;
253 if(_layoutPosition >= 1.0f)
255 angle = - sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
259 angle = sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
261 return Quaternion(Math::PI * 1.5f, Vector3::ZAXIS) * Quaternion(angle, Vector3::YAXIS);
265 struct NavigationColorConstraint
267 NavigationColorConstraint(unsigned int numberOfColumns)
268 : mNumberOfColumns(numberOfColumns)
272 Vector4 operator()(const Vector4& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
274 float darkness = 1.0f;
277 float pos = ( layoutPosition + 1.0f);
278 darkness = (-0.25f) * (pos + 1.0f) * (pos + 1.0f) + 1.0f * (pos + 1.0f) + 0.2f;
280 darkness = fabs(darkness);
283 return Vector4(darkness, darkness, darkness, current.a * alpha);
285 unsigned int mNumberOfColumns;
289 struct NavigationVisibilityConstraint
291 NavigationVisibilityConstraint(const unsigned int columnIndex,
292 const unsigned int numberOfColumns,
293 const float columnSpacing )
294 : mColumnIndex(columnIndex),
295 mNumberOfColumns(numberOfColumns),
296 mColumnSpacing(columnSpacing)
300 bool operator()(const bool& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
302 float index = layoutPosition + 1.0f;
303 return (index >= -1.0f) && (index <= mNumberOfColumns );
307 unsigned int mColumnIndex;
308 unsigned int mNumberOfColumns;
309 float mColumnSpacing;
317 struct NavigationLayout::Impl
320 : mNumberOfColumns(DEFAULT_NUMBER_OF_COLUMNS),
321 mColumnSpacing(DEFAULT_COLUMN_SPACING),
322 mTopMargin(DEFAULT_TOP_MARGIN),
323 mBottomMargin(DEFAULT_BOTTOM_MARGIN),
324 mSideMargin(DEFAULT_SIDE_MARGIN),
325 mScrollSpeedFactor(DEFAULT_SCROLL_SPEED_FACTOR),
326 mMaximumSwipeSpeed(DEFAULT_MAXIMUM_SWIPE_SPEED),
327 mItemFlickAnimationDuration(DEFAULT_ITEM_FLICK_ANIMATION_DURATION),
328 mSizeExtend(DEFAULT_SIZE_EXTEND)
330 mColorConstraint = NavigationColorConstraint(mNumberOfColumns);
331 mRotationConstraint[0] = NavigationRotationConstraintUp();
332 mRotationConstraint[1] = NavigationRotationConstraintLeft();
333 mRotationConstraint[2] = NavigationRotationConstraintDown();
334 mRotationConstraint[3] = NavigationRotationConstraintRight();
337 unsigned int mNumberOfColumns;
338 float mColumnSpacing;
342 float mScrollSpeedFactor;
343 float mMaximumSwipeSpeed;
344 float mItemFlickAnimationDuration;
347 ItemLayout::QuaternionFunction mRotationConstraint[4];
349 ItemLayout::Vector4Function mColorConstraint;
352 NavigationLayoutPtr NavigationLayout::New()
354 return NavigationLayoutPtr(new NavigationLayout());
357 NavigationLayout::~NavigationLayout()
362 void NavigationLayout::SetNumberOfColumns(unsigned int columns)
364 mImpl->mNumberOfColumns = columns;
367 unsigned int NavigationLayout::GetNumberOfColumns() const
369 return mImpl->mNumberOfColumns;
372 void NavigationLayout::SetColumnSpacing(float spacing)
374 mImpl->mColumnSpacing = spacing;
377 float NavigationLayout::GetColumnSpacing() const
379 return mImpl->mColumnSpacing;
382 void NavigationLayout::SetTopMargin(float margin)
384 mImpl->mTopMargin = margin;
387 float NavigationLayout::GetTopMargin() const
389 return mImpl->mTopMargin;
392 void NavigationLayout::SetBottomMargin(float margin)
394 mImpl->mBottomMargin = margin;
397 float NavigationLayout::GetBottomMargin() const
399 return mImpl->mBottomMargin;
402 void NavigationLayout::SetSideMargin(float margin)
404 mImpl->mSideMargin = margin;
405 mImpl->mSizeExtend = (1.0f - margin) * 3.0f;
408 void NavigationLayout::SetScrollSpeedFactor(float scrollSpeed)
410 mImpl->mScrollSpeedFactor = scrollSpeed;
413 void NavigationLayout::SetMaximumSwipeSpeed(float speed)
415 mImpl->mMaximumSwipeSpeed = speed;
418 void NavigationLayout::SetItemFlickAnimationDuration(float durationSeconds)
420 mImpl->mItemFlickAnimationDuration = durationSeconds;
423 float NavigationLayout::GetScrollSpeedFactor() const
425 return mImpl->mScrollSpeedFactor;
428 float NavigationLayout::GetMaximumSwipeSpeed() const
430 return mImpl->mMaximumSwipeSpeed;
433 float NavigationLayout::GetItemFlickAnimationDuration() const
435 return mImpl->mItemFlickAnimationDuration;
438 float NavigationLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
440 unsigned int itemsLastRow = numberOfItems % mImpl->mNumberOfColumns;
441 if (itemsLastRow == 0)
443 itemsLastRow = mImpl->mNumberOfColumns;
446 float itemsLastPage = static_cast<float>(itemsLastRow);
447 return itemsLastPage - static_cast<float>(numberOfItems) - 2.0f;
451 float NavigationLayout::GetClosestAnchorPosition(float layoutPosition) const
453 return round(layoutPosition);
456 float NavigationLayout::GetItemScrollToPosition(unsigned int itemId) const
458 return - static_cast<float>(itemId);
461 ItemRange NavigationLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
463 int itemsPerPage = mImpl->mNumberOfColumns;
465 int firstItemIndex = std::max(0.0f, -firstItemPosition -1.0f );
466 int lastItemIndex = std::max(0.0f, -(firstItemPosition) + itemsPerPage );
468 return ItemRange(firstItemIndex , lastItemIndex );
471 unsigned int NavigationLayout::GetReserveItemCount(Vector3 layoutSize) const
473 float layoutWidth = IsHorizontal(mOrientation) ? layoutSize.height : layoutSize.width;
474 float itemWidth = (layoutWidth * mImpl->mSizeExtend - mImpl->mColumnSpacing * (mImpl->mNumberOfColumns - 1))/( mImpl->mNumberOfColumns );
475 return static_cast<unsigned int>(layoutWidth / itemWidth);
478 bool NavigationLayout::GetItemSize(unsigned int itemId, Vector3 layoutSize, Vector3& itemSize) const
480 float layoutWidth = IsHorizontal(mOrientation) ? (DEFAULT_HEIGHT_FACTOR * layoutSize.height) : layoutSize.width;
481 layoutWidth = layoutWidth * mImpl->mSizeExtend;
483 float itemWidth = (layoutWidth - mImpl->mColumnSpacing*(mImpl->mNumberOfColumns-1)) / mImpl->mNumberOfColumns;
484 float itemHeight = layoutWidth * (1.0f - mImpl->mBottomMargin - mImpl->mTopMargin);
485 itemSize = Vector3(itemWidth, itemHeight, (itemWidth/4)*3);
490 void NavigationLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 size, float durationSeconds) const
494 bool NavigationLayout::GetPositionConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
496 unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
497 if (mOrientation == ControlOrientation::Left)
499 constraint = NavigationPositionConstraintLeft(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
501 else if (mOrientation == ControlOrientation::Up)
503 constraint = NavigationPositionConstraintUp(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
505 else if (mOrientation == ControlOrientation::Down)
507 constraint = NavigationPositionConstraintDown(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
509 else if (mOrientation == ControlOrientation::Right)
511 constraint = NavigationPositionConstraintRight(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
517 bool NavigationLayout::GetScaleConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
519 return false; // No scaling
522 bool NavigationLayout::GetRotationConstraint(unsigned int itemId, ItemLayout::QuaternionFunction& constraint) const
524 constraint = mImpl->mRotationConstraint[mOrientation];
528 bool NavigationLayout::GetColorConstraint(unsigned int itemId, ItemLayout::Vector4Function& constraint) const
530 constraint = mImpl->mColorConstraint;
534 bool NavigationLayout::GetVisibilityConstraint(unsigned int itemId, ItemLayout::BoolFunction& constraint) const
536 unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
537 constraint = NavigationVisibilityConstraint(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing);
541 Degree NavigationLayout::GetScrollDirection() const
543 Degree scrollDirection(0);
544 if (mOrientation == ControlOrientation::Down)
546 scrollDirection = 0.0f - 45.0f;
548 else if (mOrientation == ControlOrientation::Right)
550 scrollDirection = 90.0f - 45.0f;
552 else if (mOrientation == ControlOrientation::Up)
554 scrollDirection = 180.0f - 45.0f;
556 else // mOrientation == ControlOrientation::Left
558 scrollDirection = 270.0f - 45.0f;
561 return scrollDirection;
564 NavigationLayout::NavigationLayout()