Merge "DALi Version 1.0.31" into tizen
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scroll-component / scroll-bar-internal-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 // CLASS HEADER
19 #include <dali-toolkit/internal/controls/scroll-component/scroll-bar-internal-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/animation/active-constraint.h>
23 #include <dali/public-api/animation/constraint.h>
24 #include <dali/public-api/object/property-input.h>
25 #include <dali/public-api/object/type-registry.h>
26 #include <dali/public-api/images/resource-image.h>
27
28 // INTERNAL INCLUDES
29 #include <dali-toolkit/public-api/enums.h>
30
31 using namespace Dali;
32
33 namespace
34 {
35 /**
36  * Squares input value
37  * i.e. y = x*x
38  * @param[in] x Input value to be squared
39  * @return Result (x*x)
40  */
41 template<typename T>
42 inline T Square(T x)
43 {
44   return x*x;
45 }
46
47 const char* BAR_TAB_IMAGE_PATH = DALI_IMAGE_DIR "popup_scroll.png";
48 const Vector4 BAR_TAB_NINE_PATCH_BORDER(0.0f, 12.0f, 14.0f, 14.0f);
49 const Vector3 BAR_TAB_SIZE(18.0f, 72.0f, 0.0f);
50 const Vector3 BAR_TAB_OFFSET_V(-18.0f, 0.0f, 0.1f);
51 const Vector3 BAR_TAB_OFFSET_H(0.0f, -18.0f, 0.1f);
52 const float BAR_CONTRACT_DELAY(0.8f);
53 const float BAR_SHOW_TIME(0.4f);
54 const float BAR_HIDE_TIME(0.5f);
55 const int SECOND_UNIT(1000);
56
57 /**
58  * ScrollBarInternal Visibility Constraint
59  * Returns whether scroll bar is visible
60  */
61 bool ScrollBarInternalVisibilityConstraint(const bool& current,
62     const PropertyInput& canScrollProperty)
63 {
64   bool canScroll = canScrollProperty.GetBoolean();
65   return canScroll;
66 }
67
68 /**
69  * ScrollBarInternal Size Constraint
70  * Resize ScrollBarInternal Size depends on both ScrollSize and DomainSize
71  */
72 struct ScrollBarInternalSizeConstraint
73 {
74   /**
75    * @param[in] vertical Whether this constraint controls a vertical scrollbar (true)
76    * or a horizontal one (false)
77    */
78   ScrollBarInternalSizeConstraint(bool vertical)
79   : mVertical(vertical)
80   {
81   }
82
83   /**
84    * Constraint operator
85    * @param[in] current The current ScrollBarInternal size
86    * @param[in] scrollMinProperty The container's minimum position.
87    * @param[in] scrollMaxProperty The container's maximum position.
88    * @param[in] scrollDirectionProperty The container's scroll direction.
89    * @param[in] scrollSizeProperty The container's size of viewport.
90    * @return The new ScrollBarInternal position is returned.
91    */
92   Vector3 operator()(const Vector3& current,
93                      const PropertyInput& scrollMinProperty,
94                      const PropertyInput& scrollMaxProperty,
95                      const PropertyInput& scrollDirectionProperty,
96                      const PropertyInput& scrollSizeProperty)
97   {
98     const Vector3& min = scrollMinProperty.GetVector3();
99     const Vector3& max = scrollMaxProperty.GetVector3();
100     const Vector3& scrollDirection = scrollDirectionProperty.GetVector3();
101     const Toolkit::ControlOrientation::Type& orientation = static_cast<Toolkit::ControlOrientation::Type>(scrollDirection.z);
102     const Vector3& size = scrollSizeProperty.GetVector3();
103     const Vector3 domainSize = max - min;
104
105     if (mVertical && Toolkit::IsVertical(orientation))
106     {
107       float mod = fabsf(domainSize.height) > size.height ? size.height * ( size.height / fabsf(domainSize.height) ) : size.height * ( (size.height - fabsf(domainSize.height * 0.5f)) / size.height);
108       return Vector3( current.width, mod, current.depth );
109     }
110     else
111     {
112       float mod = fabsf(domainSize.height) > size.width ? size.width * ( size.width / fabsf(domainSize.height) ) : size.width * ( (size.width - fabsf(domainSize.height * 0.5f)) / size.width);
113       return Vector3( current.width, mod, current.depth );
114     }
115   }
116
117   bool mVertical;  ///< Whether vertical or horizontal
118 };
119
120 /**
121  * ScrollBarInternal rotation Constraint
122  * Rotate ScrollBarInternal depends on the scroll direction
123  */
124 struct ScrollBarInternalRotationConstraint
125 {
126   /**
127    * @param[in] vertical Whether this constraint controls a vertical scrollbar (true)
128    * or a horizontal one (false)
129    */
130   ScrollBarInternalRotationConstraint(bool vertical)
131   : mVertical(vertical)
132   {
133   }
134
135   /**
136    * Constraint operator
137    * @param[in] current The current ScrollBarInternal rotation
138    * @param[in] scrollDirectionProperty The container's scroll direction.
139    * @return The new ScrollBarInternal rotation is returned.
140    */
141   Quaternion operator()(const Quaternion& current,
142                         const PropertyInput& scrollDirectionProperty)
143   {
144     const Vector3& scrollDirection = scrollDirectionProperty.GetVector3();
145     const Toolkit::ControlOrientation::Type& orientation = static_cast<Toolkit::ControlOrientation::Type>(scrollDirection.z);
146
147     if( (mVertical && Toolkit::IsVertical(orientation)) || (!mVertical && Toolkit::IsHorizontal(orientation)) )
148     {
149       return Quaternion(0.0f, Vector3::ZAXIS);
150     }
151     else
152     {
153       return Quaternion(0.5f * Math::PI, Vector3::ZAXIS);
154     }
155   }
156
157   bool mVertical;  ///< Whether vertical or horizontal
158 };
159
160 /**
161  * ScrollBarInternal Position Constraint
162  * Positions the scroll bar to reflect the current scroll position
163  * within the domain.
164  */
165 struct ScrollBarInternalPositionConstraint
166 {
167   /**
168    * @param[in] vertical Whether this constraint controls a vertical scrollbar (true)
169    * or a horizontal one (false)
170    * @param[in] wrap Whether to base scrollbar on original position or wrapped position
171    */
172   ScrollBarInternalPositionConstraint(bool vertical, bool wrap = false)
173   : mVertical(vertical),
174     mWrap(wrap)
175   {
176   }
177
178   /**
179    * Constraint operator
180    * @param[in] current The current ScrollBarInternal position
181    * @param[in] scrollBarSizeProperty ScrollBarInternal size
182    * @param[in] scrollRelativePositionProperty The container's relative position (from 0.0 -> 1.0 in each axis)
183    * @param[in] scrollMinProperty The container's minimum position.
184    * @param[in] scrollMaxProperty The container's maximum position.
185    * @param[in] scrollDirectionProperty The container's scroll direction.
186    * @param[in] scrollSizeProperty The container's size of viewport.
187    * @return The new ScrollBarInternal position is returned.
188    */
189   Vector3 operator()(const Vector3&    current,
190                      const PropertyInput& scrollBarSizeProperty,
191                      const PropertyInput& scrollRelativePositionProperty,
192                      const PropertyInput& scrollMinProperty,
193                      const PropertyInput& scrollMaxProperty,
194                      const PropertyInput& scrollDirectionProperty,
195                      const PropertyInput& scrollSizeProperty)
196   {
197     Vector3 barSize = scrollBarSizeProperty.GetVector3();
198     Vector3 relativePosition = scrollRelativePositionProperty.GetVector3();
199     Vector3 size = scrollSizeProperty.GetVector3();
200     const Vector3& min = scrollMinProperty.GetVector3();
201     const Vector3& max = scrollMaxProperty.GetVector3();
202     const Vector3& scrollDirection = scrollDirectionProperty.GetVector3();
203     const Toolkit::ControlOrientation::Type& orientation = static_cast<Toolkit::ControlOrientation::Type>(scrollDirection.z);
204
205     Vector3 domainSize = max - min;
206     domainSize.x = fabsf(domainSize.x);
207     domainSize.y = fabsf(domainSize.y);
208     domainSize -= size;
209
210     Vector3 mask;            // Mask movement aspect of scroll bar
211     Vector3 relativeOffset;  // base position of scroll bar in relation to the container
212     Vector3 absoluteOffset;  // absolute offset position of scroll bar
213
214     if(mVertical)
215     {
216       switch(orientation)
217       {
218         case Toolkit::ControlOrientation::Up:
219         {
220           mask = Vector3::YAXIS;
221           relativeOffset = (scrollDirection.y < 0.0f && relativePosition.y <= 0.0f) ? Vector3(1.0f, 1.0f, 0.0f) : Vector3(1.0f, 0.0f, 0.0f); // Right side of stage.
222           absoluteOffset = (scrollDirection.y < 0.0f && relativePosition.y <= 0.0f) ? BAR_TAB_OFFSET_V + Vector3( barSize.width * 0.5f, -barSize.height * 0.5f, 1.0f ) : BAR_TAB_OFFSET_V + Vector3( barSize.width * 0.5f, barSize.height * 0.5f, 1.0f );
223           break;
224         }
225         case Toolkit::ControlOrientation::Left:
226         {
227           mask = Vector3::XAXIS;
228           relativeOffset = (scrollDirection.x <= 0.0f && relativePosition.y <= 0.0f) ? Vector3(1.0f, 0.0f, 0.0f) : Vector3(0.0f, 0.0f, 0.0f); // Bottom side of stage.
229           absoluteOffset = (scrollDirection.x <= 0.0f && relativePosition.y <= 0.0f) ? Vector3( -barSize.height * 0.5f, barSize.width * 0.5f, 1.0f ) : Vector3( barSize.height * 0.5f, barSize.width * 0.5f, 1.0f );
230           break;
231         }
232         case Toolkit::ControlOrientation::Down:
233         {
234           mask = Vector3::YAXIS;
235           relativeOffset = (scrollDirection.y <= 0.0f && relativePosition.y <= 0.0f) ? Vector3(0.0f, 1.0f, 0.0f) : Vector3(0.0f, 0.0f, 0.0f); // Left side of stage.
236           absoluteOffset = (scrollDirection.y <= 0.0f && relativePosition.y <= 0.0f) ? Vector3( barSize.width * 0.5f, -barSize.height * 0.5f, 1.0f ) : Vector3( barSize.width * 0.5f, barSize.height * 0.5f, 1.0f );
237           break;
238         }
239         case Toolkit::ControlOrientation::Right:
240         {
241           mask = Vector3::XAXIS;
242           relativeOffset = (scrollDirection.x <= 0.0f && relativePosition.y <= 0.0f) ? Vector3(1.0f, 1.0f, 0.0f) : Vector3(0.0f, 1.0f, 0.0f); // Up side of stage.
243           absoluteOffset = (scrollDirection.x <= 0.0f && relativePosition.y <= 0.0f) ? Vector3( -barSize.height * 0.5f, -barSize.width * 0.5f, 1.0f ) : Vector3( barSize.height * 0.5f, -barSize.width * 0.5f, 1.0f );
244           break;
245         }
246       }
247     }
248     else
249     {
250       mask = Vector3::XAXIS;
251       relativeOffset = Vector3(0.0f, 1.0f, 0.0f); // Bottom side of stage.
252       absoluteOffset = BAR_TAB_OFFSET_H + Vector3( barSize.height * 0.5f, barSize.width * 0.5f, 1.0f );
253     }
254
255     Vector3 maskedRelativePosition = Toolkit::IsVertical(orientation) ? Vector3(relativePosition.x * (size.x-barSize.y), relativePosition.y * (size.y-barSize.y), 0.0f) * mask
256                                    : Vector3(relativePosition.y * (size.x-barSize.y), relativePosition.x * (size.y-barSize.y), 0.0f) * mask;
257
258     Vector3 finalPosition = relativeOffset * size + absoluteOffset + maskedRelativePosition;
259
260     // If Wrapped Slider, then position 1 domain either before or after current slider.
261     if(mWrap)
262     {
263       if(finalPosition.x < 0.5f)
264       {
265         finalPosition.x += size.x;
266       }
267       else
268       {
269         finalPosition.x -= size.x;
270       }
271
272       if(finalPosition.y < 0.5f)
273       {
274         finalPosition.y += size.y;
275       }
276       else
277       {
278         finalPosition.y -= size.y;
279       }
280     }
281
282     return finalPosition;
283   }
284
285   bool mVertical;           ///< Whether vertical or horizontal.
286   bool mWrap;               ///< Whether to wrap this position.
287 };
288
289 /**
290  * ScrollBarInternal HitSize Constraint
291  * Resizes HitArea to size of the container.
292  */
293 struct ScrollBarInternalHitSizeConstraint
294 {
295   /**
296    * @param[in] vertical Whether this constraint controls a vertical scrollbar (true)
297    * or a horizontal one (false)
298    * @param[in] thickness The thickness of the scrollbar
299    */
300   ScrollBarInternalHitSizeConstraint(bool vertical,
301                              float thickness)
302   : mVertical(vertical),
303     mThickness(thickness)
304   {
305   }
306
307   /**
308    * Constraint operator
309    * @param[in] current The current HitSize
310    * @param[in] scrollDirectionProperty The container's scroll direction.
311    * @param[in] scrollSizeProperty The container's size of viewport.
312    * @return The new ScrollBarInternal Hit Area size is returned.
313    */
314   Vector3 operator()(const Vector3&    current,
315                      const PropertyInput& scrollDirectionProperty,
316                      const PropertyInput& scrollSizeProperty)
317   {
318     const Vector3& scrollDirection = scrollDirectionProperty.GetVector3();
319     const Toolkit::ControlOrientation::Type& orientation = static_cast<Toolkit::ControlOrientation::Type>(scrollDirection.z);
320     Vector3 size = scrollSizeProperty.GetVector3();
321
322     Vector3 mask;            // Mask size aspect of hit area.
323     Vector3 offset;          // Add Offset size.
324
325     if( (mVertical && Toolkit::IsVertical(orientation)) || (!mVertical && Toolkit::IsHorizontal(orientation)) )
326     {
327       mask = Vector3::YAXIS;
328       offset = Vector3::XAXIS * mThickness;
329     }
330     else
331     {
332       mask = Vector3::XAXIS;
333       offset = Vector3::YAXIS * mThickness;
334     }
335
336     return size * mask + offset;
337   }
338
339   bool mVertical;           ///< Whether vertical or horizontal.
340   float mThickness;          ///< Thickness of the scroll bar
341 };
342
343 } // unnamed namespace
344
345 namespace Dali
346 {
347
348 namespace Toolkit
349 {
350
351 namespace Internal
352 {
353
354 namespace
355 {
356
357 using namespace Dali;
358
359 BaseHandle Create()
360 {
361   return BaseHandle();
362 }
363
364 TypeRegistration mType( typeid(Toolkit::ScrollBarInternal), typeid(Toolkit::ScrollComponent), Create );
365
366 }
367
368 ScrollBarInternal::ScrollBarInternal(Toolkit::Scrollable& container, bool vertical)
369 : mContainer(static_cast<Toolkit::Internal::Scrollable&>(container.GetImplementation())),
370   mVertical(vertical),
371   mAxisMask(vertical ? Vector3::YAXIS : Vector3::XAXIS),
372   mDragMode(false)
373 {
374   Image sliderImage = ResourceImage::New( BAR_TAB_IMAGE_PATH );
375
376   mSlider = ImageActor::New( sliderImage );
377   mSlider.SetParentOrigin( ParentOrigin::TOP_LEFT );
378   mSlider.SetAnchorPoint( AnchorPoint::CENTER );
379   mSlider.SetSize( BAR_TAB_SIZE );
380   mSlider.SetStyle( ImageActor::STYLE_NINE_PATCH );
381   mSlider.SetNinePatchBorder( BAR_TAB_NINE_PATCH_BORDER );
382
383   // A duplicate Slider should appear 1 domain away from the original Slider
384   mSliderWrap = ImageActor::New( sliderImage );
385   mSliderWrap.SetParentOrigin( ParentOrigin::TOP_LEFT );
386   mSliderWrap.SetAnchorPoint( AnchorPoint::CENTER );
387   mSliderWrap.SetSize( BAR_TAB_SIZE );
388   mSliderWrap.SetStyle( ImageActor::STYLE_NINE_PATCH );
389   mSliderWrap.SetNinePatchBorder( BAR_TAB_NINE_PATCH_BORDER );
390
391   // target the container to observe for scrolling
392   Actor target = mContainer.Self();
393   Constraint constraint = Constraint::New<bool>( Actor::VISIBLE,
394                                       Source( target, vertical ? target.GetPropertyIndex(Scrollable::SCROLLABLE_CAN_SCROLL_VERTICAL) : target.GetPropertyIndex(Scrollable::SCROLLABLE_CAN_SCROLL_HORIZONTAL)),
395                                       ScrollBarInternalVisibilityConstraint );
396   mSlider.ApplyConstraint( constraint );
397   mSliderWrap.ApplyConstraint( constraint );
398
399   constraint = Constraint::New<Vector3>( Actor::SIZE,
400                                                    Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
401                                                    Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
402                                                    Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME ) ),
403                                                    Source( target, Actor::SIZE ),
404                                                    ScrollBarInternalSizeConstraint( vertical ) );
405   mSlider.ApplyConstraint( constraint );
406   mSliderWrap.ApplyConstraint( constraint );
407
408   constraint = Constraint::New<Quaternion>( Actor::ROTATION,
409                                             Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME ) ),
410                                             ScrollBarInternalRotationConstraint( vertical ) );
411   mSlider.ApplyConstraint( constraint );
412   mSliderWrap.ApplyConstraint( constraint );
413
414   constraint = Constraint::New<Vector3>( Actor::POSITION,
415                                          Source( mSlider, Actor::SIZE),
416                                          Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_RELATIVE_POSITION_PROPERTY_NAME ) ),
417                                          Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
418                                          Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
419                                          Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME ) ),
420                                          Source( target, Actor::SIZE ),
421                                          ScrollBarInternalPositionConstraint(vertical) );
422
423   mSlider.ApplyConstraint( constraint );
424
425   constraint = Constraint::New<Vector3>( Actor::POSITION,
426                                          Source( mSlider, Actor::SIZE),
427                                          Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_RELATIVE_POSITION_PROPERTY_NAME ) ),
428                                          Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
429                                          Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
430                                          Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME ) ),
431                                          Source( target, Actor::SIZE ),
432                                          ScrollBarInternalPositionConstraint(vertical, true) );
433   mSliderWrap.ApplyConstraint( constraint );
434
435   // Add Sliders to internal Actor, to avoid mixing up with regular
436   // Actors added by user.
437   mContainer.AddOverlay( mSlider );
438   mContainer.AddOverlay( mSliderWrap );
439   mContainer.ScrollStartedSignal().Connect( this, &ScrollBarInternal::OnStarted );
440   mContainer.ScrollCompletedSignal().Connect( this, &ScrollBarInternal::OnCompleted );
441
442   // Hit Area for dragging slider /////////////////////////////////////////////
443   mHitArea = Actor::New();
444   mHitArea.SetPosition(0.0f, 0.0f, 0.2f);
445
446   mContainer.AddOverlay( mHitArea );
447   constraint = Constraint::New<Vector3>( Actor::SIZE,
448                                          Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME ) ),
449                                          Source( target, Actor::SIZE ),
450                                          ScrollBarInternalHitSizeConstraint(vertical, BAR_TAB_SIZE.width) );
451   mHitArea.ApplyConstraint( constraint );
452
453   if(vertical)
454   {
455     mHitArea.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
456     mHitArea.SetAnchorPoint(AnchorPoint::CENTER_RIGHT);
457   }
458   else
459   {
460     mHitArea.SetParentOrigin(ParentOrigin::BOTTOM_CENTER);
461     mHitArea.SetAnchorPoint(AnchorPoint::BOTTOM_CENTER);
462   }
463
464   WaitingContractDelay();
465 }
466
467 ScrollBarInternal::~ScrollBarInternal()
468 {
469   DestructTimer();
470 }
471
472 void ScrollBarInternal::OnInitialize()
473 {
474   EnableGestureDetection(Gesture::Type(Gesture::Pan));
475 }
476
477 void ScrollBarInternal::OnDisconnect()
478 {
479   // Disconnect all connected callback functions.
480   mContainer.RemoveOverlay( mSlider );
481   mContainer.RemoveOverlay( mSliderWrap );
482 }
483
484 void ScrollBarInternal::OnPanGesture(Actor actor, PanGesture gesture)
485 {
486   switch(gesture.state)
487   {
488     case Gesture::Started:
489     {
490       mDragMode = true;
491       Show();
492       mScrollStart = mContainer.GetCurrentScrollPosition();
493       mGestureDisplacement = Vector3::ZERO;
494       break;
495     }
496     case Gesture::Continuing:
497     {
498       Vector3 delta(gesture.displacement.x, gesture.displacement.y, 0.0f);
499       mGestureDisplacement+=delta;
500
501       Vector3 size = mContainer.Self().GetCurrentSize();
502       Vector3 span = size - Vector3(BAR_TAB_SIZE.y, BAR_TAB_SIZE.y, 1.0f);
503       Vector3 domainSize = mContainer.GetDomainSize();
504
505       Vector3 position = mScrollStart + mGestureDisplacement * mAxisMask * domainSize / span;
506       mContainer.ScrollTo(position, 0.0f);
507       break;
508     }
509     default:
510     {
511       mDragMode = false;
512       break;
513     }
514   }
515 }
516
517 void ScrollBarInternal::OnStarted(const Vector3& position)
518 {
519   // TODO: Need to disable this for the scrollbar which isn't being scrolled.
520   if(!mDragMode)
521   {
522     mDragMode = true;
523     Show();
524   }
525 }
526
527 void ScrollBarInternal::OnCompleted(const Vector3& position)
528 {
529   if( mDragMode )
530   {
531     mDragMode = false;
532
533     WaitingContractDelay();
534   }
535 }
536
537 bool ScrollBarInternal::OnContractDelayExpired()
538 {
539   if ( !mDragMode )
540   {
541     Hide();
542   }
543
544   DestructTimer();
545
546   return true;
547 }
548
549 void ScrollBarInternal::Show()
550 {
551   // Cancel any animation
552   if(mAnimation)
553   {
554     mAnimation.Clear();
555     mAnimation.Reset();
556   }
557
558   mAnimation = Animation::New( BAR_SHOW_TIME );
559   mAnimation.OpacityTo( mSlider, 1.0f, AlphaFunctions::EaseIn );
560   mAnimation.OpacityTo( mSliderWrap, 1.0f, AlphaFunctions::EaseIn );
561   mAnimation.Play();
562
563   DestructTimer();
564 }
565
566 void ScrollBarInternal::Hide()
567 {
568   // Cancel any animation
569   if(mAnimation)
570   {
571     mAnimation.Clear();
572     mAnimation.Reset();
573   }
574
575   mAnimation = Animation::New( BAR_HIDE_TIME );
576   mAnimation.OpacityTo( mSlider, 0.0f, AlphaFunctions::EaseIn );
577   mAnimation.OpacityTo( mSliderWrap, 0.0f, AlphaFunctions::EaseIn );
578   mAnimation.Play();
579 }
580
581 void ScrollBarInternal::CreateTimer()
582 {
583   if( !mTimer )
584   {
585     // Create timer for contract delay
586     mTimer = Timer::New( BAR_CONTRACT_DELAY * SECOND_UNIT );
587     mTimer.TickSignal().Connect( this, &ScrollBarInternal::OnContractDelayExpired );
588   }
589 }
590
591 void ScrollBarInternal::DestructTimer()
592 {
593   if( mTimer )
594   {
595     mTimer.Stop();
596     mTimer.TickSignal().Disconnect( this, &ScrollBarInternal::OnContractDelayExpired );
597     mTimer.Reset();
598   }
599 }
600
601 void ScrollBarInternal::WaitingContractDelay()
602 {
603   CreateTimer();
604   mTimer.Start();
605 }
606
607 Toolkit::ScrollBarInternal ScrollBarInternal::New(Toolkit::Scrollable& container, bool vertical)
608 {
609   // Create the implementation, temporarily owned by this handle on stack
610   IntrusivePtr< ScrollBarInternal > impl = new ScrollBarInternal( container, vertical );
611
612   // Pass ownership to CustomActor handle
613   Toolkit::ScrollBarInternal handle( *impl );
614
615   // Second-phase init of the implementation
616   // This can only be done after the CustomActor connection has been made...
617   impl->Initialize();
618
619   return handle;
620 }
621
622 } // namespace Internal
623
624 } // namespace Toolkit
625
626 } // namespace Dali