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