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/roll-layout.h>
23 using namespace Dali::Toolkit;
26 namespace // unnamed namespace
29 const float DEFAULT_ROW_SPACING = 20.0f;
30 const float DEFAULT_SCROLL_SPEED_FACTOR = 0.0015f;
31 const float DEFAULT_MAXIMUM_SWIPE_SPEED = 8.0f;
32 const float DEFAULT_ITEM_FLICK_ANIMATION_DURATION = 0.4f;
34 // 4 orientations are supported
35 static const unsigned int ORIENTATION_COUNT = 4;
37 static Vector3 GetItemSizeDefaultFunction(float layoutWidth, float layoutHeight, float rowSpacing)
39 float height = (layoutHeight - rowSpacing) * 0.5f;
40 return Vector3(layoutWidth, height, height);
43 struct RollPositionConstraint0
45 RollPositionConstraint0(const float rowSpacing, RollLayout::ItemSizeFunction itemSizeFunction)
46 : mRowSpacing(rowSpacing),
47 mItemSizeFunction(itemSizeFunction)
51 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
53 Vector3 itemSize = mItemSizeFunction(layoutSize.width, layoutSize.height, mRowSpacing);
55 float adjustedLayoutPosition = layoutPosition;
56 float scrollSpeedFactor = scrollSpeed * scrollSpeed * scrollSpeed * scrollSpeed;
59 float adjustedRowSpacing = mRowSpacing + scrollSpeedFactor;
61 if(adjustedLayoutPosition > Math::MACHINE_EPSILON_0 && adjustedLayoutPosition -2.0f < Math::MACHINE_EPSILON_0)
63 float adjustment = 1.0f - Dali::AlphaFunctions::EaseInOutSine60((2.0f - adjustedLayoutPosition) * 0.5f);
64 adjustedLayoutPosition = adjustment * 2.0f;
65 y = ((itemSize.y + adjustedRowSpacing ) * adjustedLayoutPosition) - layoutSize.height * 0.5f + itemSize.y * 0.5f;
69 float yStep = max(50.0f, min(itemSize.y, scrollSpeedFactor));
70 y = adjustedLayoutPosition < Math::MACHINE_EPSILON_0 ? adjustedLayoutPosition * yStep : (layoutSize.height * 0.5f + adjustedRowSpacing) + (adjustedLayoutPosition - 1.0f) * yStep;
71 y += itemSize.y * 0.5f - layoutSize.height * 0.5f;
74 float z = adjustedLayoutPosition * (10.0f + scrollSpeedFactor);
75 z -= min(3000.0f, scrollSpeedFactor * 2.0f);
77 return Vector3(itemSize.x * 0.5f - layoutSize.x * 0.5f, y, z);
83 RollLayout::ItemSizeFunction mItemSizeFunction;
86 struct RollPositionConstraint90
88 RollPositionConstraint90(const float rowSpacing, RollLayout::ItemSizeFunction itemSizeFunction)
89 : mRowSpacing(rowSpacing),
90 mItemSizeFunction(itemSizeFunction)
94 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
96 Vector3 itemSize = mItemSizeFunction(layoutSize.height, layoutSize.width, mRowSpacing);
98 float adjustedLayoutPosition = layoutPosition;
99 float scrollSpeedFactor = scrollSpeed * scrollSpeed * scrollSpeed;
102 float adjustedRowSpacing = mRowSpacing + scrollSpeedFactor;
104 if(adjustedLayoutPosition > Math::MACHINE_EPSILON_0 && adjustedLayoutPosition -2.0f < Math::MACHINE_EPSILON_0)
106 float adjustment = 1.0f - Dali::AlphaFunctions::EaseInOutSine60((2.0f - adjustedLayoutPosition) * 0.5f);
107 adjustedLayoutPosition = adjustment * 2.0f;
108 x = ((itemSize.y + adjustedRowSpacing ) * adjustedLayoutPosition) - layoutSize.width * 0.5f + itemSize.y * 0.5f;
112 float xStep = max(50.0f, min(itemSize.y, scrollSpeedFactor));
113 x = adjustedLayoutPosition < Math::MACHINE_EPSILON_0 ? adjustedLayoutPosition * xStep : (layoutSize.width * 0.5f + adjustedRowSpacing) + (adjustedLayoutPosition - 1.0f) * xStep;
114 x += itemSize.y * 0.5f - layoutSize.width * 0.5f;
117 float z = adjustedLayoutPosition * (10.0f + scrollSpeedFactor);
118 z -= min(3000.0f, scrollSpeedFactor * 2.0f);
120 return Vector3(x, itemSize.x * 0.5f - layoutSize.y * 0.5f, z);
126 RollLayout::ItemSizeFunction mItemSizeFunction;
129 struct RollPositionConstraint180
131 RollPositionConstraint180(const float rowSpacing, RollLayout::ItemSizeFunction itemSizeFunction)
132 : mRowSpacing(rowSpacing),
133 mItemSizeFunction(itemSizeFunction)
137 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
139 Vector3 itemSize = mItemSizeFunction(layoutSize.width, layoutSize.height, mRowSpacing);
141 float adjustedLayoutPosition = layoutPosition;
142 float scrollSpeedFactor = scrollSpeed * scrollSpeed * scrollSpeed;
145 float adjustedRowSpacing = mRowSpacing + scrollSpeedFactor;
147 if(adjustedLayoutPosition > Math::MACHINE_EPSILON_0 && adjustedLayoutPosition -2.0f < Math::MACHINE_EPSILON_0)
149 float adjustment = 1.0f - Dali::AlphaFunctions::EaseInOutSine60((2.0f - adjustedLayoutPosition) * 0.5f);
150 adjustedLayoutPosition = adjustment * 2.0f;
151 y = ((itemSize.y + adjustedRowSpacing ) * adjustedLayoutPosition) - layoutSize.height * 0.5f + itemSize.y * 0.5f;
155 float yStep = max(50.0f, min(itemSize.y, scrollSpeedFactor));
156 y = adjustedLayoutPosition < Math::MACHINE_EPSILON_0 ? adjustedLayoutPosition * yStep : (layoutSize.height * 0.5f + adjustedRowSpacing) + (adjustedLayoutPosition - 1.0f) * yStep;
157 y += itemSize.y * 0.5f - layoutSize.height * 0.5f;
160 float z = adjustedLayoutPosition * (10.0f + scrollSpeedFactor);
161 z -= min(3000.0f, scrollSpeedFactor * 2.0f);
164 return Vector3(-(itemSize.x * 0.5f - layoutSize.x * 0.5f),
172 RollLayout::ItemSizeFunction mItemSizeFunction;
175 struct RollPositionConstraint270
177 RollPositionConstraint270(const float rowSpacing, RollLayout::ItemSizeFunction itemSizeFunction)
178 : mRowSpacing(rowSpacing),
179 mItemSizeFunction(itemSizeFunction)
183 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
185 Vector3 itemSize = mItemSizeFunction(layoutSize.height, layoutSize.width, mRowSpacing);
187 float adjustedLayoutPosition = layoutPosition;
188 float scrollSpeedFactor = scrollSpeed * scrollSpeed * scrollSpeed;
191 float adjustedRowSpacing = mRowSpacing + scrollSpeedFactor;
193 if(adjustedLayoutPosition > Math::MACHINE_EPSILON_0 && adjustedLayoutPosition -2.0f < Math::MACHINE_EPSILON_0)
195 float adjustment = 1.0f - Dali::AlphaFunctions::EaseInOutSine60((2.0f - adjustedLayoutPosition) * 0.5f);
196 adjustedLayoutPosition = adjustment * 2.0f;
197 x = ((itemSize.y + adjustedRowSpacing ) * adjustedLayoutPosition) - layoutSize.width * 0.5f + itemSize.y * 0.5f;
201 float xStep = max(50.0f, min(itemSize.y, scrollSpeedFactor));
202 x = adjustedLayoutPosition < Math::MACHINE_EPSILON_0 ? adjustedLayoutPosition * xStep : (layoutSize.width * 0.5f + adjustedRowSpacing) + (adjustedLayoutPosition - 1.0f) * xStep;
203 x += itemSize.y * 0.5f - layoutSize.width * 0.5f;
206 float z = adjustedLayoutPosition * (10.0f + scrollSpeedFactor);
207 z -= min(3000.0f, scrollSpeedFactor * 2.0f);
210 itemSize.x * 0.5f - layoutSize.y * 0.5f,
217 RollLayout::ItemSizeFunction mItemSizeFunction;
220 struct RollRotationConstraint0
222 Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
224 return Quaternion(0.0f, Vector3::ZAXIS);
228 struct RollRotationConstraint90
230 Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
232 return Quaternion(1.5f * Math::PI, Vector3::ZAXIS);
236 struct RollRotationConstraint180
238 Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
240 return Quaternion(Math::PI, Vector3::ZAXIS);
244 struct RollRotationConstraint270
246 Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
248 return Quaternion(0.5f * Math::PI, Vector3::ZAXIS);
252 struct RollScaleConstraint
254 Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
256 float adjustedLayoutPosition = layoutPosition;
258 if(adjustedLayoutPosition < Math::MACHINE_EPSILON_0)
260 factor = fabsf(adjustedLayoutPosition);
262 if(adjustedLayoutPosition - 1.0f > Math::MACHINE_EPSILON_0)
264 factor = adjustedLayoutPosition - 1.0f;
267 float scale = min(1.0f, max(0.1f, 1.0f - 0.1f * factor));
268 if(scrollSpeed > 0.0f)
270 scale *= min(1.0f, max(0.1f, 1.0f / (scrollSpeed * 0.05f)));
273 return Vector3(scale, scale, scale);
277 struct RollColorConstraint
279 Vector4 operator()(const Vector4& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
281 float adjustedLayoutPosition = layoutPosition;
284 if(adjustedLayoutPosition < Math::MACHINE_EPSILON_0)
286 factor = fabsf(adjustedLayoutPosition);
288 if(adjustedLayoutPosition - 1.0f > Math::MACHINE_EPSILON_0)
290 factor = adjustedLayoutPosition - 1.0f;
293 float darkness = min(1.0f, max(0.5f, 1.0f - 0.5f * factor));
294 float alpha = min(1.0f, max(0.0f, 1.0f - 0.9f * factor));
295 return Vector4(darkness, darkness, darkness, alpha);
299 struct RollVisibilityConstraintPortrait
301 RollVisibilityConstraintPortrait(const float rowSpacing, RollLayout::ItemSizeFunction itemSizeFunction)
302 : mRowSpacing(rowSpacing),
303 mItemSizeFunction(itemSizeFunction)
307 bool operator()(const bool& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
309 Vector3 itemSize = mItemSizeFunction(layoutSize.width, layoutSize.height, mRowSpacing);
310 int rowsPerPage = ceil(layoutSize.height / (itemSize.y + mRowSpacing));
311 return (layoutPosition > -rowsPerPage) && (layoutPosition < rowsPerPage);
317 RollLayout::ItemSizeFunction mItemSizeFunction;
320 struct RollVisibilityConstraintLandscape
322 RollVisibilityConstraintLandscape(const float rowSpacing, RollLayout::ItemSizeFunction itemSizeFunction)
323 : mRowSpacing(rowSpacing),
324 mItemSizeFunction(itemSizeFunction)
328 bool operator()(const bool& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
330 Vector3 itemSize = mItemSizeFunction(layoutSize.height, layoutSize.width, mRowSpacing);
331 int rowsPerPage = ceil(layoutSize.width / (itemSize.y + mRowSpacing));
332 return (layoutPosition + 2.0f > Math::MACHINE_EPSILON_0) && (layoutPosition < rowsPerPage);
338 RollLayout::ItemSizeFunction mItemSizeFunction;
341 } // unnamed namespace
349 struct RollLayout::Impl
352 : mRowSpacing(DEFAULT_ROW_SPACING),
353 mScrollSpeedFactor(DEFAULT_SCROLL_SPEED_FACTOR),
354 mMaximumSwipeSpeed(DEFAULT_MAXIMUM_SWIPE_SPEED),
355 mItemFlickAnimationDuration(DEFAULT_ITEM_FLICK_ANIMATION_DURATION),
356 mItemSizeFunction(GetItemSizeDefaultFunction)
358 mScaleConstraint = RollScaleConstraint();
359 mColorConstraint = RollColorConstraint();
361 mRotationConstraint[0] = RollRotationConstraint0();
362 mRotationConstraint[1] = RollRotationConstraint90();
363 mRotationConstraint[2] = RollRotationConstraint180();
364 mRotationConstraint[3] = RollRotationConstraint270();
369 float mScrollSpeedFactor;
370 float mMaximumSwipeSpeed;
371 float mItemFlickAnimationDuration;
373 ItemLayout::QuaternionFunction mRotationConstraint[ORIENTATION_COUNT];
374 ItemLayout::Vector3Function mScaleConstraint;
375 ItemLayout::Vector4Function mColorConstraint;
377 ItemSizeFunction mItemSizeFunction;
380 RollLayoutPtr RollLayout::New()
382 return RollLayoutPtr(new RollLayout());
385 RollLayout::~RollLayout()
390 void RollLayout::SetRowSpacing(float spacing)
392 mImpl->mRowSpacing = spacing;
395 float RollLayout::GetRowSpacing() const
397 return mImpl->mRowSpacing;
400 void RollLayout::SetItemSizeFunction(ItemSizeFunction function)
402 mImpl->mItemSizeFunction = function;
405 RollLayout::ItemSizeFunction RollLayout::GetItemSizeFunction() const
407 return mImpl->mItemSizeFunction;
410 void RollLayout::SetScrollSpeedFactor(float scrollSpeed)
412 mImpl->mScrollSpeedFactor = scrollSpeed;
415 void RollLayout::SetMaximumSwipeSpeed(float speed)
417 mImpl->mMaximumSwipeSpeed = speed;
420 void RollLayout::SetItemFlickAnimationDuration(float durationSeconds)
422 mImpl->mItemFlickAnimationDuration = durationSeconds;
425 float RollLayout::GetScrollSpeedFactor() const
427 return mImpl->mScrollSpeedFactor;
430 float RollLayout::GetMaximumSwipeSpeed() const
432 return mImpl->mMaximumSwipeSpeed;
435 float RollLayout::GetItemFlickAnimationDuration() const
437 return mImpl->mItemFlickAnimationDuration;
440 float RollLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
442 return 2.0f - static_cast<float>(numberOfItems);
445 float RollLayout::GetClosestAnchorPosition(float layoutPosition) const
447 return static_cast<float>(round(layoutPosition));
450 float RollLayout::GetItemScrollToPosition(unsigned int itemId) const
452 return 0.0f - static_cast<float>(itemId);
455 ItemRange RollLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
457 float layoutWidth = IsHorizontal(mOrientation) ? layoutSize.height : layoutSize.width;
458 float layoutHeight = IsHorizontal(mOrientation) ? layoutSize.width : layoutSize.height;
460 Vector3 itemSize = mImpl->mItemSizeFunction( layoutWidth,layoutHeight, mImpl->mRowSpacing);
462 float itemsPerPage = (layoutHeight / (itemSize.y + mImpl->mRowSpacing));
463 if(firstItemPosition + 0.001f >= Math::MACHINE_EPSILON_0)
465 itemsPerPage = std::max(0.0f, itemsPerPage - 1.0f);
467 int firstVisibleItem = -(static_cast<int>(firstItemPosition));
469 int firstItemIndex = std::max(0, firstVisibleItem);
470 int lastItemIndex = std::max(0, static_cast<int>(ceil(firstVisibleItem + itemsPerPage - 1)));
471 return ItemRange(firstItemIndex, lastItemIndex);
474 unsigned int RollLayout::GetReserveItemCount(Vector3 layoutSize) const
476 float layoutWidth = IsHorizontal(mOrientation) ? layoutSize.height : layoutSize.width;
477 float layoutHeight = IsHorizontal(mOrientation) ? layoutSize.width : layoutSize.height;
479 Vector3 itemSize = mImpl->mItemSizeFunction(layoutWidth, layoutHeight, mImpl->mRowSpacing);
480 int itemsPerPage = ceil(layoutHeight / (itemSize.y + mImpl->mRowSpacing));
481 return itemsPerPage * 5;
484 bool RollLayout::GetItemSize(unsigned int itemId, Vector3 layoutSize, Vector3& itemSize) const
486 // Note: itemId is not checked, since every item has the same size
487 float layoutWidth = IsHorizontal(mOrientation) ? layoutSize.height : layoutSize.width;
488 float layoutHeight = IsHorizontal(mOrientation) ? layoutSize.width : layoutSize.height;
490 itemSize = mImpl->mItemSizeFunction(layoutWidth, layoutHeight, mImpl->mRowSpacing);
495 void RollLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 size, float durationSeconds) const
499 animation.Resize(actor, size);
503 bool RollLayout::GetPositionConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
505 if (mOrientation == ControlOrientation::Up)
507 constraint = RollPositionConstraint0(mImpl->mRowSpacing, mImpl->mItemSizeFunction);
509 else if (mOrientation == ControlOrientation::Left)
511 constraint = RollPositionConstraint90(mImpl->mRowSpacing, mImpl->mItemSizeFunction);
513 else if (mOrientation == ControlOrientation::Down)
515 constraint = RollPositionConstraint180(mImpl->mRowSpacing, mImpl->mItemSizeFunction);
517 else // mOrientation == ControlOrientation::Right
519 constraint = RollPositionConstraint270(mImpl->mRowSpacing, mImpl->mItemSizeFunction);
525 bool RollLayout::GetRotationConstraint(unsigned int itemId, ItemLayout::QuaternionFunction& constraint) const
527 constraint = mImpl->mRotationConstraint[mOrientation];
531 bool RollLayout::GetScaleConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
533 constraint = mImpl->mScaleConstraint;
537 bool RollLayout::GetColorConstraint(unsigned int itemId, ItemLayout::Vector4Function& constraint) const
539 constraint = mImpl->mColorConstraint;
543 bool RollLayout::GetVisibilityConstraint(unsigned int itemId, ItemLayout::BoolFunction& constraint) const
545 if (IsVertical(mOrientation))
547 constraint = RollVisibilityConstraintPortrait(mImpl->mRowSpacing, mImpl->mItemSizeFunction);
551 constraint = RollVisibilityConstraintLandscape(mImpl->mRowSpacing, mImpl->mItemSizeFunction);
557 Degree RollLayout::GetScrollDirection() const
559 Degree scrollDirection(0.0f);
561 if (mOrientation == ControlOrientation::Up)
563 scrollDirection = 0.0f;
565 else if (mOrientation == ControlOrientation::Left)
567 scrollDirection = 90.0f;
569 else if (mOrientation == ControlOrientation::Down)
571 scrollDirection = 180.0f;
573 else // mOrientation == ControlOrientation::Right
575 scrollDirection = 270.0f;
578 return scrollDirection;
581 RollLayout::RollLayout()
587 } // namespace Toolkit