remove (dead) ImageView UI control
[platform/core/uifw/dali-toolkit.git] / 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 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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
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
18 #include <algorithm>
19
20 #include <dali-toolkit/public-api/controls/scrollable/item-view/navigation-layout.h>
21 using namespace Dali;
22 using namespace Dali::Toolkit;
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
352 NavigationLayoutPtr NavigationLayout::New()
353 {
354   return NavigationLayoutPtr(new NavigationLayout());
355 }
356
357 NavigationLayout::~NavigationLayout()
358 {
359   delete mImpl;
360 }
361
362 void NavigationLayout::SetNumberOfColumns(unsigned int columns)
363 {
364   mImpl->mNumberOfColumns = columns;
365 }
366
367 unsigned int NavigationLayout::GetNumberOfColumns() const
368 {
369   return mImpl->mNumberOfColumns;
370 }
371
372 void NavigationLayout::SetColumnSpacing(float spacing)
373 {
374   mImpl->mColumnSpacing = spacing;
375 }
376
377 float NavigationLayout::GetColumnSpacing() const
378 {
379   return mImpl->mColumnSpacing;
380 }
381
382 void NavigationLayout::SetTopMargin(float margin)
383 {
384   mImpl->mTopMargin = margin;
385 }
386
387 float NavigationLayout::GetTopMargin() const
388 {
389   return mImpl->mTopMargin;
390 }
391
392 void NavigationLayout::SetBottomMargin(float margin)
393 {
394   mImpl->mBottomMargin = margin;
395 }
396
397 float NavigationLayout::GetBottomMargin() const
398 {
399   return mImpl->mBottomMargin;
400 }
401
402 void NavigationLayout::SetSideMargin(float margin)
403 {
404   mImpl->mSideMargin = margin;
405   mImpl->mSizeExtend = (1.0f - margin) * 3.0f;
406 }
407
408 void NavigationLayout::SetScrollSpeedFactor(float scrollSpeed)
409 {
410   mImpl->mScrollSpeedFactor = scrollSpeed;
411 }
412
413 void NavigationLayout::SetMaximumSwipeSpeed(float speed)
414 {
415   mImpl->mMaximumSwipeSpeed = speed;
416 }
417
418 void NavigationLayout::SetItemFlickAnimationDuration(float durationSeconds)
419 {
420   mImpl->mItemFlickAnimationDuration = durationSeconds;
421 }
422
423 float NavigationLayout::GetScrollSpeedFactor() const
424 {
425   return mImpl->mScrollSpeedFactor;
426 }
427
428 float NavigationLayout::GetMaximumSwipeSpeed() const
429 {
430   return mImpl->mMaximumSwipeSpeed;
431 }
432
433 float NavigationLayout::GetItemFlickAnimationDuration() const
434 {
435   return mImpl->mItemFlickAnimationDuration;
436 }
437
438 float NavigationLayout::GetMinimumLayoutPosition(unsigned int numberOfItems, Vector3 layoutSize) const
439 {
440   unsigned int itemsLastRow = numberOfItems % mImpl->mNumberOfColumns;
441   if (itemsLastRow == 0)
442   {
443     itemsLastRow = mImpl->mNumberOfColumns;
444   }
445
446   float itemsLastPage =  static_cast<float>(itemsLastRow);
447   return itemsLastPage - static_cast<float>(numberOfItems) - 2.0f;
448
449 }
450
451 float NavigationLayout::GetClosestAnchorPosition(float layoutPosition) const
452 {
453   return round(layoutPosition);
454 }
455
456 float NavigationLayout::GetItemScrollToPosition(unsigned int itemId) const
457 {
458   return - static_cast<float>(itemId);
459 }
460
461 ItemRange NavigationLayout::GetItemsWithinArea(float firstItemPosition, Vector3 layoutSize) const
462 {
463   int itemsPerPage = mImpl->mNumberOfColumns;
464
465   int firstItemIndex = std::max(0.0f, -firstItemPosition -1.0f  );
466   int lastItemIndex = std::max(0.0f, -(firstItemPosition) + itemsPerPage );
467
468   return ItemRange(firstItemIndex , lastItemIndex );
469 }
470
471 unsigned int NavigationLayout::GetReserveItemCount(Vector3 layoutSize) const
472 {
473   float layoutWidth = IsHorizontal(mOrientation) ? layoutSize.height : layoutSize.width;
474   float itemWidth = (layoutWidth * mImpl->mSizeExtend - mImpl->mColumnSpacing * (mImpl->mNumberOfColumns - 1))/( mImpl->mNumberOfColumns );
475   return static_cast<unsigned int>(layoutWidth / itemWidth);
476 }
477
478 bool NavigationLayout::GetItemSize(unsigned int itemId, Vector3 layoutSize, Vector3& itemSize) const
479 {
480   float layoutWidth = IsHorizontal(mOrientation) ? (DEFAULT_HEIGHT_FACTOR * layoutSize.height) : layoutSize.width;
481   layoutWidth = layoutWidth * mImpl->mSizeExtend;
482
483   float itemWidth = (layoutWidth -  mImpl->mColumnSpacing*(mImpl->mNumberOfColumns-1)) / mImpl->mNumberOfColumns;
484   float itemHeight = layoutWidth * (1.0f - mImpl->mBottomMargin - mImpl->mTopMargin);
485   itemSize = Vector3(itemWidth, itemHeight, (itemWidth/4)*3);
486
487   return true;
488 }
489
490 void NavigationLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 size, float durationSeconds) const
491 {
492 }
493
494 bool NavigationLayout::GetPositionConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
495 {
496   unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
497   if (mOrientation == ControlOrientation::Left)
498   {
499     constraint = NavigationPositionConstraintLeft(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
500   }
501   else if (mOrientation == ControlOrientation::Up)
502   {
503     constraint = NavigationPositionConstraintUp(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
504   }
505   else if (mOrientation == ControlOrientation::Down)
506   {
507     constraint = NavigationPositionConstraintDown(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
508   }
509   else if (mOrientation == ControlOrientation::Right)
510   {
511     constraint = NavigationPositionConstraintRight(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing, mImpl->mSizeExtend, mImpl->mBottomMargin, mImpl->mTopMargin);
512   }
513
514   return true;
515 }
516
517 bool NavigationLayout::GetScaleConstraint(unsigned int itemId, ItemLayout::Vector3Function& constraint) const
518 {
519   return false; // No scaling
520 }
521
522 bool NavigationLayout::GetRotationConstraint(unsigned int itemId, ItemLayout::QuaternionFunction& constraint) const
523 {
524   constraint = mImpl->mRotationConstraint[mOrientation];
525   return true;
526 }
527
528 bool NavigationLayout::GetColorConstraint(unsigned int itemId, ItemLayout::Vector4Function& constraint) const
529 {
530   constraint = mImpl->mColorConstraint;
531   return true;
532 }
533
534 bool NavigationLayout::GetVisibilityConstraint(unsigned int itemId, ItemLayout::BoolFunction& constraint) const
535 {
536   unsigned int columnIndex = itemId % mImpl->mNumberOfColumns;
537   constraint = NavigationVisibilityConstraint(columnIndex, mImpl->mNumberOfColumns, mImpl->mColumnSpacing);
538   return true;
539 }
540
541 Degree NavigationLayout::GetScrollDirection() const
542 {
543   Degree scrollDirection(0);
544   if (mOrientation == ControlOrientation::Down)
545   {
546     scrollDirection = 0.0f - 45.0f;
547   }
548   else if (mOrientation == ControlOrientation::Right)
549   {
550     scrollDirection = 90.0f - 45.0f;
551   }
552   else if (mOrientation == ControlOrientation::Up)
553   {
554     scrollDirection = 180.0f - 45.0f;
555   }
556   else // mOrientation == ControlOrientation::Left
557   {
558     scrollDirection = 270.0f - 45.0f;
559   }
560
561   return scrollDirection;
562 }
563
564 NavigationLayout::NavigationLayout()
565   :mImpl(NULL)
566 {
567   mImpl = new Impl();
568 }
569
570 }
571 }