Merge "Scrollable public API clean-up phase 1" into tizen
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scrollable / scroll-view / scroll-view-carousel-effect-impl.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 // EXTERNAL INCLUDES
19 #include <boost/bind.hpp>
20 #include <dali/public-api/animation/active-constraint.h>
21 #include <dali/public-api/animation/constraint.h>
22 #include <dali/public-api/object/property-input.h>
23
24 // INTERNAL INCLUDES
25 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-effect-impl.h>
26 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-carousel-effect-impl.h>
27
28 using namespace Dali;
29
30 namespace // unnamed namespace
31 {
32
33 /**
34  * Gets a property index. If the property doesn't already exist, then
35  * it will create the property.
36  * @param[in] handle The handle that owns or will own the property
37  * @param[in] name The name for this property
38  * @param[in] propertyValue The initial value for this property
39  * @return The property index for this property is returned.
40  */
41 Property::Index SafeRegisterProperty( Handle& handle, const std::string& name, Property::Value propertyValue )
42 {
43   Property::Index index = handle.GetPropertyIndex( name );
44
45   if(index == Property::INVALID_INDEX)
46   {
47     index = handle.RegisterProperty( name, propertyValue );
48   }
49
50   return index;
51 }
52
53 /**
54  * ScrollCarouselEffectInfo
55  *
56  * Visibility constraint: switches off the visibility when Actor
57  * is outside of bounds, for performance reasons.
58  *
59  * Rotate constraint: adjusts the angle of the Actors
60  * based on their position relative to the edges of the screen.
61  * When in the middle portion of the screen Angle does not change.
62  * When leaving the edge of the screen screen rotation changes.
63  *
64  * Position constraint: adjusts the position of the Actors
65  * based on their parent page's position relative to the edges of the screen.
66  * The position constraint compensates for the rotation which would otherwise
67  * move the Actor's edge visually away from the neighboring actor, as they rotate
68  * around their default anchor point.
69  */
70 class ScrollCarouselEffectInfo
71 {
72 public:
73
74   ScrollCarouselEffectInfo(const Vector2& angleSwing)
75   : mAngleSwing(angleSwing),
76     mCanvasMargin( 0.0f, 0.0f ),
77     mVisibilityThreshold( 1.0f, 1.0f )
78   {
79   }
80
81   /**
82    * @param[in] current The current visibility of this Actor
83    * @param[in] positionProperty The Actor's Position.
84    * @param[in] scaleProperty The Actor's Scale.
85    * @param[in] sizeProperty The Actor's Size
86    * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
87    * @param[in] scrollSizeProperty The size of the scroll-view (scrollView SIZE)
88    * @return The new visibility of this Actor.
89    */
90   bool VisibilityConstraint(const bool& current,
91                                   const PropertyInput& positionProperty,
92                                   const PropertyInput& scaleProperty,
93                                   const PropertyInput& sizeProperty,
94                                   const PropertyInput& scrollPositionProperty,
95                                   const PropertyInput& scrollSizeProperty)
96   {
97     const Vector2& anchor(AnchorPoint::CENTER.GetVectorXY());
98     Vector2 position(positionProperty.GetVector3() + scrollPositionProperty.GetVector3());
99     Vector2 scaledSize(sizeProperty.GetVector3() * scaleProperty.GetVector3());
100
101     Vector2 domain(scrollSizeProperty.GetVector3());
102
103     position -= (anchor - mVisibilityThreshold) * scaledSize;
104     domain -= (Vector2::ONE - mVisibilityThreshold * 2.0f) * scaledSize;
105
106     return ( position.x >= 0 &&
107              position.x <= domain.x &&
108              position.y >= 0 &&
109              position.y <= domain.y );
110   }
111
112   /**
113    * @param[in] current The current orientation of this Actor
114    * @param[in] positionProperty The Actor's Position.
115    * @param[in] scaleProperty The Actor's Scale.
116    * @param[in] sizeProperty The Actor's Size
117    * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
118    * @param[in] scrollSizeProperty The size of the scroll-view (scrollView SIZE)
119    * @param[in] activateProperty Activation value (0 - normal, 1.0 - full effect)
120    * @return The new orientation of this Actor.
121    */
122   Quaternion RotationConstraint(const Quaternion& current,
123                                 const PropertyInput& positionProperty,
124                                 const PropertyInput& scaleProperty,
125                                 const PropertyInput& sizeProperty,
126                                 const PropertyInput& scrollPositionProperty,
127                                 const PropertyInput& scrollSizeProperty,
128                                 const PropertyInput& activateProperty)
129   {
130     const float activate(activateProperty.GetFloat());
131
132     if(activate <= Math::MACHINE_EPSILON_0)
133     {
134       return current;
135     }
136
137     const Vector2& anchor(AnchorPoint::CENTER.GetVectorXY());
138     Vector2 position(positionProperty.GetVector3() + scrollPositionProperty.GetVector3());
139     Vector2 scaledSize(sizeProperty.GetVector3() * scaleProperty.GetVector3());
140     Vector2 domain(scrollSizeProperty.GetVector3());
141
142     position -= (anchor - mCanvasMargin) * scaledSize;
143     domain -= (Vector2::ONE - mCanvasMargin * 2.0f) * scaledSize;
144
145     Vector2 angle;
146
147     if( position.y < 0 )
148     {
149       angle.y = (-position.y / scaledSize.height) * mAngleSwing.y;
150     }
151     else if( position.y > domain.y )
152     {
153       angle.y = ((domain.y - position.y) / scaledSize.height) * mAngleSwing.y;
154     }
155
156     angle *= activate;
157
158     return Quaternion(-angle.x, Vector3::YAXIS) *
159            Quaternion(angle.y, Vector3::XAXIS) *
160            current;
161   }
162
163   /**
164    * @param[in] current The current position of this Actor
165    * @param[in] scaleProperty The Actor's Scale.
166    * @param[in] sizeProperty The Actor's Size
167    * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
168    * @param[in] scrollSizeProperty The size of the scroll-view (scrollView SIZE)
169    * @param[in] activateProperty Activation value (0 - normal, 1.0 - full effect)
170    * @return The new position of this Actor.
171    */
172   Vector3 PositionConstraint(const Vector3& current,
173                              const PropertyInput& scaleProperty,
174                              const PropertyInput& sizeProperty,
175                              const PropertyInput& scrollPositionProperty,
176                              const PropertyInput& scrollSizeProperty,
177                              const PropertyInput& activateProperty)
178   {
179     const float activate(activateProperty.GetFloat());
180     Vector3 position(current + scrollPositionProperty.GetVector3());
181
182     if(activate <= Math::MACHINE_EPSILON_0)
183     {
184       return position;
185     }
186
187     const Vector2& anchor(AnchorPoint::CENTER.GetVectorXY());
188     Vector2 scaledSize(sizeProperty.GetVector3() * scaleProperty.GetVector3());
189     Vector2 domain(scrollSizeProperty.GetVector3());
190
191     position.GetVectorXY() -= (anchor - mCanvasMargin) * scaledSize;
192     domain -= (Vector2::ONE - mCanvasMargin * 2.0f) * scaledSize;
193
194     Vector2 angle;
195
196     if(position.y < 0)
197     {
198       angle.y = (-position.y / scaledSize.height) * mAngleSwing.y * activate;
199       position.y += (1.0f - cosf(angle.y)) * scaledSize.height * 0.5f;
200       position.z -= sinf(angle.y) * scaledSize.height * 0.5f;
201     }
202     else if(position.y > domain.y)
203     {
204       angle.y = ((domain.y - position.y) / scaledSize.height) * mAngleSwing.y * activate;
205       position.y -= (1.0f - cosf(angle.y)) * scaledSize.height * 0.5f;
206       position.z -= sinf(-angle.y) * scaledSize.height * 0.5f;
207     }
208
209     position.GetVectorXY() += (anchor - mCanvasMargin) * scaledSize;
210
211     return position;
212   }
213
214   Vector2 mAngleSwing;                                    ///< Maximum amount in X and Y axes to rotate.
215   Vector2 mCanvasMargin;                                  ///< Margin around the canvas for when to start rotating
216   Vector2 mVisibilityThreshold;                           ///< Threshold for when to to switch off visibility of Actor (for performance)
217 };
218
219 /**
220  * Helper: Applies the 3D scroll carousel constraints to the child actor
221  *
222  * @param[in] scrollView The ScrollView containing the pages.
223  * @param[in] child The child to be affected with the 3D Effect.
224  * @param[in] info The effect info for the constraints
225  */
226 void ApplyScrollCarouselConstraints(Toolkit::ScrollView scrollView,
227                                     Actor child,
228                                     ScrollCarouselEffectInfo& info)
229 {
230   // Apply constraints to this actor //
231   Constraint constraint;
232
233   constraint = Constraint::New<bool>( Actor::VISIBLE,
234                                       LocalSource( Actor::POSITION ),
235                                       LocalSource( Actor::SCALE ),
236                                       LocalSource( Actor::SIZE ),
237                                       Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
238                                       Source(scrollView, Actor::SIZE ),
239                                       Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ),
240                                       boost::bind( &ScrollCarouselEffectInfo::VisibilityConstraint, info, _1, _2, _3, _4, _5, _6) );
241   constraint.SetRemoveAction( Constraint::Discard );
242   child.ApplyConstraint( constraint );
243
244   constraint = Constraint::New<Quaternion>( Actor::ROTATION,
245                                             LocalSource( Actor::POSITION ),
246                                             LocalSource( Actor::SCALE ),
247                                             LocalSource( Actor::SIZE ),
248                                             Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
249                                             Source(scrollView, Actor::SIZE ),
250                                             Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ),
251                                             boost::bind( &ScrollCarouselEffectInfo::RotationConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
252   constraint.SetRemoveAction( Constraint::Discard );
253   child.ApplyConstraint( constraint );
254
255   constraint = Constraint::New<Vector3>( Actor::POSITION,
256                                          LocalSource( Actor::SCALE ),
257                                          LocalSource( Actor::SIZE ),
258                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
259                                          Source(scrollView, Actor::SIZE ),
260                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ),
261                                          boost::bind( &ScrollCarouselEffectInfo::PositionConstraint, info, _1, _2, _3, _4, _5, _6) );
262
263   constraint.SetRemoveAction( Constraint::Discard );
264   child.ApplyConstraint( constraint );
265 }
266
267 } // unnamed namespace
268
269 namespace Dali
270 {
271
272 namespace Toolkit
273 {
274
275 namespace Internal
276 {
277
278 ScrollViewCarouselEffect::ScrollViewCarouselEffect()
279 : mPropertyActivate(Property::INVALID_INDEX)
280 {
281 }
282
283 ScrollViewCarouselEffect::~ScrollViewCarouselEffect()
284 {
285 }
286
287 void ScrollViewCarouselEffect::ApplyToActor(Actor child, const Vector2& angleSwing)
288 {
289   ScrollCarouselEffectInfo info( angleSwing );
290
291   ApplyScrollCarouselConstraints( GetScrollView(), child, info );
292 }
293
294 void ScrollViewCarouselEffect::OnAttach(Toolkit::ScrollView& scrollView)
295 {
296   if(mPropertyActivate == Property::INVALID_INDEX)
297   {
298     mPropertyActivate = SafeRegisterProperty( scrollView, Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE, 1.0f );
299   }
300 }
301
302 void ScrollViewCarouselEffect::OnDetach(Toolkit::ScrollView& scrollView)
303 {
304 }
305
306 } // namespace Internal
307
308 } // namespace Toolkit
309
310 } // namespace Dali