2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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/public-api/controls/scrollable/item-view/navigation-layout.h>
21 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;
351 NavigationLayout::NavigationSignalV2 mSignalPanV2;/*the signal to notify the application the selected item*/
354 NavigationLayoutPtr NavigationLayout::New()
356 return NavigationLayoutPtr(new NavigationLayout());
359 NavigationLayout::~NavigationLayout()
364 void NavigationLayout::SetNumberOfColumns(unsigned int columns)
366 mImpl->mNumberOfColumns = columns;
369 unsigned int NavigationLayout::GetNumberOfColumns() const
371 return mImpl->mNumberOfColumns;
374 void NavigationLayout::SetColumnSpacing(float spacing)
376 mImpl->mColumnSpacing = spacing;
379 float NavigationLayout::GetColumnSpacing() const
381 return mImpl->mColumnSpacing;
384 void NavigationLayout::SetTopMargin(float margin)
386 mImpl->mTopMargin = margin;
389 float NavigationLayout::GetTopMargin() const
391 return mImpl->mTopMargin;
394 void NavigationLayout::SetBottomMargin(float margin)
396 mImpl->mBottomMargin = margin;
399 float NavigationLayout::GetBottomMargin() const
401 return mImpl->mBottomMargin;
404 void NavigationLayout::SetSideMargin(float margin)
406 mImpl->mSideMargin = margin;
407 mImpl->mSizeExtend = (1.0f - margin) * 3.0f;
410 void NavigationLayout::SetScrollSpeedFactor(float scrollSpeed)
412 mImpl->mScrollSpeedFactor = scrollSpeed;
415 void NavigationLayout::SetMaximumSwipeSpeed(float speed)
417 mImpl->mMaximumSwipeSpeed = speed;
420 void NavigationLayout::SetItemFlickAnimationDuration(float durationSeconds)
422 mImpl->mItemFlickAnimationDuration = durationSeconds;
425 float NavigationLayout::GetScrollSpeedFactor() const
427 return mImpl->mScrollSpeedFactor;
430 float NavigationLayout::GetMaximumSwipeSpeed() const
432 return mImpl->mMaximumSwipeSpeed;
435 float NavigationLayout::GetItemFlickAnimationDuration() const
437 return mImpl->mItemFlickAnimationDuration;
440 float NavigationLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
442 unsigned int itemsLastRow = numberOfItems % mImpl->mNumberOfColumns;
443 if (itemsLastRow == 0)
445 itemsLastRow = mImpl->mNumberOfColumns;
448 float itemsLastPage = static_cast<float>(itemsLastRow);
449 return itemsLastPage - static_cast<float>(numberOfItems) - 2.0f;
453 float NavigationLayout::GetClosestAnchorPosition(float layoutPosition) const
455 return round(layoutPosition);
458 float NavigationLayout::GetItemScrollToPosition(unsigned int itemId) const
460 return - static_cast<float>(itemId);
463 ItemRange NavigationLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
465 int itemsPerPage = mImpl->mNumberOfColumns;
467 int firstItemIndex = std::max(0.0f, -firstItemPosition -1.0f );
468 int lastItemIndex = std::max(0.0f, -(firstItemPosition) + itemsPerPage );
470 mImpl->mSignalPanV2.Emit(lastItemIndex - mImpl->mNumberOfColumns);
471 return ItemRange(firstItemIndex , lastItemIndex );
474 unsigned int NavigationLayout::GetReserveItemCount(Vector3 layoutSize) const
476 float layoutWidth = IsHorizontal(mOrientation) ? layoutSize.height : layoutSize.width;
477 float itemWidth = (layoutWidth * mImpl->mSizeExtend - mImpl->mColumnSpacing * (mImpl->mNumberOfColumns - 1))/( mImpl->mNumberOfColumns );
478 return static_cast<unsigned int>(layoutWidth / itemWidth);
481 bool NavigationLayout::GetItemSize(unsigned int itemId, Vector3 layoutSize, Vector3& itemSize) const
483 float layoutWidth = IsHorizontal(mOrientation) ? (DEFAULT_HEIGHT_FACTOR * layoutSize.height) : layoutSize.width;
484 layoutWidth = layoutWidth * mImpl->mSizeExtend;
486 float itemWidth = (layoutWidth - mImpl->mColumnSpacing*(mImpl->mNumberOfColumns-1)) / mImpl->mNumberOfColumns;
487 float itemHeight = layoutWidth * (1.0f - mImpl->mBottomMargin - mImpl->mTopMargin);
488 itemSize = Vector3(itemWidth, itemHeight, (itemWidth/4)*3);
493 void NavigationLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 size, float durationSeconds) const
497 bool NavigationLayout::GetPositionConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
499 unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
500 if (mOrientation == ControlOrientation::Left)
502 constraint = NavigationPositionConstraintLeft(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
504 else if (mOrientation == ControlOrientation::Up)
506 constraint = NavigationPositionConstraintUp(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
508 else if (mOrientation == ControlOrientation::Down)
510 constraint = NavigationPositionConstraintDown(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
512 else if (mOrientation == ControlOrientation::Right)
514 constraint = NavigationPositionConstraintRight(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
520 bool NavigationLayout::GetScaleConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
522 return false; // No scaling
525 bool NavigationLayout::GetRotationConstraint(unsigned int itemId, ItemLayout::QuaternionFunction& constraint) const
527 constraint = mImpl->mRotationConstraint[mOrientation];
531 bool NavigationLayout::GetColorConstraint(unsigned int itemId, ItemLayout::Vector4Function& constraint) const
533 constraint = mImpl->mColorConstraint;
537 bool NavigationLayout::GetVisibilityConstraint(unsigned int itemId, ItemLayout::BoolFunction& constraint) const
539 unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
540 constraint = NavigationVisibilityConstraint(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing);
544 NavigationLayout::NavigationSignalV2& NavigationLayout::PanSignal()
546 return mImpl->mSignalPanV2;
549 Degree NavigationLayout::GetScrollDirection() const
551 Degree scrollDirection(0);
552 if (mOrientation == ControlOrientation::Down)
554 scrollDirection = 0.0f - 45.0f;
556 else if (mOrientation == ControlOrientation::Right)
558 scrollDirection = 90.0f - 45.0f;
560 else if (mOrientation == ControlOrientation::Up)
562 scrollDirection = 180.0f - 45.0f;
564 else // mOrientation == ControlOrientation::Left
566 scrollDirection = 270.0f - 45.0f;
569 return scrollDirection;
572 NavigationLayout::NavigationLayout()