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;
25 namespace // unnamed namespace
27 const unsigned int DEFAULT_NUMBER_OF_COLUMNS = 3;
28 const float DEFAULT_TOP_MARGIN = 0.3f;
29 const float DEFAULT_BOTTOM_MARGIN = 0.3f;
30 const float DEFAULT_SIDE_MARGIN = 0.2f;
31 const float DEFAULT_COLUMN_SPACING = 20.0f;
32 const float DEFAULT_ROW_SPACING = 20.0f;
33 const float DEFAULT_SCROLL_SPEED_FACTOR = 0.01f;
34 const float DEFAULT_MAXIMUM_SWIPE_SPEED = 3.0f;
35 const float DEFAULT_ITEM_FLICK_ANIMATION_DURATION = 0.05f;
36 const float DEFAULT_SIZE_EXTEND = 1.4f;
37 const float DEFAULT_HEIGHT_FACTOR = 0.6f;
39 // 4 orientations are supported
40 struct NavigationPositionConstraintUp
42 NavigationPositionConstraintUp(const unsigned int columnIndex,
43 const unsigned int numberOfColumns,
44 const float columnSpacing,
45 const float sizeExtend,
46 const float bottomMargin,
47 const float topMargin)
48 : mColumnIndex(columnIndex),
49 mNumberOfColumns(numberOfColumns),
50 mColumnSpacing(columnSpacing),
51 mSizeExtend(sizeExtend),
52 mBottomMargin(bottomMargin),
57 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
59 float itemWidth = (layoutSize.width * mSizeExtend- mColumnSpacing * (mNumberOfColumns - 1))/( mNumberOfColumns );
63 float z = (sinf((layoutPosition + 1.0f) * Math::PI *0.5f) - 1.0f) * itemWidth * 2.0f;
65 itemPosition = Vector3( (layoutPosition + 1.0f) * (itemWidth + mColumnSpacing) + itemWidth * 0.5f - layoutSize.width * mSizeExtend * 0.5f,
66 (- mBottomMargin + mTopMargin) * layoutSize.width * 0.5f ,
72 unsigned int mColumnIndex;
73 unsigned int mNumberOfColumns;
80 struct NavigationPositionConstraintLeft
82 NavigationPositionConstraintLeft(const unsigned int columnIndex,
83 const unsigned int numberOfColumns,
84 const float columnSpacing,
85 const float sizeExtend,
86 const float bottomMargin,
87 const float topMargin)
88 : mColumnIndex(columnIndex),
89 mNumberOfColumns(numberOfColumns),
90 mColumnSpacing(columnSpacing),
91 mSizeExtend(sizeExtend),
92 mBottomMargin(bottomMargin),
97 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
99 float itemWidth = (DEFAULT_HEIGHT_FACTOR * layoutSize.height * mSizeExtend- mColumnSpacing * (mNumberOfColumns - 1))/( mNumberOfColumns );
100 Vector3 itemPosition;
101 float z = (sinf((layoutPosition + 1.0f) * Math::PI *0.5f) - 1.0f) * itemWidth * 1.5f;
102 itemPosition = Vector3( (- mBottomMargin + mTopMargin) * 0.5f * layoutSize.width ,
103 -((layoutPosition+ 1.0) * (itemWidth + mColumnSpacing) + itemWidth * 0.5f - DEFAULT_HEIGHT_FACTOR * layoutSize.height * mSizeExtend * 0.5f ),
109 unsigned int mColumnIndex;
110 unsigned int mNumberOfColumns;
111 float mColumnSpacing;
117 struct NavigationPositionConstraintDown
119 NavigationPositionConstraintDown(const unsigned int columnIndex,
120 const unsigned int numberOfColumns,
121 const float columnSpacing,
122 const float sizeExtend,
123 const float bottomMargin,
124 const float topMargin)
125 : mColumnIndex(columnIndex),
126 mNumberOfColumns(numberOfColumns),
127 mColumnSpacing(columnSpacing),
128 mSizeExtend(sizeExtend),
129 mBottomMargin(bottomMargin),
130 mTopMargin(topMargin)
134 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
136 float itemWidth = (layoutSize.width * mSizeExtend- mColumnSpacing * (mNumberOfColumns - 1))/( mNumberOfColumns );
137 Vector3 itemPosition;
139 float z = (sinf((layoutPosition + 1.0f ) * Math::PI *0.5f) - 1.0f) * itemWidth * 2.0f;
140 itemPosition = Vector3( -((layoutPosition + 1.0f) * (itemWidth + mColumnSpacing) + itemWidth * 0.5f - layoutSize.width * mSizeExtend * 0.5f),
141 (- mBottomMargin + mTopMargin)* layoutSize.width * 0.5f,
147 unsigned int mColumnIndex;
148 unsigned int mNumberOfColumns;
149 float mColumnSpacing;
155 struct NavigationPositionConstraintRight
157 NavigationPositionConstraintRight(const unsigned int columnIndex,
158 const unsigned int numberOfColumns,
159 const float columnSpacing,
160 const float sizeExtend,
161 const float bottomMargin,
162 const float topMargin)
163 : mColumnIndex(columnIndex),
164 mNumberOfColumns(numberOfColumns),
165 mColumnSpacing(columnSpacing),
166 mSizeExtend(sizeExtend),
167 mBottomMargin(bottomMargin),
168 mTopMargin(topMargin)
172 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
174 float itemWidth = (DEFAULT_HEIGHT_FACTOR * layoutSize.height * mSizeExtend- mColumnSpacing * (mNumberOfColumns - 1))/( mNumberOfColumns );
175 Vector3 itemPosition;
176 float z = (sinf((layoutPosition + 1.0f) * Math::PI *0.5f) - 1.0f) * itemWidth * 1.5f;
177 itemPosition = Vector3( (- mBottomMargin + mTopMargin) * layoutSize.width * 0.5f,
178 ((layoutPosition + 1.0f) * (itemWidth + mColumnSpacing) + itemWidth * 0.5f - DEFAULT_HEIGHT_FACTOR * layoutSize.height * mSizeExtend *0.5f ),
184 unsigned int mColumnIndex;
185 unsigned int mNumberOfColumns;
186 float mColumnSpacing;
192 struct NavigationRotationConstraintUp
194 Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
197 float _layoutPosition = layoutPosition + 1.0f;
198 if(_layoutPosition >= 1.0f)
200 angle = - sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
204 angle = sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
206 return Quaternion(angle, Vector3::YAXIS);
211 struct NavigationRotationConstraintLeft
213 Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
216 float _layoutPosition = layoutPosition + 1.0f;
217 if(_layoutPosition >= 1.0f)
219 angle = - sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
223 angle = sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
225 return Quaternion(Math::PI * 0.5f, Vector3::ZAXIS) * Quaternion(angle, Vector3::YAXIS);
229 struct NavigationRotationConstraintDown
231 Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
234 float _layoutPosition = layoutPosition + 1.0f;
235 if(_layoutPosition >= 1.0f)//right side
237 //rotation angle by z axis
238 angle = - sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
242 angle = sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
244 return Quaternion(Math::PI, Vector3::ZAXIS) * Quaternion(angle, Vector3::YAXIS);
248 struct NavigationRotationConstraintRight
250 Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
253 float _layoutPosition = layoutPosition + 1.0f;
254 if(_layoutPosition >= 1.0f)
256 angle = - sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
260 angle = sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
262 return Quaternion(Math::PI * 1.5f, Vector3::ZAXIS) * Quaternion(angle, Vector3::YAXIS);
266 struct NavigationColorConstraint
268 NavigationColorConstraint(unsigned int numberOfColumns)
269 : mNumberOfColumns(numberOfColumns)
273 Vector4 operator()(const Vector4& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
275 float darkness = 1.0f;
278 float pos = ( layoutPosition + 1.0f);
279 darkness = (-0.25f) * (pos + 1.0f) * (pos + 1.0f) + 1.0f * (pos + 1.0f) + 0.2f;
281 darkness = fabs(darkness);
284 return Vector4(darkness, darkness, darkness, current.a * alpha);
286 unsigned int mNumberOfColumns;
290 struct NavigationVisibilityConstraint
292 NavigationVisibilityConstraint(const unsigned int columnIndex,
293 const unsigned int numberOfColumns,
294 const float columnSpacing )
295 : mColumnIndex(columnIndex),
296 mNumberOfColumns(numberOfColumns),
297 mColumnSpacing(columnSpacing)
301 bool operator()(const bool& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
303 float index = layoutPosition + 1.0f;
304 return (index >= -1.0f) && (index <= mNumberOfColumns );
308 unsigned int mColumnIndex;
309 unsigned int mNumberOfColumns;
310 float mColumnSpacing;
318 struct NavigationLayout::Impl
321 : mNumberOfColumns(DEFAULT_NUMBER_OF_COLUMNS),
322 mColumnSpacing(DEFAULT_COLUMN_SPACING),
323 mTopMargin(DEFAULT_TOP_MARGIN),
324 mBottomMargin(DEFAULT_BOTTOM_MARGIN),
325 mSideMargin(DEFAULT_SIDE_MARGIN),
326 mScrollSpeedFactor(DEFAULT_SCROLL_SPEED_FACTOR),
327 mMaximumSwipeSpeed(DEFAULT_MAXIMUM_SWIPE_SPEED),
328 mItemFlickAnimationDuration(DEFAULT_ITEM_FLICK_ANIMATION_DURATION),
329 mSizeExtend(DEFAULT_SIZE_EXTEND)
331 mColorConstraint = NavigationColorConstraint(mNumberOfColumns);
332 mRotationConstraint[0] = NavigationRotationConstraintUp();
333 mRotationConstraint[1] = NavigationRotationConstraintLeft();
334 mRotationConstraint[2] = NavigationRotationConstraintDown();
335 mRotationConstraint[3] = NavigationRotationConstraintRight();
338 unsigned int mNumberOfColumns;
339 float mColumnSpacing;
343 float mScrollSpeedFactor;
344 float mMaximumSwipeSpeed;
345 float mItemFlickAnimationDuration;
348 ItemLayout::QuaternionFunction mRotationConstraint[4];
350 ItemLayout::Vector4Function mColorConstraint;
353 NavigationLayoutPtr NavigationLayout::New()
355 return NavigationLayoutPtr(new NavigationLayout());
358 NavigationLayout::~NavigationLayout()
363 void NavigationLayout::SetNumberOfColumns(unsigned int columns)
365 mImpl->mNumberOfColumns = columns;
368 unsigned int NavigationLayout::GetNumberOfColumns() const
370 return mImpl->mNumberOfColumns;
373 void NavigationLayout::SetColumnSpacing(float spacing)
375 mImpl->mColumnSpacing = spacing;
378 float NavigationLayout::GetColumnSpacing() const
380 return mImpl->mColumnSpacing;
383 void NavigationLayout::SetTopMargin(float margin)
385 mImpl->mTopMargin = margin;
388 float NavigationLayout::GetTopMargin() const
390 return mImpl->mTopMargin;
393 void NavigationLayout::SetBottomMargin(float margin)
395 mImpl->mBottomMargin = margin;
398 float NavigationLayout::GetBottomMargin() const
400 return mImpl->mBottomMargin;
403 void NavigationLayout::SetSideMargin(float margin)
405 mImpl->mSideMargin = margin;
406 mImpl->mSizeExtend = (1.0f - margin) * 3.0f;
409 void NavigationLayout::SetScrollSpeedFactor(float scrollSpeed)
411 mImpl->mScrollSpeedFactor = scrollSpeed;
414 void NavigationLayout::SetMaximumSwipeSpeed(float speed)
416 mImpl->mMaximumSwipeSpeed = speed;
419 void NavigationLayout::SetItemFlickAnimationDuration(float durationSeconds)
421 mImpl->mItemFlickAnimationDuration = durationSeconds;
424 float NavigationLayout::GetScrollSpeedFactor() const
426 return mImpl->mScrollSpeedFactor;
429 float NavigationLayout::GetMaximumSwipeSpeed() const
431 return mImpl->mMaximumSwipeSpeed;
434 float NavigationLayout::GetItemFlickAnimationDuration() const
436 return mImpl->mItemFlickAnimationDuration;
439 float NavigationLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
441 unsigned int itemsLastRow = numberOfItems % mImpl->mNumberOfColumns;
442 if (itemsLastRow == 0)
444 itemsLastRow = mImpl->mNumberOfColumns;
447 float itemsLastPage = static_cast<float>(itemsLastRow);
448 return itemsLastPage - static_cast<float>(numberOfItems) - 2.0f;
452 float NavigationLayout::GetClosestAnchorPosition(float layoutPosition) const
454 return round(layoutPosition);
457 float NavigationLayout::GetItemScrollToPosition(unsigned int itemId) const
459 return - static_cast<float>(itemId);
462 ItemRange NavigationLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
464 int itemsPerPage = mImpl->mNumberOfColumns;
466 int firstItemIndex = std::max(0.0f, -firstItemPosition -1.0f );
467 int lastItemIndex = std::max(0.0f, -(firstItemPosition) + itemsPerPage );
469 return ItemRange(firstItemIndex , lastItemIndex );
472 unsigned int NavigationLayout::GetReserveItemCount(Vector3 layoutSize) const
474 float layoutWidth = IsHorizontal(mOrientation) ? layoutSize.height : layoutSize.width;
475 float itemWidth = (layoutWidth * mImpl->mSizeExtend - mImpl->mColumnSpacing * (mImpl->mNumberOfColumns - 1))/( mImpl->mNumberOfColumns );
476 return static_cast<unsigned int>(layoutWidth / itemWidth);
479 bool NavigationLayout::GetItemSize(unsigned int itemId, Vector3 layoutSize, Vector3& itemSize) const
481 float layoutWidth = IsHorizontal(mOrientation) ? (DEFAULT_HEIGHT_FACTOR * layoutSize.height) : layoutSize.width;
482 layoutWidth = layoutWidth * mImpl->mSizeExtend;
484 float itemWidth = (layoutWidth - mImpl->mColumnSpacing*(mImpl->mNumberOfColumns-1)) / mImpl->mNumberOfColumns;
485 float itemHeight = layoutWidth * (1.0f - mImpl->mBottomMargin - mImpl->mTopMargin);
486 itemSize = Vector3(itemWidth, itemHeight, (itemWidth/4)*3);
491 void NavigationLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 size, float durationSeconds) const
495 bool NavigationLayout::GetPositionConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
497 unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
498 if (mOrientation == ControlOrientation::Left)
500 constraint = NavigationPositionConstraintLeft(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
502 else if (mOrientation == ControlOrientation::Up)
504 constraint = NavigationPositionConstraintUp(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
506 else if (mOrientation == ControlOrientation::Down)
508 constraint = NavigationPositionConstraintDown(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
510 else if (mOrientation == ControlOrientation::Right)
512 constraint = NavigationPositionConstraintRight(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
518 bool NavigationLayout::GetScaleConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
520 return false; // No scaling
523 bool NavigationLayout::GetRotationConstraint(unsigned int itemId, ItemLayout::QuaternionFunction& constraint) const
525 constraint = mImpl->mRotationConstraint[mOrientation];
529 bool NavigationLayout::GetColorConstraint(unsigned int itemId, ItemLayout::Vector4Function& constraint) const
531 constraint = mImpl->mColorConstraint;
535 bool NavigationLayout::GetVisibilityConstraint(unsigned int itemId, ItemLayout::BoolFunction& constraint) const
537 unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
538 constraint = NavigationVisibilityConstraint(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing);
542 Degree NavigationLayout::GetScrollDirection() const
544 Degree scrollDirection(0);
545 if (mOrientation == ControlOrientation::Down)
547 scrollDirection = 0.0f - 45.0f;
549 else if (mOrientation == ControlOrientation::Right)
551 scrollDirection = 90.0f - 45.0f;
553 else if (mOrientation == ControlOrientation::Up)
555 scrollDirection = 180.0f - 45.0f;
557 else // mOrientation == ControlOrientation::Left
559 scrollDirection = 270.0f - 45.0f;
562 return scrollDirection;
565 NavigationLayout::NavigationLayout()