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;
352 NavigationLayout::NavigationSignalV2 mSignalPanV2;/*the signal to notify the application the selected item*/
355 NavigationLayoutPtr NavigationLayout::New()
357 return NavigationLayoutPtr(new NavigationLayout());
360 NavigationLayout::~NavigationLayout()
365 void NavigationLayout::SetNumberOfColumns(unsigned int columns)
367 mImpl->mNumberOfColumns = columns;
370 unsigned int NavigationLayout::GetNumberOfColumns() const
372 return mImpl->mNumberOfColumns;
375 void NavigationLayout::SetColumnSpacing(float spacing)
377 mImpl->mColumnSpacing = spacing;
380 float NavigationLayout::GetColumnSpacing() const
382 return mImpl->mColumnSpacing;
385 void NavigationLayout::SetTopMargin(float margin)
387 mImpl->mTopMargin = margin;
390 float NavigationLayout::GetTopMargin() const
392 return mImpl->mTopMargin;
395 void NavigationLayout::SetBottomMargin(float margin)
397 mImpl->mBottomMargin = margin;
400 float NavigationLayout::GetBottomMargin() const
402 return mImpl->mBottomMargin;
405 void NavigationLayout::SetSideMargin(float margin)
407 mImpl->mSideMargin = margin;
408 mImpl->mSizeExtend = (1.0f - margin) * 3.0f;
411 void NavigationLayout::SetScrollSpeedFactor(float scrollSpeed)
413 mImpl->mScrollSpeedFactor = scrollSpeed;
416 void NavigationLayout::SetMaximumSwipeSpeed(float speed)
418 mImpl->mMaximumSwipeSpeed = speed;
421 void NavigationLayout::SetItemFlickAnimationDuration(float durationSeconds)
423 mImpl->mItemFlickAnimationDuration = durationSeconds;
426 float NavigationLayout::GetScrollSpeedFactor() const
428 return mImpl->mScrollSpeedFactor;
431 float NavigationLayout::GetMaximumSwipeSpeed() const
433 return mImpl->mMaximumSwipeSpeed;
436 float NavigationLayout::GetItemFlickAnimationDuration() const
438 return mImpl->mItemFlickAnimationDuration;
441 float NavigationLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
443 unsigned int itemsLastRow = numberOfItems % mImpl->mNumberOfColumns;
444 if (itemsLastRow == 0)
446 itemsLastRow = mImpl->mNumberOfColumns;
449 float itemsLastPage = static_cast<float>(itemsLastRow);
450 return itemsLastPage - static_cast<float>(numberOfItems) - 2.0f;
454 float NavigationLayout::GetClosestAnchorPosition(float layoutPosition) const
456 return round(layoutPosition);
459 float NavigationLayout::GetItemScrollToPosition(unsigned int itemId) const
461 return - static_cast<float>(itemId);
464 ItemRange NavigationLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
466 int itemsPerPage = mImpl->mNumberOfColumns;
468 int firstItemIndex = std::max(0.0f, -firstItemPosition -1.0f );
469 int lastItemIndex = std::max(0.0f, -(firstItemPosition) + itemsPerPage );
471 mImpl->mSignalPanV2.Emit(lastItemIndex - mImpl->mNumberOfColumns);
472 return ItemRange(firstItemIndex , lastItemIndex );
475 unsigned int NavigationLayout::GetReserveItemCount(Vector3 layoutSize) const
477 float layoutWidth = IsHorizontal(mOrientation) ? layoutSize.height : layoutSize.width;
478 float itemWidth = (layoutWidth * mImpl->mSizeExtend - mImpl->mColumnSpacing * (mImpl->mNumberOfColumns - 1))/( mImpl->mNumberOfColumns );
479 return static_cast<unsigned int>(layoutWidth / itemWidth);
482 bool NavigationLayout::GetItemSize(unsigned int itemId, Vector3 layoutSize, Vector3& itemSize) const
484 float layoutWidth = IsHorizontal(mOrientation) ? (DEFAULT_HEIGHT_FACTOR * layoutSize.height) : layoutSize.width;
485 layoutWidth = layoutWidth * mImpl->mSizeExtend;
487 float itemWidth = (layoutWidth - mImpl->mColumnSpacing*(mImpl->mNumberOfColumns-1)) / mImpl->mNumberOfColumns;
488 float itemHeight = layoutWidth * (1.0f - mImpl->mBottomMargin - mImpl->mTopMargin);
489 itemSize = Vector3(itemWidth, itemHeight, (itemWidth/4)*3);
494 void NavigationLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 size, float durationSeconds) const
498 bool NavigationLayout::GetPositionConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
500 unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
501 if (mOrientation == ControlOrientation::Left)
503 constraint = NavigationPositionConstraintLeft(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
505 else if (mOrientation == ControlOrientation::Up)
507 constraint = NavigationPositionConstraintUp(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
509 else if (mOrientation == ControlOrientation::Down)
511 constraint = NavigationPositionConstraintDown(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
513 else if (mOrientation == ControlOrientation::Right)
515 constraint = NavigationPositionConstraintRight(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
521 bool NavigationLayout::GetScaleConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
523 return false; // No scaling
526 bool NavigationLayout::GetRotationConstraint(unsigned int itemId, ItemLayout::QuaternionFunction& constraint) const
528 constraint = mImpl->mRotationConstraint[mOrientation];
532 bool NavigationLayout::GetColorConstraint(unsigned int itemId, ItemLayout::Vector4Function& constraint) const
534 constraint = mImpl->mColorConstraint;
538 bool NavigationLayout::GetVisibilityConstraint(unsigned int itemId, ItemLayout::BoolFunction& constraint) const
540 unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
541 constraint = NavigationVisibilityConstraint(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing);
545 NavigationLayout::NavigationSignalV2& NavigationLayout::PanSignal()
547 return mImpl->mSignalPanV2;
550 Degree NavigationLayout::GetScrollDirection() const
552 Degree scrollDirection(0);
553 if (mOrientation == ControlOrientation::Down)
555 scrollDirection = 0.0f - 45.0f;
557 else if (mOrientation == ControlOrientation::Right)
559 scrollDirection = 90.0f - 45.0f;
561 else if (mOrientation == ControlOrientation::Up)
563 scrollDirection = 180.0f - 45.0f;
565 else // mOrientation == ControlOrientation::Left
567 scrollDirection = 270.0f - 45.0f;
570 return scrollDirection;
573 NavigationLayout::NavigationLayout()