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