Dali 3D User Interface Engine
scroll-overshoot-indicator-impl.cpp
Go to the documentation of this file.
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
20 
21 // INTERNAL INCLUDES
25 
26 using namespace Dali;
27 
28 namespace
29 {
30 
32 
33 // local helper function to resize the height of the bounce actor
34 float GetBounceActorHeight( float width, float defaultHeight )
35 {
36  return (width > OVERSHOOT_BOUNCE_ACTOR_RESIZE_THRESHOLD) ? defaultHeight : defaultHeight * 0.5f;
37 }
38 
39 const float MAX_OVERSHOOT_NOTIFY_AMOUNT = 0.99f; // maximum amount to set notification for increased overshoot, beyond this we just wait for it to reduce again
40 const float MIN_OVERSHOOT_NOTIFY_AMOUNT = Math::MACHINE_EPSILON_0; // minimum amount to set notification for reduced overshoot, beyond this we just wait for it to increase again
41 const float OVERSHOOT_NOTIFY_STEP = 0.01f; // amount to set notifications beyond current overshoot value
42 
43 }
44 
45 namespace Dali
46 {
47 
48 namespace Toolkit
49 {
50 
51 namespace Internal
52 {
53 
54 ScrollOvershootIndicator::ScrollOvershootIndicator() :
55  mEffectX(NULL),
56  mEffectY(NULL)
57 {
58 }
59 
61 {
62 
63 }
64 
66 {
67  ScrollOvershootIndicator* scrollOvershootPtr = new ScrollOvershootIndicator();
68  return scrollOvershootPtr;
69 }
70 
72 {
73  if(!mEffectX)
74  {
75  mEffectX = ScrollOvershootEffectRipple::New(false, scrollable);
76  }
77  mEffectX->Apply();
78  if(!mEffectY)
79  {
80  mEffectY = ScrollOvershootEffectRipple::New(true, scrollable);
81  }
82  mEffectY->Apply();
83 }
84 
86 {
87  if(mEffectX)
88  {
89  mEffectX->Remove(scrollable);
90  }
91  if(mEffectY)
92  {
93  mEffectY->Remove(scrollable);
94  }
95 }
96 
98 {
99  mEffectX->Reset();
100  mEffectY->Reset();
101 }
102 
104 {
105  if(mEffectX)
106  {
107  mEffectX->SetOvershootEffectColor(color);
108  }
109  if(mEffectY)
110  {
111  mEffectY->SetOvershootEffectColor(color);
112  }
113 }
114 
116  mVertical(vertical)
117 {
118 
119 }
120 
122 {
123  return mVertical;
124 }
125 
127  ScrollOvershootEffect( vertical ),
128  mAttachedScrollView(scrollable),
129  mOvershootProperty(Property::INVALID_INDEX),
130  mEffectOvershootProperty(Property::INVALID_INDEX),
131  mOvershoot(0.0f),
132  mOvershootSize( scrollable.GetOvershootSize() ),
133  mAnimationStateFlags(0)
134 {
140 
141 }
142 
144 {
145  Actor self = mAttachedScrollView.Self();
147 
148  // make sure height is set, since we only create a constraint for image width
151 
153 
155 }
156 
158 {
160  {
162  {
165  }
167  {
170  }
171  scrollable.RemoveOverlay(mOvershootOverlay);
172  }
173 }
174 
176 {
179 }
180 
182 {
183  float absOvershoot = fabsf(mOvershoot);
184 
185  Actor self = mAttachedScrollView.Self();
186  // update overshoot increase notify
188  {
191  }
192  if( absOvershoot < MAX_OVERSHOOT_NOTIFY_AMOUNT )
193  {
194  float increaseStep = absOvershoot + OVERSHOOT_NOTIFY_STEP;
195  if( increaseStep > MAX_OVERSHOOT_NOTIFY_AMOUNT )
196  {
197  increaseStep = MAX_OVERSHOOT_NOTIFY_AMOUNT;
198  }
199  mOvershootIncreaseNotification = self.AddPropertyNotification( mOvershootProperty, OutsideCondition(-increaseStep, increaseStep) );
202  }
203 
204  // update overshoot decrease notify
206  {
207  self.RemovePropertyNotification( mOvershootDecreaseNotification );
209  }
210  if( absOvershoot > MIN_OVERSHOOT_NOTIFY_AMOUNT )
211  {
212  float reduceStep = absOvershoot - OVERSHOOT_NOTIFY_STEP;
213  if( reduceStep < MIN_OVERSHOOT_NOTIFY_AMOUNT )
214  {
215  reduceStep = MIN_OVERSHOOT_NOTIFY_AMOUNT;
216  }
217  mOvershootDecreaseNotification = self.AddPropertyNotification( mOvershootProperty, InsideCondition(-reduceStep, reduceStep) );
220  }
221 }
222 
224 {
226  {
228  }
229 }
230 
232 {
233  mOvershootOverlay.SetVisible(visible);
234  // make sure overshoot image is correctly placed
235  if( visible )
236  {
237  Actor self = mAttachedScrollView.Self();
238  if(mOvershoot > 0.0f)
239  {
240  // positive overshoot
242  Vector3 relativeOffset;
243  const Vector3 parentSize = self.GetCurrentSize();
244  if(IsVertical())
245  {
248  }
249  else
250  {
253  relativeOffset = Vector3(0.0f, 1.0f, 0.0f);
254  }
255  mOvershootOverlay.SetPosition(relativeOffset * parentSize);
256  }
257  else
258  {
259  // negative overshoot
261  Vector3 relativeOffset;
262  const Vector3 parentSize = self.GetCurrentSize();
263  if(IsVertical())
264  {
267  relativeOffset = Vector3(1.0f, 1.0f, 0.0f);
268  }
269  else
270  {
273  relativeOffset = Vector3(1.0f, 0.0f, 0.0f);
274  }
275  mOvershootOverlay.SetPosition(relativeOffset * parentSize);
276  }
277  }
278 }
279 
281 {
282  Actor self = mAttachedScrollView.Self();
283  mOvershoot = self.GetProperty<float>(mOvershootProperty);
284  SetOvershoot(mOvershoot, false);
286 }
287 
288 void ScrollOvershootEffectRipple::SetOvershoot(float amount, bool animate)
289 {
290  float absAmount = fabsf(amount);
291  bool animatingOn = absAmount > Math::MACHINE_EPSILON_0;
292  if( (animatingOn && (mAnimationStateFlags & AnimatingIn)) )
293  {
294  // trying to do what we are already doing
296  {
297  mAnimationStateFlags &= ~AnimateBack;
298  }
299  return;
300  }
301  if( (!animatingOn && (mAnimationStateFlags & AnimatingOut)) )
302  {
303  // trying to do what we are already doing
304  return;
305  }
306  if( !animatingOn && (mAnimationStateFlags & AnimatingIn) )
307  {
308  // dont interrupt while animating on
310  return;
311  }
312 
313  if( absAmount > Math::MACHINE_EPSILON_1 )
314  {
315  UpdateVisibility(true);
316  }
317 
319 
320  if( animate && overshootAnimationSpeed > Math::MACHINE_EPSILON_0 )
321  {
322  float currentOvershoot = fabsf( mOvershootOverlay.GetProperty( mEffectOvershootProperty ).Get<float>() );
323  float duration = mOvershootOverlay.GetCurrentSize().height * (animatingOn ? (1.0f - currentOvershoot) : currentOvershoot) / overshootAnimationSpeed;
324 
325  if( duration > Math::MACHINE_EPSILON_0 )
326  {
328  {
332  }
337  mAnimationStateFlags = animatingOn ? AnimatingIn : AnimatingOut;
338  }
339  }
340  else
341  {
343  }
344 }
345 
347 {
348  bool animateOff = false;
350  {
351  // should now be offscreen
353  }
355  {
356  animateOff = true;
357  }
362  if( animateOff )
363  {
364  SetOvershoot(0.0f, true);
365  }
366 }
367 
369 {
370  return new ScrollOvershootEffectRipple(vertical, scrollable);
371 }
372 
373 } // namespace Internal
374 
375 } // namespace Toolkit
376 
377 } // namespace Dali
Dali Docs Home
Read more about Dali