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