[3.0] Moved regular scrollbar image url into stylesheet
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scroll-bar / scroll-bar-impl.cpp
1 /*
2  * Copyright (c) 2017 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-bar/scroll-bar-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23 #include <dali/public-api/animation/constraint.h>
24 #include <dali/public-api/animation/constraints.h>
25 #include <dali/public-api/images/resource-image.h>
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/public-api/object/property-array.h>
28 #include <dali/public-api/object/type-registry-helper.h>
29 #include <dali/integration-api/debug.h>
30
31 // INTERNAL INCLUDES
32 #include <dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h>
33 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
34
35 using namespace Dali;
36
37 namespace
38 {
39
40 const float DEFAULT_SLIDER_DEPTH(1.0f);
41 const float DEFAULT_INDICATOR_SHOW_DURATION(0.5f);
42 const float DEFAULT_INDICATOR_HIDE_DURATION(0.5f);
43 const float DEFAULT_PAN_GESTURE_PROCESS_TIME(16.7f); // 16.7 milliseconds, i.e. one frame
44 const float DEFAULT_INDICATOR_FIXED_HEIGHT(80.0f);
45 const float DEFAULT_INDICATOR_MINIMUM_HEIGHT(0.0f);
46 const float DEFAULT_INDICATOR_START_PADDING(0.0f);
47 const float DEFAULT_INDICATOR_END_PADDING(0.0f);
48
49 /**
50  * Indicator size constraint
51  * Indicator size depends on both indicator's parent size and the scroll content size
52  */
53 struct IndicatorSizeConstraint
54 {
55   /**
56    * @param[in] minimumHeight The minimum height for the indicator
57    * @param[in] padding The sum of the padding at the start & end of the indicator
58    */
59   IndicatorSizeConstraint( float minimumHeight, float padding )
60   : mMinimumHeight( minimumHeight ),
61     mPadding( padding )
62   {
63   }
64
65   /**
66    * Constraint operator
67    * @param[in] current The current indicator size
68    * @param[in] parentSizeProperty The parent size of scroll indicator.
69    * @return The new scroll indicator size.
70    */
71   void operator()( Vector3& current, const PropertyInputContainer& inputs )
72   {
73     const Vector3& parentSize = inputs[0]->GetVector3();
74     const float contentSize = inputs[1]->GetFloat();
75
76     // Take into account padding that may exist at the beginning and end of the indicator.
77     const float parentHeightMinusPadding = parentSize.height - mPadding;
78
79     float height = contentSize > parentHeightMinusPadding ?
80                    parentHeightMinusPadding * ( parentHeightMinusPadding / contentSize ) :
81                    parentHeightMinusPadding * ( ( parentHeightMinusPadding - contentSize * 0.5f ) / parentHeightMinusPadding );
82
83     current.y = std::max( mMinimumHeight, height );
84   }
85
86   float mMinimumHeight;
87   float mPadding;
88 };
89
90 /**
91  * Indicator position constraint
92  * Positions the indicator to reflect the current scroll position within the scroll domain.
93  */
94 struct IndicatorPositionConstraint
95 {
96   /**
97    * @param[in] startPadding The padding at the start of the indicator
98    * @param[in] endPadding The padding at the end of the indicator
99    */
100   IndicatorPositionConstraint( float startPadding, float endPadding )
101   : mStartPadding( startPadding ),
102     mEndPadding( endPadding )
103   {
104   }
105
106   /**
107    * Constraint operator
108    * @param[in,out] current The current indicator position
109    * @param[in] inputs Contains the size of indicator, the size of indicator's parent, and the scroll position of the scrollable container (from 0.0 -> 1.0 in each axis)
110    * @return The new indicator position is returned.
111    */
112   void operator()( Vector3& current, const PropertyInputContainer& inputs )
113   {
114     const Vector3& indicatorSize = inputs[0]->GetVector3();
115     const Vector3& parentSize = inputs[1]->GetVector3();
116     const float scrollPosition = -inputs[2]->GetFloat();
117     const float minimumScrollPosition = inputs[3]->GetFloat();
118     const float maximumScrollPosition = inputs[4]->GetFloat();
119
120     // Take into account padding that may exist at the beginning and end of the indicator.
121     const float parentHeightMinusPadding = parentSize.height - ( mStartPadding + mEndPadding );
122
123     float relativePosition = std::max( 0.0f, std::min( 1.0f, ( scrollPosition - minimumScrollPosition ) / ( maximumScrollPosition - minimumScrollPosition ) ) );
124     current.y = mStartPadding + ( parentHeightMinusPadding - indicatorSize.height ) * relativePosition;
125     current.z = DEFAULT_SLIDER_DEPTH;
126   }
127
128   float mStartPadding;
129   float mEndPadding;
130 };
131
132 } // unnamed namespace
133
134 namespace Dali
135 {
136
137 namespace Toolkit
138 {
139
140 namespace Internal
141 {
142
143 namespace
144 {
145
146 using namespace Dali;
147
148 BaseHandle Create()
149 {
150   return Toolkit::ScrollBar::New();
151 }
152
153 // Setup properties, signals and actions using the type-registry.
154 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::ScrollBar, Toolkit::Control, Create );
155
156 DALI_PROPERTY_REGISTRATION( Toolkit, ScrollBar, "scrollDirection",                   STRING, SCROLL_DIRECTION          )
157 DALI_PROPERTY_REGISTRATION( Toolkit, ScrollBar, "indicatorHeightPolicy",             STRING, INDICATOR_HEIGHT_POLICY   )
158 DALI_PROPERTY_REGISTRATION( Toolkit, ScrollBar, "indicatorFixedHeight",              FLOAT,  INDICATOR_FIXED_HEIGHT    )
159 DALI_PROPERTY_REGISTRATION( Toolkit, ScrollBar, "indicatorShowDuration",             FLOAT,  INDICATOR_SHOW_DURATION   )
160 DALI_PROPERTY_REGISTRATION( Toolkit, ScrollBar, "indicatorHideDuration",             FLOAT,  INDICATOR_HIDE_DURATION   )
161 DALI_PROPERTY_REGISTRATION( Toolkit, ScrollBar, "scrollPositionIntervals",           ARRAY,  SCROLL_POSITION_INTERVALS )
162 DALI_PROPERTY_REGISTRATION( Toolkit, ScrollBar, "indicatorMinimumHeight",            FLOAT,  INDICATOR_MINIMUM_HEIGHT  )
163 DALI_PROPERTY_REGISTRATION( Toolkit, ScrollBar, "indicatorStartPadding",             FLOAT,  INDICATOR_START_PADDING   )
164 DALI_PROPERTY_REGISTRATION( Toolkit, ScrollBar, "indicatorEndPadding",               FLOAT,  INDICATOR_END_PADDING     )
165
166 DALI_SIGNAL_REGISTRATION(   Toolkit, ScrollBar, "panFinished",                       PAN_FINISHED_SIGNAL )
167 DALI_SIGNAL_REGISTRATION(   Toolkit, ScrollBar, "scrollPositionIntervalReached",     SCROLL_POSITION_INTERVAL_REACHED_SIGNAL )
168
169 DALI_TYPE_REGISTRATION_END()
170
171 const char* SCROLL_DIRECTION_NAME[] = {"Vertical", "Horizontal"};
172 const char* INDICATOR_HEIGHT_POLICY_NAME[] = {"Variable", "Fixed"};
173
174 }
175
176 ScrollBar::ScrollBar(Toolkit::ScrollBar::Direction direction)
177 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
178   mIndicatorShowAlpha(1.0f),
179   mDirection(direction),
180   mScrollableObject(WeakHandleBase()),
181   mPropertyScrollPosition(Property::INVALID_INDEX),
182   mPropertyMinScrollPosition(Property::INVALID_INDEX),
183   mPropertyMaxScrollPosition(Property::INVALID_INDEX),
184   mPropertyScrollContentSize(Property::INVALID_INDEX),
185   mIndicatorShowDuration(DEFAULT_INDICATOR_SHOW_DURATION),
186   mIndicatorHideDuration(DEFAULT_INDICATOR_HIDE_DURATION),
187   mScrollStart(0.0f),
188   mCurrentScrollPosition(0.0f),
189   mIndicatorHeightPolicy(Toolkit::ScrollBar::Variable),
190   mIndicatorFixedHeight(DEFAULT_INDICATOR_FIXED_HEIGHT),
191   mIndicatorMinimumHeight(DEFAULT_INDICATOR_MINIMUM_HEIGHT),
192   mIndicatorStartPadding(DEFAULT_INDICATOR_START_PADDING),
193   mIndicatorEndPadding(DEFAULT_INDICATOR_END_PADDING),
194   mIsPanning(false),
195   mIndicatorFirstShow(true)
196 {
197 }
198
199 ScrollBar::~ScrollBar()
200 {
201 }
202
203 void ScrollBar::OnInitialize()
204 {
205   CreateDefaultIndicatorActor();
206   Self().SetDrawMode(DrawMode::OVERLAY_2D);
207 }
208
209 void ScrollBar::SetScrollPropertySource( Handle handle, Property::Index propertyScrollPosition, Property::Index propertyMinScrollPosition, Property::Index propertyMaxScrollPosition, Property::Index propertyScrollContentSize )
210 {
211   if( handle
212       && propertyScrollPosition != Property::INVALID_INDEX
213       && propertyMinScrollPosition != Property::INVALID_INDEX
214       && propertyMaxScrollPosition != Property::INVALID_INDEX
215       && propertyScrollContentSize != Property::INVALID_INDEX )
216   {
217     mScrollableObject = WeakHandleBase(handle);
218     mPropertyScrollPosition = propertyScrollPosition;
219     mPropertyMinScrollPosition = propertyMinScrollPosition;
220     mPropertyMaxScrollPosition = propertyMaxScrollPosition;
221     mPropertyScrollContentSize = propertyScrollContentSize;
222
223     ApplyConstraints();
224   }
225   else
226   {
227     DALI_LOG_ERROR("Can not set empty handle of source object or invalid source property index\n");
228   }
229 }
230
231 void ScrollBar::CreateDefaultIndicatorActor()
232 {
233   Toolkit::ImageView indicator = Toolkit::ImageView::New();
234   indicator.SetParentOrigin( ParentOrigin::TOP_LEFT );
235   indicator.SetAnchorPoint( AnchorPoint::TOP_LEFT );
236   indicator.SetStyleName( "ScrollBarIndicator" );
237   mIndicator = indicator;
238   Self().Add( mIndicator );
239
240   EnableGestureDetection( Gesture::Type( Gesture::Pan ) );
241   PanGestureDetector detector( GetPanGestureDetector() );
242   detector.Attach( mIndicator );
243 }
244
245 void ScrollBar::SetScrollIndicator( Actor indicator )
246 {
247   // Don't allow empty handle
248   if( indicator )
249   {
250     // Remove current Indicator
251     if( mIndicator )
252     {
253       Self().Remove( mIndicator );
254     }
255     mIndicator = indicator;
256     mIndicatorFirstShow = true;
257     Self().Add(mIndicator);
258
259     EnableGestureDetection(Gesture::Type(Gesture::Pan));
260
261     PanGestureDetector detector( GetPanGestureDetector() );
262     detector.DetachAll();
263     detector.Attach( mIndicator );
264
265     unsigned int childCount = mIndicator.GetChildCount();
266     for ( unsigned int index = 0; index < childCount; index++ )
267     {
268       Actor child = mIndicator.GetChildAt( index );
269       if ( child )
270       {
271         detector.Attach( child );
272       }
273     }
274   }
275   else
276   {
277     DALI_LOG_ERROR("Empty handle of scroll indicator\n");
278   }
279 }
280
281 Actor ScrollBar::GetScrollIndicator()
282 {
283   return mIndicator;
284 }
285
286 void ScrollBar::ApplyConstraints()
287 {
288   Handle scrollableHandle = mScrollableObject.GetBaseHandle();
289
290   if( scrollableHandle )
291   {
292     if(mIndicatorSizeConstraint)
293     {
294       mIndicatorSizeConstraint.Remove();
295     }
296
297     // Set indicator height according to the indicator's height policy
298     if(mIndicatorHeightPolicy == Toolkit::ScrollBar::Fixed)
299     {
300       mIndicator.SetSize(Self().GetCurrentSize().width, mIndicatorFixedHeight);
301     }
302     else
303     {
304       mIndicatorSizeConstraint = Constraint::New<Vector3>( mIndicator, Actor::Property::SIZE,
305                                                            IndicatorSizeConstraint( mIndicatorMinimumHeight, mIndicatorStartPadding + mIndicatorEndPadding ) );
306       mIndicatorSizeConstraint.AddSource( ParentSource( Actor::Property::SIZE ) );
307       mIndicatorSizeConstraint.AddSource( Source( scrollableHandle, mPropertyScrollContentSize ) );
308       mIndicatorSizeConstraint.Apply();
309     }
310
311     if(mIndicatorPositionConstraint)
312     {
313       mIndicatorPositionConstraint.Remove();
314     }
315
316     mIndicatorPositionConstraint = Constraint::New<Vector3>( mIndicator, Actor::Property::POSITION,
317                                                              IndicatorPositionConstraint( mIndicatorStartPadding, mIndicatorEndPadding ) );
318     mIndicatorPositionConstraint.AddSource( LocalSource( Actor::Property::SIZE ) );
319     mIndicatorPositionConstraint.AddSource( ParentSource( Actor::Property::SIZE ) );
320     mIndicatorPositionConstraint.AddSource( Source( scrollableHandle, mPropertyScrollPosition ) );
321     mIndicatorPositionConstraint.AddSource( Source( scrollableHandle, mPropertyMinScrollPosition ) );
322     mIndicatorPositionConstraint.AddSource( Source( scrollableHandle, mPropertyMaxScrollPosition ) );
323     mIndicatorPositionConstraint.Apply();
324   }
325 }
326
327 void ScrollBar::SetScrollPositionIntervals( const Dali::Vector<float>& positions )
328 {
329   mScrollPositionIntervals = positions;
330
331   Handle scrollableHandle = mScrollableObject.GetBaseHandle();
332
333   if( scrollableHandle )
334   {
335     if( mPositionNotification )
336     {
337       scrollableHandle.RemovePropertyNotification(mPositionNotification);
338     }
339
340     mPositionNotification = scrollableHandle.AddPropertyNotification( mPropertyScrollPosition, VariableStepCondition(mScrollPositionIntervals) );
341     mPositionNotification.NotifySignal().Connect( this, &ScrollBar::OnScrollPositionIntervalReached );
342   }
343 }
344
345 Dali::Vector<float> ScrollBar::GetScrollPositionIntervals() const
346 {
347   return mScrollPositionIntervals;
348 }
349
350 void ScrollBar::OnScrollPositionIntervalReached(PropertyNotification& source)
351 {
352   // Emit the signal to notify the scroll position crossing
353   Handle scrollableHandle = mScrollableObject.GetBaseHandle();
354   if(scrollableHandle)
355   {
356     mScrollPositionIntervalReachedSignal.Emit(scrollableHandle.GetProperty<float>(mPropertyScrollPosition));
357   }
358 }
359
360 void ScrollBar::ShowIndicator()
361 {
362   // Cancel any animation
363   if(mAnimation)
364   {
365     mAnimation.Clear();
366     mAnimation.Reset();
367   }
368
369   if( mIndicatorFirstShow )
370   {
371     // Preserve the alpha value from the stylesheet
372     mIndicatorShowAlpha = Self().GetCurrentColor().a;
373     mIndicatorFirstShow = false;
374   }
375
376   if(mIndicatorShowDuration > 0.0f)
377   {
378     mAnimation = Animation::New( mIndicatorShowDuration );
379     mAnimation.AnimateTo( Property( mIndicator, Actor::Property::COLOR_ALPHA ), mIndicatorShowAlpha, AlphaFunction::EASE_IN );
380     mAnimation.Play();
381   }
382   else
383   {
384     mIndicator.SetOpacity(mIndicatorShowAlpha);
385   }
386 }
387
388 void ScrollBar::HideIndicator()
389 {
390   // Cancel any animation
391   if(mAnimation)
392   {
393     mAnimation.Clear();
394     mAnimation.Reset();
395   }
396
397   if(mIndicatorHideDuration > 0.0f)
398   {
399     mAnimation = Animation::New( mIndicatorHideDuration );
400     mAnimation.AnimateTo( Property( mIndicator, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunction::EASE_IN );
401     mAnimation.Play();
402   }
403   else
404   {
405     mIndicator.SetOpacity(0.0f);
406   }
407 }
408
409 bool ScrollBar::OnPanGestureProcessTick()
410 {
411   // Update the scroll position property.
412   Handle scrollableHandle = mScrollableObject.GetBaseHandle();
413   if( scrollableHandle )
414   {
415     scrollableHandle.SetProperty(mPropertyScrollPosition, mCurrentScrollPosition);
416   }
417
418   return true;
419 }
420
421 void ScrollBar::OnPan( const PanGesture& gesture )
422 {
423   Handle scrollableHandle = mScrollableObject.GetBaseHandle();
424
425   if(scrollableHandle)
426   {
427     Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast(scrollableHandle);
428
429     switch(gesture.state)
430     {
431       case Gesture::Started:
432       {
433         if( !mPanProcessTimer )
434         {
435           // Make sure the pan gesture is only being processed once per frame.
436           mPanProcessTimer = Timer::New( DEFAULT_PAN_GESTURE_PROCESS_TIME );
437           mPanProcessTimer.TickSignal().Connect( this, &ScrollBar::OnPanGestureProcessTick );
438           mPanProcessTimer.Start();
439         }
440
441         ShowIndicator();
442         mScrollStart = scrollableHandle.GetProperty<float>(mPropertyScrollPosition);
443         mGestureDisplacement = Vector3::ZERO;
444         mIsPanning = true;
445
446         break;
447       }
448       case Gesture::Continuing:
449       {
450         mGestureDisplacement.x += gesture.displacement.x;
451         mGestureDisplacement.y += gesture.displacement.y;
452
453         float minScrollPosition = scrollableHandle.GetProperty<float>( mPropertyMinScrollPosition );
454         float maxScrollPosition = scrollableHandle.GetProperty<float>( mPropertyMaxScrollPosition );
455
456         // The domain size is the internal range
457         float domainSize = maxScrollPosition - minScrollPosition;
458         float logicalSize = Self().GetCurrentSize().y - ( mIndicator.GetCurrentSize().y + mIndicatorStartPadding + mIndicatorEndPadding );
459
460         mCurrentScrollPosition = mScrollStart - ( ( mGestureDisplacement.y * domainSize ) / logicalSize );
461         mCurrentScrollPosition = -std::min( maxScrollPosition, std::max( -mCurrentScrollPosition, minScrollPosition ) );
462
463         break;
464       }
465       default:
466       {
467         mIsPanning = false;
468
469         if( mPanProcessTimer )
470         {
471           // Destroy the timer when pan gesture is finished.
472           mPanProcessTimer.Stop();
473           mPanProcessTimer.TickSignal().Disconnect( this, &ScrollBar::OnPanGestureProcessTick );
474           mPanProcessTimer.Reset();
475         }
476
477         if(itemView)
478         {
479           // Refresh the ItemView cache with extra items
480           GetImpl(itemView).DoRefresh(mCurrentScrollPosition, true);
481         }
482
483         mPanFinishedSignal.Emit();
484
485         break;
486       }
487     }
488
489     if(itemView)
490     {
491       // Disable automatic refresh in ItemView during fast scrolling
492       GetImpl(itemView).SetRefreshEnabled(!mIsPanning);
493     }
494   }
495 }
496
497 void ScrollBar::OnSizeSet( const Vector3& size )
498 {
499   if(mIndicatorHeightPolicy == Toolkit::ScrollBar::Fixed)
500   {
501     mIndicator.SetSize(size.width, mIndicatorFixedHeight);
502   }
503 }
504
505 void ScrollBar::SetScrollDirection( Toolkit::ScrollBar::Direction direction )
506 {
507   mDirection = direction;
508 }
509
510 Toolkit::ScrollBar::Direction ScrollBar::GetScrollDirection() const
511 {
512   return mDirection;
513 }
514
515 void ScrollBar::SetIndicatorHeightPolicy( Toolkit::ScrollBar::IndicatorHeightPolicy policy )
516 {
517   if( policy != mIndicatorHeightPolicy )
518   {
519     mIndicatorHeightPolicy = policy;
520     ApplyConstraints();
521   }
522 }
523
524 Toolkit::ScrollBar::IndicatorHeightPolicy ScrollBar::GetIndicatorHeightPolicy() const
525 {
526   return mIndicatorHeightPolicy;
527 }
528
529 void ScrollBar::SetIndicatorFixedHeight( float height )
530 {
531   mIndicatorFixedHeight = height;
532
533   if(mIndicatorHeightPolicy == Toolkit::ScrollBar::Fixed)
534   {
535     mIndicator.SetSize(Self().GetCurrentSize().width, mIndicatorFixedHeight);
536   }
537 }
538
539 float ScrollBar::GetIndicatorFixedHeight() const
540 {
541   return mIndicatorFixedHeight;
542 }
543
544 void ScrollBar::SetIndicatorShowDuration( float durationSeconds )
545 {
546   mIndicatorShowDuration = durationSeconds;
547 }
548
549 float ScrollBar::GetIndicatorShowDuration() const
550 {
551   return mIndicatorShowDuration;
552 }
553
554 void ScrollBar::SetIndicatorHideDuration( float durationSeconds )
555 {
556   mIndicatorHideDuration = durationSeconds;
557 }
558
559 float ScrollBar::GetIndicatorHideDuration() const
560 {
561   return mIndicatorHideDuration;
562 }
563
564 void ScrollBar::OnScrollDirectionPropertySet( Property::Value propertyValue )
565 {
566   std::string directionName( propertyValue.Get<std::string>() );
567   if(directionName == "Vertical")
568   {
569     SetScrollDirection(Toolkit::ScrollBar::Vertical);
570   }
571   else if(directionName == "Horizontal")
572   {
573     SetScrollDirection(Toolkit::ScrollBar::Horizontal);
574   }
575   else
576   {
577     DALI_ASSERT_ALWAYS( !"ScrollBar::OnScrollDirectionPropertySet(). Invalid Property value." );
578   }
579 }
580
581 void ScrollBar::OnIndicatorHeightPolicyPropertySet( Property::Value propertyValue )
582 {
583   std::string policyName( propertyValue.Get<std::string>() );
584   if(policyName == "Variable")
585   {
586     SetIndicatorHeightPolicy(Toolkit::ScrollBar::Variable);
587   }
588   else if(policyName == "Fixed")
589   {
590     SetIndicatorHeightPolicy(Toolkit::ScrollBar::Fixed);
591   }
592   else
593   {
594     DALI_ASSERT_ALWAYS( !"ScrollBar::OnIndicatorHeightPolicyPropertySet(). Invalid Property value." );
595   }
596 }
597
598 bool ScrollBar::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
599 {
600   Dali::BaseHandle handle( object );
601
602   bool connected( true );
603   Toolkit::ScrollBar scrollBar = Toolkit::ScrollBar::DownCast( handle );
604
605   if( 0 == strcmp( signalName.c_str(), PAN_FINISHED_SIGNAL ) )
606   {
607     scrollBar.PanFinishedSignal().Connect( tracker, functor );
608   }
609   else if( 0 == strcmp( signalName.c_str(), SCROLL_POSITION_INTERVAL_REACHED_SIGNAL ) )
610   {
611     scrollBar.ScrollPositionIntervalReachedSignal().Connect( tracker, functor );
612   }
613   else
614   {
615     // signalName does not match any signal
616     connected = false;
617   }
618
619   return connected;
620 }
621
622 void ScrollBar::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
623 {
624   Toolkit::ScrollBar scrollBar = Toolkit::ScrollBar::DownCast( Dali::BaseHandle( object ) );
625
626   if( scrollBar )
627   {
628     ScrollBar& scrollBarImpl( GetImpl( scrollBar ) );
629     switch( index )
630     {
631       case Toolkit::ScrollBar::Property::SCROLL_DIRECTION:
632       {
633         scrollBarImpl.OnScrollDirectionPropertySet( value );
634         break;
635       }
636       case Toolkit::ScrollBar::Property::INDICATOR_HEIGHT_POLICY:
637       {
638         scrollBarImpl.OnIndicatorHeightPolicyPropertySet( value );
639         break;
640       }
641       case Toolkit::ScrollBar::Property::INDICATOR_FIXED_HEIGHT:
642       {
643         scrollBarImpl.SetIndicatorFixedHeight(value.Get<float>());
644         break;
645       }
646       case Toolkit::ScrollBar::Property::INDICATOR_SHOW_DURATION:
647       {
648         scrollBarImpl.SetIndicatorShowDuration(value.Get<float>());
649         break;
650       }
651       case Toolkit::ScrollBar::Property::INDICATOR_HIDE_DURATION:
652       {
653         scrollBarImpl.SetIndicatorHideDuration(value.Get<float>());
654         break;
655       }
656       case Toolkit::ScrollBar::Property::SCROLL_POSITION_INTERVALS:
657       {
658         Property::Array* array = value.GetArray();
659         if( array )
660         {
661           Dali::Vector<float> positions;
662           size_t positionCount = array->Count();
663           positions.Resize( positionCount );
664           for( size_t i = 0; i != positionCount; ++i )
665           {
666             array->GetElementAt( i ).Get( positions[i] );
667           }
668
669           scrollBarImpl.SetScrollPositionIntervals(positions);
670         }
671         break;
672       }
673       case Toolkit::ScrollBar::Property::INDICATOR_MINIMUM_HEIGHT:
674       {
675         scrollBarImpl.mIndicatorMinimumHeight = value.Get<float>();
676         scrollBarImpl.ApplyConstraints();
677         break;
678       }
679       case Toolkit::ScrollBar::Property::INDICATOR_START_PADDING:
680       {
681         scrollBarImpl.mIndicatorStartPadding = value.Get<float>();
682         scrollBarImpl.ApplyConstraints();
683         break;
684       }
685       case Toolkit::ScrollBar::Property::INDICATOR_END_PADDING:
686       {
687         scrollBarImpl.mIndicatorEndPadding = value.Get<float>();
688         scrollBarImpl.ApplyConstraints();
689         break;
690       }
691     }
692   }
693 }
694
695 Property::Value ScrollBar::GetProperty( BaseObject* object, Property::Index index )
696 {
697   Property::Value value;
698
699   Toolkit::ScrollBar scrollBar = Toolkit::ScrollBar::DownCast( Dali::BaseHandle( object ) );
700
701   if( scrollBar )
702   {
703     ScrollBar& scrollBarImpl( GetImpl( scrollBar ) );
704     switch( index )
705     {
706       case Toolkit::ScrollBar::Property::SCROLL_DIRECTION:
707       {
708         value = SCROLL_DIRECTION_NAME[ scrollBarImpl.GetScrollDirection() ];
709         break;
710       }
711       case Toolkit::ScrollBar::Property::INDICATOR_HEIGHT_POLICY:
712       {
713         value = INDICATOR_HEIGHT_POLICY_NAME[ scrollBarImpl.GetIndicatorHeightPolicy() ];
714         break;
715       }
716       case Toolkit::ScrollBar::Property::INDICATOR_FIXED_HEIGHT:
717       {
718         value = scrollBarImpl.GetIndicatorFixedHeight();
719         break;
720       }
721       case Toolkit::ScrollBar::Property::INDICATOR_SHOW_DURATION:
722       {
723         value = scrollBarImpl.GetIndicatorShowDuration();
724         break;
725       }
726       case Toolkit::ScrollBar::Property::INDICATOR_HIDE_DURATION:
727       {
728         value = scrollBarImpl.GetIndicatorHideDuration();
729         break;
730       }
731       case Toolkit::ScrollBar::Property::SCROLL_POSITION_INTERVALS:
732       {
733         Property::Value value( Property::ARRAY );
734         Property::Array* array = value.GetArray();
735
736         if( array )
737         {
738           Dali::Vector<float> positions = scrollBarImpl.GetScrollPositionIntervals();
739           size_t positionCount( array->Count() );
740           for( size_t i( 0 ); i != positionCount; ++i )
741           {
742             array->PushBack( positions[i] );
743           }
744         }
745         break;
746       }
747       case Toolkit::ScrollBar::Property::INDICATOR_MINIMUM_HEIGHT:
748       {
749         value = scrollBarImpl.mIndicatorMinimumHeight;
750         break;
751       }
752       case Toolkit::ScrollBar::Property::INDICATOR_START_PADDING:
753       {
754         value = scrollBarImpl.mIndicatorStartPadding;
755         break;
756       }
757       case Toolkit::ScrollBar::Property::INDICATOR_END_PADDING:
758       {
759         value = scrollBarImpl.mIndicatorEndPadding;
760         break;
761       }
762     }
763   }
764   return value;
765 }
766
767 Toolkit::ScrollBar ScrollBar::New(Toolkit::ScrollBar::Direction direction)
768 {
769   // Create the implementation, temporarily owned by this handle on stack
770   IntrusivePtr< ScrollBar > impl = new ScrollBar(direction);
771
772   // Pass ownership to CustomActor handle
773   Toolkit::ScrollBar handle( *impl );
774
775   // Second-phase init of the implementation
776   // This can only be done after the CustomActor connection has been made...
777   impl->Initialize();
778
779   return handle;
780 }
781
782 } // namespace Internal
783
784 } // namespace Toolkit
785
786 } // namespace Dali