03a06c05a486e9aac80bab8d3cdfafdf5bf4ac77
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / public-api / controls / scrollable / item-view / item-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 // CLASS HEADER
19 #include <dali-toolkit/public-api/controls/scrollable/item-view/item-layout.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/animation/constraint.h>
23 #include <dali/public-api/animation/time-period.h>
24
25 // INTERNAL INCLUDES
26 #include <dali-toolkit/public-api/controls/scrollable/item-view/item-view.h>
27
28 namespace
29 {
30
31   // Functors which wrap constraint functions with stored item IDs
32   struct WrappedQuaternionConstraint
33   {
34     WrappedQuaternionConstraint(Dali::Toolkit::ItemLayout::QuaternionFunction wrapMe, unsigned int itemId)
35     :mWrapMe(wrapMe),
36      mItemId(itemId)
37     {
38     }
39
40     Dali::Quaternion operator()(const Dali::Quaternion& current, const Dali::PropertyInput& layoutPosition, const Dali::PropertyInput& scrollSpeed, const Dali::PropertyInput& layoutSize)
41     {
42       float offsetLayoutPosition = layoutPosition.GetFloat() + static_cast<float>(mItemId);
43
44       return mWrapMe(current, offsetLayoutPosition, scrollSpeed.GetFloat(), layoutSize.GetVector3());
45     }
46
47     Dali::Toolkit::ItemLayout::QuaternionFunction mWrapMe;
48     unsigned int mItemId;
49   };
50
51   struct WrappedVector3Constraint
52   {
53     WrappedVector3Constraint(Dali::Toolkit::ItemLayout::Vector3Function wrapMe, unsigned int itemId)
54     : mWrapMe(wrapMe),
55       mItemId(itemId)
56     {
57     }
58
59     Dali::Vector3 operator()(const Dali::Vector3& current, const Dali::PropertyInput& layoutPosition, const Dali::PropertyInput& scrollSpeed, const Dali::PropertyInput& layoutSize)
60     {
61       float offsetLayoutPosition = layoutPosition.GetFloat() + static_cast<float>(mItemId);
62
63       return mWrapMe(current, offsetLayoutPosition, scrollSpeed.GetFloat(), layoutSize.GetVector3());
64     }
65
66     Dali::Toolkit::ItemLayout::Vector3Function mWrapMe;
67     unsigned int mItemId;
68   };
69
70   struct WrappedVector4Constraint
71   {
72     WrappedVector4Constraint(Dali::Toolkit::ItemLayout::Vector4Function wrapMe, unsigned int itemId)
73     : mWrapMe(wrapMe),
74       mItemId(itemId)
75     {
76     }
77
78     Dali::Vector4 operator()(const Dali::Vector4& current, const Dali::PropertyInput& layoutPosition, const Dali::PropertyInput& scrollSpeed, const Dali::PropertyInput& layoutSize)
79     {
80       float offsetLayoutPosition = layoutPosition.GetFloat() + static_cast<float>(mItemId);
81
82       return mWrapMe(current, offsetLayoutPosition, scrollSpeed.GetFloat(), layoutSize.GetVector3());
83     }
84
85     Dali::Toolkit::ItemLayout::Vector4Function mWrapMe;
86     unsigned int mItemId;
87   };
88
89   struct WrappedBoolConstraint
90   {
91     WrappedBoolConstraint(Dali::Toolkit::ItemLayout::BoolFunction wrapMe, unsigned int itemId)
92     : mWrapMe(wrapMe),
93       mItemId(itemId)
94     {
95     }
96
97     bool operator()(const bool& current, const Dali::PropertyInput& layoutPosition, const Dali::PropertyInput& scrollSpeed, const Dali::PropertyInput& layoutSize)
98     {
99       float offsetLayoutPosition = layoutPosition.GetFloat() + static_cast<float>(mItemId);
100
101       return mWrapMe(current, offsetLayoutPosition, scrollSpeed.GetFloat(), layoutSize.GetVector3());
102     }
103
104     Dali::Toolkit::ItemLayout::BoolFunction mWrapMe;
105     unsigned int mItemId;
106   };
107
108 }  //Unnamed namespace
109
110 namespace Dali
111 {
112
113 namespace Toolkit
114 {
115
116 ItemLayout::ItemLayout()
117 : mOrientation(ControlOrientation::Up),
118   mAlphaFunction(Dali::Constraint::DEFAULT_ALPHA_FUNCTION)
119 {
120 }
121
122 ItemLayout::~ItemLayout()
123 {
124 }
125
126 void ItemLayout::SetOrientation(ControlOrientation::Type orientation)
127 {
128   mOrientation = orientation;
129 }
130
131 ControlOrientation::Type ItemLayout::GetOrientation() const
132 {
133   return mOrientation;
134 }
135
136 float ItemLayout::GetClosestOnScreenLayoutPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize)
137 {
138   Vector3 itemPosition = GetItemPosition( itemID, currentLayoutPosition, layoutSize );
139   Vector3 itemSize;
140   GetItemSize(itemID, layoutSize, itemSize);
141   Vector3 onScreenArea = (layoutSize - itemSize) * 0.5f;
142   if (itemPosition.x < -onScreenArea.x
143       || itemPosition.x > onScreenArea.x
144       || itemPosition.y < -onScreenArea.y
145       || itemPosition.y > onScreenArea.y)
146   {
147     // item not within viewable area
148     // safest thing to do here since we have no idea how the implementation will work is to return the scroll to position
149     return GetItemScrollToPosition(itemID);
150   }
151   return currentLayoutPosition;
152 }
153
154 int ItemLayout::GetNextFocusItemID(int itemID, int maxItems, Dali::Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
155 {
156   switch( direction )
157   {
158     case Control::Left:
159     case Control::Up:
160     {
161       itemID--;
162       if( itemID < 0 )
163       {
164         itemID = loopEnabled ? maxItems - 1 : 0;
165       }
166       break;
167     }
168     case Control::Right:
169     case Control::Down:
170     {
171       itemID++;
172       if( itemID >= maxItems )
173       {
174         itemID = loopEnabled ? 0 : maxItems - 1;
175       }
176       break;
177     }
178   }
179   return itemID;
180 }
181
182 float ItemLayout::GetFlickSpeedFactor() const
183 {
184   // By default, the speed factor while dragging and swiping is the same.
185   return GetScrollSpeedFactor();
186 }
187
188 void ItemLayout::ApplyConstraints( Actor& actor, const int itemId, const float durationSeconds, Constrainable scrollPositionObject, const Actor& itemViewActor )
189 {
190   // This just implements the default behaviour of constraint application.
191   // Custom layouts can override this function to apply their custom constraints.
192   Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast( itemViewActor );
193   if(itemView && scrollPositionObject)
194   {
195     Property::Index scrollSpeedProperty = itemView.GetPropertyIndex("item-view-scroll-speed");
196     Property::Index scrollPositionProperty = scrollPositionObject.GetPropertyIndex("scroll-position");
197
198     ItemLayout::Vector3Function positionConstraint;
199     if (GetPositionConstraint(itemId, positionConstraint))
200     {
201       WrappedVector3Constraint wrapped(positionConstraint, itemId);
202       Constraint constraint = Constraint::New<Vector3>( Actor::POSITION,
203                                                         Source( scrollPositionObject, scrollPositionProperty ),
204                                                         ParentSource( scrollSpeedProperty ),
205                                                         ParentSource( Actor::SIZE ),
206                                                         wrapped );
207       constraint.SetApplyTime(durationSeconds);
208       constraint.SetAlphaFunction(mAlphaFunction);
209       actor.ApplyConstraint(constraint);
210     }
211
212     ItemLayout::QuaternionFunction rotationConstraint;
213     if (GetRotationConstraint(itemId, rotationConstraint))
214     {
215       WrappedQuaternionConstraint wrapped(rotationConstraint, itemId);
216
217       Constraint constraint = Constraint::New<Quaternion>( Actor::ROTATION,
218                                                            Source( scrollPositionObject, scrollPositionProperty ),
219                                                            ParentSource( scrollSpeedProperty ),
220                                                            ParentSource( Actor::SIZE ),
221                                                            wrapped );
222       constraint.SetApplyTime(durationSeconds);
223       constraint.SetAlphaFunction(mAlphaFunction);
224
225       actor.ApplyConstraint(constraint);
226     }
227
228     ItemLayout::Vector3Function scaleConstraint;
229     if (GetScaleConstraint(itemId, scaleConstraint))
230     {
231       WrappedVector3Constraint wrapped(scaleConstraint, itemId);
232
233       Constraint constraint = Constraint::New<Vector3>( Actor::SCALE,
234                                                         Source( scrollPositionObject, scrollPositionProperty ),
235                                                         ParentSource( scrollSpeedProperty ),
236                                                         ParentSource( Actor::SIZE ),
237                                                         wrapped );
238       constraint.SetApplyTime(durationSeconds);
239       constraint.SetAlphaFunction(mAlphaFunction);
240
241       actor.ApplyConstraint(constraint);
242     }
243
244     ItemLayout::Vector4Function colorConstraint;
245     if (GetColorConstraint(itemId, colorConstraint))
246     {
247       WrappedVector4Constraint wrapped(colorConstraint, itemId);
248
249       Constraint constraint = Constraint::New<Vector4>( Actor::COLOR,
250                                                         Source( scrollPositionObject, scrollPositionProperty ),
251                                                         ParentSource( scrollSpeedProperty ),
252                                                         ParentSource( Actor::SIZE ),
253                                                         wrapped );
254
255       constraint.SetApplyTime(durationSeconds);
256       constraint.SetAlphaFunction(mAlphaFunction);
257       constraint.SetRemoveAction(Dali::Constraint::Discard);
258
259       actor.ApplyConstraint(constraint);
260     }
261
262     ItemLayout::BoolFunction visibilityConstraint;
263     if (GetVisibilityConstraint(itemId, visibilityConstraint))
264     {
265       WrappedBoolConstraint wrapped(visibilityConstraint, itemId);
266
267       Constraint constraint = Constraint::New<bool>( Actor::VISIBLE,
268                                                      Source( scrollPositionObject, scrollPositionProperty ),
269                                                      ParentSource( scrollSpeedProperty ),
270                                                      ParentSource( Actor::SIZE ),
271                                                      wrapped );
272
273       constraint.SetApplyTime(durationSeconds);
274       constraint.SetAlphaFunction(mAlphaFunction);
275
276       // Release visibility constraints the same time as the color constraint
277       constraint.SetRemoveAction(Dali::Constraint::Discard);
278
279       actor.ApplyConstraint(constraint);
280     }
281   }
282 }
283
284 Vector3 ItemLayout::GetItemPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize) const
285 {
286   Vector3 itemPosition = Vector3::ZERO;
287
288   ItemLayout::Vector3Function positionConstraint;
289   if (GetPositionConstraint(itemID, positionConstraint))
290   {
291     itemPosition = positionConstraint(Vector3::ZERO, currentLayoutPosition + itemID, 0.0f, layoutSize);
292   }
293
294   return itemPosition;
295 }
296
297 void ItemLayout::SetAlphaFunction(AlphaFunction func)
298 {
299   mAlphaFunction = func;
300 }
301
302 AlphaFunction ItemLayout::GetAlphaFunction() const
303 {
304   return mAlphaFunction;
305 }
306
307
308 } // namespace Toolkit
309
310 } // namespace Dali