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