Revert "License conversion from Flora to Apache 2.0"
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / public-api / controls / scrollable / item-view / navigation-layout.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 //     http://floralicense.org/license/
9 //
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.
15 //
16
17 #include <algorithm>
18
19 #include <dali-toolkit/public-api/controls/scrollable/item-view/navigation-layout.h>
20 using namespace Dali;
21 using namespace Dali::Toolkit;
22 using namespace std;
23
24 namespace // unnamed namespace
25 {
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;
37
38 // 4 orientations are supported
39 struct NavigationPositionConstraintUp
40 {
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),
52     mTopMargin(topMargin)
53   {
54   }
55
56   Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
57   {
58     float itemWidth = (layoutSize.width * mSizeExtend- mColumnSpacing * (mNumberOfColumns - 1))/( mNumberOfColumns );
59
60     Vector3 itemPosition;
61
62     float z = (sinf((layoutPosition + 1.0f) * Math::PI *0.5f) - 1.0f) * itemWidth * 2.0f;
63
64     itemPosition = Vector3( (layoutPosition + 1.0f) * (itemWidth + mColumnSpacing) + itemWidth * 0.5f - layoutSize.width * mSizeExtend * 0.5f,
65                              (- mBottomMargin + mTopMargin) * layoutSize.width * 0.5f ,
66                              z);
67     return itemPosition;
68   }
69
70 public:
71   unsigned int mColumnIndex;
72   unsigned int mNumberOfColumns;
73   float mColumnSpacing;
74   float mSizeExtend;
75   float mBottomMargin;
76   float mTopMargin;
77 };
78
79 struct NavigationPositionConstraintLeft
80 {
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),
92     mTopMargin(topMargin)
93   {
94   }
95
96   Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
97   {
98     float itemWidth = (DEFAULT_HEIGHT_FACTOR * layoutSize.height * mSizeExtend- mColumnSpacing * (mNumberOfColumns - 1))/( mNumberOfColumns );
99     Vector3 itemPosition;
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 ),
103                             z);
104     return itemPosition;
105   }
106
107 public:
108   unsigned int mColumnIndex;
109   unsigned int mNumberOfColumns;
110   float mColumnSpacing;
111   float mSizeExtend;
112   float mBottomMargin;
113   float mTopMargin;
114 };
115
116 struct NavigationPositionConstraintDown
117 {
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)
130   {
131   }
132
133   Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
134   {
135     float itemWidth = (layoutSize.width * mSizeExtend- mColumnSpacing * (mNumberOfColumns - 1))/( mNumberOfColumns );
136     Vector3 itemPosition;
137
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,
141                              z);
142     return itemPosition;
143   }
144
145   public:
146     unsigned int mColumnIndex;
147     unsigned int mNumberOfColumns;
148     float mColumnSpacing;
149     float mSizeExtend;
150     float mBottomMargin;
151     float mTopMargin;
152 };
153
154 struct NavigationPositionConstraintRight
155 {
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)
168   {
169   }
170
171   Vector3 operator()(const Vector3& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
172   {
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 ),
178                              z);
179   return itemPosition;
180   }
181
182 public:
183   unsigned int mColumnIndex;
184   unsigned int mNumberOfColumns;
185   float mColumnSpacing;
186   float mSizeExtend;
187   float mBottomMargin;
188   float mTopMargin;
189 };
190
191 struct NavigationRotationConstraintUp
192 {
193   Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
194   {
195     float angle = 0.0f;
196     float _layoutPosition = layoutPosition + 1.0f;
197     if(_layoutPosition >= 1.0f)
198     {
199       angle = - sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
200     }
201     else
202     {
203       angle =  sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
204     }
205     return Quaternion(angle, Vector3::YAXIS);
206   }
207
208 };
209
210 struct NavigationRotationConstraintLeft
211 {
212   Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
213   {
214     float angle = 0.0f;
215     float _layoutPosition = layoutPosition + 1.0f;
216     if(_layoutPosition >= 1.0f)
217     {
218       angle = - sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
219     }
220     else
221     {
222       angle =  sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
223     }
224     return Quaternion(Math::PI * 0.5f, Vector3::ZAXIS) * Quaternion(angle, Vector3::YAXIS);
225   }
226 };
227
228 struct NavigationRotationConstraintDown
229 {
230   Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
231   {
232     float angle = 0.0f;
233     float _layoutPosition = layoutPosition + 1.0f;
234     if(_layoutPosition >= 1.0f)//right side
235     {
236       //rotation angle by z axis
237       angle = - sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
238     }
239     else // left side
240     {
241       angle =  sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
242     }
243     return Quaternion(Math::PI, Vector3::ZAXIS) * Quaternion(angle, Vector3::YAXIS);
244   }
245 };
246
247 struct NavigationRotationConstraintRight
248 {
249   Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
250   {
251     float angle = 0.0f;
252     float _layoutPosition = layoutPosition + 1.0f;
253     if(_layoutPosition >= 1.0f)
254     {
255       angle = - sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
256     }
257     else
258     {
259       angle =  sinf(Math::PI * _layoutPosition) * Math::PI * 0.2f;
260     }
261     return Quaternion(Math::PI * 1.5f, Vector3::ZAXIS) * Quaternion(angle, Vector3::YAXIS);
262   }
263 };
264
265 struct NavigationColorConstraint
266 {
267   NavigationColorConstraint(unsigned int numberOfColumns)
268   : mNumberOfColumns(numberOfColumns)
269   {
270
271   }
272   Vector4 operator()(const Vector4& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
273   {
274     float darkness = 1.0f;
275     float alpha = 1.0f;
276
277     float pos = ( layoutPosition + 1.0f);
278     darkness = (-0.25f) * (pos + 1.0f) * (pos + 1.0f) + 1.0f * (pos + 1.0f) + 0.2f;
279
280     darkness = fabs(darkness);
281     darkness /= 1.2f;
282
283     return Vector4(darkness, darkness, darkness, current.a * alpha);
284   }
285   unsigned int mNumberOfColumns;
286
287 };
288
289 struct NavigationVisibilityConstraint
290 {
291   NavigationVisibilityConstraint(const unsigned int columnIndex,
292                                       const unsigned int numberOfColumns,
293                                       const float columnSpacing )
294   : mColumnIndex(columnIndex),
295     mNumberOfColumns(numberOfColumns),
296     mColumnSpacing(columnSpacing)
297   {
298   }
299
300   bool operator()(const bool& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize)
301   {
302     float index = layoutPosition + 1.0f;
303     return (index >= -1.0f) && (index <= mNumberOfColumns );
304   }
305
306 public:
307   unsigned int mColumnIndex;
308   unsigned int mNumberOfColumns;
309   float mColumnSpacing;
310 };
311 }//end namespace
312
313 namespace Dali
314 {
315 namespace Toolkit
316 {
317 struct NavigationLayout::Impl
318 {
319   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)
329     {
330       mColorConstraint = NavigationColorConstraint(mNumberOfColumns);
331       mRotationConstraint[0] = NavigationRotationConstraintUp();
332       mRotationConstraint[1] = NavigationRotationConstraintLeft();
333       mRotationConstraint[2] = NavigationRotationConstraintDown();
334       mRotationConstraint[3] = NavigationRotationConstraintRight();
335     }
336
337   unsigned int mNumberOfColumns;
338   float mColumnSpacing;
339   float mTopMargin;
340   float mBottomMargin;
341   float mSideMargin;
342   float mScrollSpeedFactor;
343   float mMaximumSwipeSpeed;
344   float mItemFlickAnimationDuration;
345   float mSizeExtend;
346
347   ItemLayout::QuaternionFunction mRotationConstraint[4];
348
349   ItemLayout::Vector4Function mColorConstraint;
350
351   NavigationLayout::NavigationSignalV2 mSignalPanV2;/*the signal to notify the application the selected item*/
352 };
353
354 NavigationLayoutPtr NavigationLayout::New()
355 {
356   return NavigationLayoutPtr(new NavigationLayout());
357 }
358
359 NavigationLayout::~NavigationLayout()
360 {
361   delete mImpl;
362 }
363
364 void NavigationLayout::SetNumberOfColumns(unsigned int columns)
365 {
366   mImpl->mNumberOfColumns = columns;
367 }
368
369 unsigned int NavigationLayout::GetNumberOfColumns() const
370 {
371   return mImpl->mNumberOfColumns;
372 }
373
374 void NavigationLayout::SetColumnSpacing(float spacing)
375 {
376   mImpl->mColumnSpacing = spacing;
377 }
378
379 float NavigationLayout::GetColumnSpacing() const
380 {
381   return mImpl->mColumnSpacing;
382 }
383
384 void NavigationLayout::SetTopMargin(float margin)
385 {
386   mImpl->mTopMargin = margin;
387 }
388
389 float NavigationLayout::GetTopMargin() const
390 {
391   return mImpl->mTopMargin;
392 }
393
394 void NavigationLayout::SetBottomMargin(float margin)
395 {
396   mImpl->mBottomMargin = margin;
397 }
398
399 float NavigationLayout::GetBottomMargin() const
400 {
401   return mImpl->mBottomMargin;
402 }
403
404 void NavigationLayout::SetSideMargin(float margin)
405 {
406   mImpl->mSideMargin = margin;
407   mImpl->mSizeExtend = (1.0f - margin) * 3.0f;
408 }
409
410 void NavigationLayout::SetScrollSpeedFactor(float scrollSpeed)
411 {
412   mImpl->mScrollSpeedFactor = scrollSpeed;
413 }
414
415 void NavigationLayout::SetMaximumSwipeSpeed(float speed)
416 {
417   mImpl->mMaximumSwipeSpeed = speed;
418 }
419
420 void NavigationLayout::SetItemFlickAnimationDuration(float durationSeconds)
421 {
422   mImpl->mItemFlickAnimationDuration = durationSeconds;
423 }
424
425 float NavigationLayout::GetScrollSpeedFactor() const
426 {
427   return mImpl->mScrollSpeedFactor;
428 }
429
430 float NavigationLayout::GetMaximumSwipeSpeed() const
431 {
432   return mImpl->mMaximumSwipeSpeed;
433 }
434
435 float NavigationLayout::GetItemFlickAnimationDuration() const
436 {
437   return mImpl->mItemFlickAnimationDuration;
438 }
439
440 float NavigationLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
441 {
442   unsigned int itemsLastRow = numberOfItems % mImpl->mNumberOfColumns;
443   if (itemsLastRow == 0)
444   {
445     itemsLastRow = mImpl->mNumberOfColumns;
446   }
447
448   float itemsLastPage =  static_cast<float>(itemsLastRow);
449   return itemsLastPage - static_cast<float>(numberOfItems) - 2.0f;
450
451 }
452
453 float NavigationLayout::GetClosestAnchorPosition(float layoutPosition) const
454 {
455   return round(layoutPosition);
456 }
457
458 float NavigationLayout::GetItemScrollToPosition(unsigned int itemId) const
459 {
460   return - static_cast<float>(itemId);
461 }
462
463 ItemRange NavigationLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
464 {
465   int itemsPerPage = mImpl->mNumberOfColumns;
466
467   int firstItemIndex = std::max(0.0f, -firstItemPosition -1.0f  );
468   int lastItemIndex = std::max(0.0f, -(firstItemPosition) + itemsPerPage );
469
470   mImpl->mSignalPanV2.Emit(lastItemIndex - mImpl->mNumberOfColumns);
471   return ItemRange(firstItemIndex , lastItemIndex );
472 }
473
474 unsigned int NavigationLayout::GetReserveItemCount(Vector3 layoutSize) const
475 {
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);
479 }
480
481 bool NavigationLayout::GetItemSize(unsigned int itemId, Vector3 layoutSize, Vector3& itemSize) const
482 {
483   float layoutWidth = IsHorizontal(mOrientation) ? (DEFAULT_HEIGHT_FACTOR * layoutSize.height) : layoutSize.width;
484   layoutWidth = layoutWidth * mImpl->mSizeExtend;
485
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);
489
490   return true;
491 }
492
493 void NavigationLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 size, float durationSeconds) const
494 {
495 }
496
497 bool NavigationLayout::GetPositionConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
498 {
499   unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
500   if (mOrientation == ControlOrientation::Left)
501   {
502     constraint = NavigationPositionConstraintLeft(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
503   }
504   else if (mOrientation == ControlOrientation::Up)
505   {
506     constraint = NavigationPositionConstraintUp(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
507   }
508   else if (mOrientation == ControlOrientation::Down)
509   {
510     constraint = NavigationPositionConstraintDown(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
511   }
512   else if (mOrientation == ControlOrientation::Right)
513   {
514     constraint = NavigationPositionConstraintRight(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
515   }
516
517   return true;
518 }
519
520 bool NavigationLayout::GetScaleConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
521 {
522   return false; // No scaling
523 }
524
525 bool NavigationLayout::GetRotationConstraint(unsigned int itemId, ItemLayout::QuaternionFunction& constraint) const
526 {
527   constraint = mImpl->mRotationConstraint[mOrientation];
528   return true;
529 }
530
531 bool NavigationLayout::GetColorConstraint(unsigned int itemId, ItemLayout::Vector4Function& constraint) const
532 {
533   constraint = mImpl->mColorConstraint;
534   return true;
535 }
536
537 bool NavigationLayout::GetVisibilityConstraint(unsigned int itemId, ItemLayout::BoolFunction& constraint) const
538 {
539   unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
540   constraint = NavigationVisibilityConstraint(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing);
541   return true;
542 }
543
544 NavigationLayout::NavigationSignalV2& NavigationLayout::PanSignal()
545 {
546   return mImpl->mSignalPanV2;
547 }
548
549 Degree NavigationLayout::GetScrollDirection() const
550 {
551   Degree scrollDirection(0);
552   if (mOrientation == ControlOrientation::Down)
553   {
554     scrollDirection = 0.0f - 45.0f;
555   }
556   else if (mOrientation == ControlOrientation::Right)
557   {
558     scrollDirection = 90.0f - 45.0f;
559   }
560   else if (mOrientation == ControlOrientation::Up)
561   {
562     scrollDirection = 180.0f - 45.0f;
563   }
564   else // mOrientation == ControlOrientation::Left
565   {
566     scrollDirection = 270.0f - 45.0f;
567   }
568
569   return scrollDirection;
570 }
571
572 NavigationLayout::NavigationLayout()
573   :mImpl(NULL)
574 {
575   mImpl = new Impl();
576 }
577
578 }
579 }