Merge "Added scroll-bar to text selection toolbar" into devel/master
[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   indicator.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
239   SetScrollIndicator(indicator);
240 }
241
242 void ScrollBar::SetScrollIndicator( Actor indicator )
243 {
244   // Don't allow empty handle
245   if( indicator )
246   {
247     // Remove current Indicator
248     if( mIndicator )
249     {
250       Self().Remove( mIndicator );
251     }
252     mIndicator = indicator;
253
254     Toolkit::Control control = Toolkit::Control::DownCast( mIndicator );
255     if( control )
256     {
257       control.SetStyleName( "ScrollBarIndicator" );
258     }
259
260     mIndicatorFirstShow = true;
261     Self().Add( mIndicator );
262
263     EnableGestureDetection( Gesture::Type( Gesture::Pan ) );
264
265     PanGestureDetector detector( GetPanGestureDetector() );
266     detector.DetachAll();
267     detector.Attach( mIndicator );
268
269     unsigned int childCount = mIndicator.GetChildCount();
270     for ( unsigned int index = 0; index < childCount; index++ )
271     {
272       Actor child = mIndicator.GetChildAt( index );
273       if ( child )
274       {
275         detector.Attach( child );
276       }
277     }
278   }
279   else
280   {
281     DALI_LOG_ERROR("Empty handle of scroll indicator\n");
282   }
283 }
284
285 Actor ScrollBar::GetScrollIndicator()
286 {
287   return mIndicator;
288 }
289
290 void ScrollBar::ApplyConstraints()
291 {
292   Handle scrollableHandle = mScrollableObject.GetBaseHandle();
293
294   if( scrollableHandle )
295   {
296     if(mIndicatorSizeConstraint)
297     {
298       mIndicatorSizeConstraint.Remove();
299     }
300
301     // Set indicator height according to the indicator's height policy
302     if(mIndicatorHeightPolicy == Toolkit::ScrollBar::Fixed)
303     {
304       mIndicator.SetSize(Self().GetCurrentSize().width, mIndicatorFixedHeight);
305     }
306     else
307     {
308       mIndicatorSizeConstraint = Constraint::New<Vector3>( mIndicator, Actor::Property::SIZE,
309                                                            IndicatorSizeConstraint( mIndicatorMinimumHeight, mIndicatorStartPadding + mIndicatorEndPadding ) );
310       mIndicatorSizeConstraint.AddSource( ParentSource( Actor::Property::SIZE ) );
311       mIndicatorSizeConstraint.AddSource( Source( scrollableHandle, mPropertyScrollContentSize ) );
312       mIndicatorSizeConstraint.Apply();
313     }
314
315     if(mIndicatorPositionConstraint)
316     {
317       mIndicatorPositionConstraint.Remove();
318     }
319
320     mIndicatorPositionConstraint = Constraint::New<Vector3>( mIndicator, Actor::Property::POSITION,
321                                                              IndicatorPositionConstraint( mIndicatorStartPadding, mIndicatorEndPadding ) );
322     mIndicatorPositionConstraint.AddSource( LocalSource( Actor::Property::SIZE ) );
323     mIndicatorPositionConstraint.AddSource( ParentSource( Actor::Property::SIZE ) );
324     mIndicatorPositionConstraint.AddSource( Source( scrollableHandle, mPropertyScrollPosition ) );
325     mIndicatorPositionConstraint.AddSource( Source( scrollableHandle, mPropertyMinScrollPosition ) );
326     mIndicatorPositionConstraint.AddSource( Source( scrollableHandle, mPropertyMaxScrollPosition ) );
327     mIndicatorPositionConstraint.Apply();
328   }
329 }
330
331 void ScrollBar::SetScrollPositionIntervals( const Dali::Vector<float>& positions )
332 {
333   mScrollPositionIntervals = positions;
334
335   Handle scrollableHandle = mScrollableObject.GetBaseHandle();
336
337   if( scrollableHandle )
338   {
339     if( mPositionNotification )
340     {
341       scrollableHandle.RemovePropertyNotification(mPositionNotification);
342     }
343
344     mPositionNotification = scrollableHandle.AddPropertyNotification( mPropertyScrollPosition, VariableStepCondition(mScrollPositionIntervals) );
345     mPositionNotification.NotifySignal().Connect( this, &ScrollBar::OnScrollPositionIntervalReached );
346   }
347 }
348
349 Dali::Vector<float> ScrollBar::GetScrollPositionIntervals() const
350 {
351   return mScrollPositionIntervals;
352 }
353
354 void ScrollBar::OnScrollPositionIntervalReached(PropertyNotification& source)
355 {
356   // Emit the signal to notify the scroll position crossing
357   Handle scrollableHandle = mScrollableObject.GetBaseHandle();
358   if(scrollableHandle)
359   {
360     mScrollPositionIntervalReachedSignal.Emit(scrollableHandle.GetProperty<float>(mPropertyScrollPosition));
361   }
362 }
363
364 void ScrollBar::ShowIndicator()
365 {
366   // Cancel any animation
367   if(mAnimation)
368   {
369     mAnimation.Clear();
370     mAnimation.Reset();
371   }
372
373   if( mIndicatorFirstShow )
374   {
375     // Preserve the alpha value from the stylesheet
376     mIndicatorShowAlpha = Self().GetCurrentColor().a;
377     mIndicatorFirstShow = false;
378   }
379
380   if(mIndicatorShowDuration > 0.0f)
381   {
382     mAnimation = Animation::New( mIndicatorShowDuration );
383     mAnimation.AnimateTo( Property( mIndicator, Actor::Property::COLOR_ALPHA ), mIndicatorShowAlpha, AlphaFunction::EASE_IN );
384     mAnimation.Play();
385   }
386   else
387   {
388     mIndicator.SetOpacity(mIndicatorShowAlpha);
389   }
390 }
391
392 void ScrollBar::HideIndicator()
393 {
394   // Cancel any animation
395   if(mAnimation)
396   {
397     mAnimation.Clear();
398     mAnimation.Reset();
399   }
400
401   if(mIndicatorHideDuration > 0.0f)
402   {
403     mAnimation = Animation::New( mIndicatorHideDuration );
404     mAnimation.AnimateTo( Property( mIndicator, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunction::EASE_IN );
405     mAnimation.Play();
406   }
407   else
408   {
409     mIndicator.SetOpacity(0.0f);
410   }
411 }
412
413 bool ScrollBar::OnPanGestureProcessTick()
414 {
415   // Update the scroll position property.
416   Handle scrollableHandle = mScrollableObject.GetBaseHandle();
417   if( scrollableHandle )
418   {
419     scrollableHandle.SetProperty(mPropertyScrollPosition, mCurrentScrollPosition);
420   }
421
422   return true;
423 }
424
425 void ScrollBar::OnPan( const PanGesture& gesture )
426 {
427   Handle scrollableHandle = mScrollableObject.GetBaseHandle();
428
429   if(scrollableHandle)
430   {
431     Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast(scrollableHandle);
432
433     switch(gesture.state)
434     {
435       case Gesture::Started:
436       {
437         if( !mPanProcessTimer )
438         {
439           // Make sure the pan gesture is only being processed once per frame.
440           mPanProcessTimer = Timer::New( DEFAULT_PAN_GESTURE_PROCESS_TIME );
441           mPanProcessTimer.TickSignal().Connect( this, &ScrollBar::OnPanGestureProcessTick );
442           mPanProcessTimer.Start();
443         }
444
445         ShowIndicator();
446         mScrollStart = scrollableHandle.GetProperty<float>(mPropertyScrollPosition);
447         mGestureDisplacement = Vector3::ZERO;
448         mIsPanning = true;
449
450         break;
451       }
452       case Gesture::Continuing:
453       {
454         mGestureDisplacement.x += gesture.displacement.x;
455         mGestureDisplacement.y += gesture.displacement.y;
456
457         float minScrollPosition = scrollableHandle.GetProperty<float>( mPropertyMinScrollPosition );
458         float maxScrollPosition = scrollableHandle.GetProperty<float>( mPropertyMaxScrollPosition );
459
460         // The domain size is the internal range
461         float domainSize = maxScrollPosition - minScrollPosition;
462         float logicalSize = Self().GetCurrentSize().y - ( mIndicator.GetCurrentSize().y + mIndicatorStartPadding + mIndicatorEndPadding );
463
464         mCurrentScrollPosition = mScrollStart - ( ( mGestureDisplacement.y * domainSize ) / logicalSize );
465         mCurrentScrollPosition = -std::min( maxScrollPosition, std::max( -mCurrentScrollPosition, minScrollPosition ) );
466
467         break;
468       }
469       default:
470       {
471         mIsPanning = false;
472
473         if( mPanProcessTimer )
474         {
475           // Destroy the timer when pan gesture is finished.
476           mPanProcessTimer.Stop();
477           mPanProcessTimer.TickSignal().Disconnect( this, &ScrollBar::OnPanGestureProcessTick );
478           mPanProcessTimer.Reset();
479         }
480
481         if(itemView)
482         {
483           // Refresh the ItemView cache with extra items
484           GetImpl(itemView).DoRefresh(mCurrentScrollPosition, true);
485         }
486
487         mPanFinishedSignal.Emit();
488
489         break;
490       }
491     }
492
493     if(itemView)
494     {
495       // Disable automatic refresh in ItemView during fast scrolling
496       GetImpl(itemView).SetRefreshEnabled(!mIsPanning);
497     }
498   }
499 }
500
501 void ScrollBar::OnSizeSet( const Vector3& size )
502 {
503   if(mIndicatorHeightPolicy == Toolkit::ScrollBar::Fixed)
504   {
505     mIndicator.SetSize(size.width, mIndicatorFixedHeight);
506   }
507
508   Control::OnSizeSet( size );
509 }
510
511 void ScrollBar::SetScrollDirection( Toolkit::ScrollBar::Direction direction )
512 {
513   mDirection = direction;
514 }
515
516 Toolkit::ScrollBar::Direction ScrollBar::GetScrollDirection() const
517 {
518   return mDirection;
519 }
520
521 void ScrollBar::SetIndicatorHeightPolicy( Toolkit::ScrollBar::IndicatorHeightPolicy policy )
522 {
523   if( policy != mIndicatorHeightPolicy )
524   {
525     mIndicatorHeightPolicy = policy;
526     ApplyConstraints();
527   }
528 }
529
530 Toolkit::ScrollBar::IndicatorHeightPolicy ScrollBar::GetIndicatorHeightPolicy() const
531 {
532   return mIndicatorHeightPolicy;
533 }
534
535 void ScrollBar::SetIndicatorFixedHeight( float height )
536 {
537   mIndicatorFixedHeight = height;
538
539   if(mIndicatorHeightPolicy == Toolkit::ScrollBar::Fixed)
540   {
541     mIndicator.SetSize(Self().GetCurrentSize().width, mIndicatorFixedHeight);
542   }
543 }
544
545 float ScrollBar::GetIndicatorFixedHeight() const
546 {
547   return mIndicatorFixedHeight;
548 }
549
550 void ScrollBar::SetIndicatorShowDuration( float durationSeconds )
551 {
552   mIndicatorShowDuration = durationSeconds;
553 }
554
555 float ScrollBar::GetIndicatorShowDuration() const
556 {
557   return mIndicatorShowDuration;
558 }
559
560 void ScrollBar::SetIndicatorHideDuration( float durationSeconds )
561 {
562   mIndicatorHideDuration = durationSeconds;
563 }
564
565 float ScrollBar::GetIndicatorHideDuration() const
566 {
567   return mIndicatorHideDuration;
568 }
569
570 void ScrollBar::OnScrollDirectionPropertySet( Property::Value propertyValue )
571 {
572   std::string directionName( propertyValue.Get<std::string>() );
573   if(directionName == "Vertical")
574   {
575     SetScrollDirection(Toolkit::ScrollBar::Vertical);
576   }
577   else if(directionName == "Horizontal")
578   {
579     SetScrollDirection(Toolkit::ScrollBar::Horizontal);
580   }
581   else
582   {
583     DALI_ASSERT_ALWAYS( !"ScrollBar::OnScrollDirectionPropertySet(). Invalid Property value." );
584   }
585 }
586
587 void ScrollBar::OnIndicatorHeightPolicyPropertySet( Property::Value propertyValue )
588 {
589   std::string policyName( propertyValue.Get<std::string>() );
590   if(policyName == "Variable")
591   {
592     SetIndicatorHeightPolicy(Toolkit::ScrollBar::Variable);
593   }
594   else if(policyName == "Fixed")
595   {
596     SetIndicatorHeightPolicy(Toolkit::ScrollBar::Fixed);
597   }
598   else
599   {
600     DALI_ASSERT_ALWAYS( !"ScrollBar::OnIndicatorHeightPolicyPropertySet(). Invalid Property value." );
601   }
602 }
603
604 bool ScrollBar::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
605 {
606   Dali::BaseHandle handle( object );
607
608   bool connected( true );
609   Toolkit::ScrollBar scrollBar = Toolkit::ScrollBar::DownCast( handle );
610
611   if( 0 == strcmp( signalName.c_str(), PAN_FINISHED_SIGNAL ) )
612   {
613     scrollBar.PanFinishedSignal().Connect( tracker, functor );
614   }
615   else if( 0 == strcmp( signalName.c_str(), SCROLL_POSITION_INTERVAL_REACHED_SIGNAL ) )
616   {
617     scrollBar.ScrollPositionIntervalReachedSignal().Connect( tracker, functor );
618   }
619   else
620   {
621     // signalName does not match any signal
622     connected = false;
623   }
624
625   return connected;
626 }
627
628 void ScrollBar::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
629 {
630   Toolkit::ScrollBar scrollBar = Toolkit::ScrollBar::DownCast( Dali::BaseHandle( object ) );
631
632   if( scrollBar )
633   {
634     ScrollBar& scrollBarImpl( GetImpl( scrollBar ) );
635     switch( index )
636     {
637       case Toolkit::ScrollBar::Property::SCROLL_DIRECTION:
638       {
639         scrollBarImpl.OnScrollDirectionPropertySet( value );
640         break;
641       }
642       case Toolkit::ScrollBar::Property::INDICATOR_HEIGHT_POLICY:
643       {
644         scrollBarImpl.OnIndicatorHeightPolicyPropertySet( value );
645         break;
646       }
647       case Toolkit::ScrollBar::Property::INDICATOR_FIXED_HEIGHT:
648       {
649         scrollBarImpl.SetIndicatorFixedHeight(value.Get<float>());
650         break;
651       }
652       case Toolkit::ScrollBar::Property::INDICATOR_SHOW_DURATION:
653       {
654         scrollBarImpl.SetIndicatorShowDuration(value.Get<float>());
655         break;
656       }
657       case Toolkit::ScrollBar::Property::INDICATOR_HIDE_DURATION:
658       {
659         scrollBarImpl.SetIndicatorHideDuration(value.Get<float>());
660         break;
661       }
662       case Toolkit::ScrollBar::Property::SCROLL_POSITION_INTERVALS:
663       {
664         Property::Array* array = value.GetArray();
665         if( array )
666         {
667           Dali::Vector<float> positions;
668           size_t positionCount = array->Count();
669           positions.Resize( positionCount );
670           for( size_t i = 0; i != positionCount; ++i )
671           {
672             array->GetElementAt( i ).Get( positions[i] );
673           }
674
675           scrollBarImpl.SetScrollPositionIntervals(positions);
676         }
677         break;
678       }
679       case Toolkit::ScrollBar::Property::INDICATOR_MINIMUM_HEIGHT:
680       {
681         scrollBarImpl.mIndicatorMinimumHeight = value.Get<float>();
682         scrollBarImpl.ApplyConstraints();
683         break;
684       }
685       case Toolkit::ScrollBar::Property::INDICATOR_START_PADDING:
686       {
687         scrollBarImpl.mIndicatorStartPadding = value.Get<float>();
688         scrollBarImpl.ApplyConstraints();
689         break;
690       }
691       case Toolkit::ScrollBar::Property::INDICATOR_END_PADDING:
692       {
693         scrollBarImpl.mIndicatorEndPadding = value.Get<float>();
694         scrollBarImpl.ApplyConstraints();
695         break;
696       }
697     }
698   }
699 }
700
701 Property::Value ScrollBar::GetProperty( BaseObject* object, Property::Index index )
702 {
703   Property::Value value;
704
705   Toolkit::ScrollBar scrollBar = Toolkit::ScrollBar::DownCast( Dali::BaseHandle( object ) );
706
707   if( scrollBar )
708   {
709     ScrollBar& scrollBarImpl( GetImpl( scrollBar ) );
710     switch( index )
711     {
712       case Toolkit::ScrollBar::Property::SCROLL_DIRECTION:
713       {
714         value = SCROLL_DIRECTION_NAME[ scrollBarImpl.GetScrollDirection() ];
715         break;
716       }
717       case Toolkit::ScrollBar::Property::INDICATOR_HEIGHT_POLICY:
718       {
719         value = INDICATOR_HEIGHT_POLICY_NAME[ scrollBarImpl.GetIndicatorHeightPolicy() ];
720         break;
721       }
722       case Toolkit::ScrollBar::Property::INDICATOR_FIXED_HEIGHT:
723       {
724         value = scrollBarImpl.GetIndicatorFixedHeight();
725         break;
726       }
727       case Toolkit::ScrollBar::Property::INDICATOR_SHOW_DURATION:
728       {
729         value = scrollBarImpl.GetIndicatorShowDuration();
730         break;
731       }
732       case Toolkit::ScrollBar::Property::INDICATOR_HIDE_DURATION:
733       {
734         value = scrollBarImpl.GetIndicatorHideDuration();
735         break;
736       }
737       case Toolkit::ScrollBar::Property::SCROLL_POSITION_INTERVALS:
738       {
739         Property::Value value( Property::ARRAY );
740         Property::Array* array = value.GetArray();
741
742         if( array )
743         {
744           Dali::Vector<float> positions = scrollBarImpl.GetScrollPositionIntervals();
745           size_t positionCount( array->Count() );
746           for( size_t i( 0 ); i != positionCount; ++i )
747           {
748             array->PushBack( positions[i] );
749           }
750         }
751         break;
752       }
753       case Toolkit::ScrollBar::Property::INDICATOR_MINIMUM_HEIGHT:
754       {
755         value = scrollBarImpl.mIndicatorMinimumHeight;
756         break;
757       }
758       case Toolkit::ScrollBar::Property::INDICATOR_START_PADDING:
759       {
760         value = scrollBarImpl.mIndicatorStartPadding;
761         break;
762       }
763       case Toolkit::ScrollBar::Property::INDICATOR_END_PADDING:
764       {
765         value = scrollBarImpl.mIndicatorEndPadding;
766         break;
767       }
768     }
769   }
770   return value;
771 }
772
773 Toolkit::ScrollBar ScrollBar::New(Toolkit::ScrollBar::Direction direction)
774 {
775   // Create the implementation, temporarily owned by this handle on stack
776   IntrusivePtr< ScrollBar > impl = new ScrollBar(direction);
777
778   // Pass ownership to CustomActor handle
779   Toolkit::ScrollBar handle( *impl );
780
781   // Second-phase init of the implementation
782   // This can only be done after the CustomActor connection has been made...
783   impl->Initialize();
784
785   return handle;
786 }
787
788 } // namespace Internal
789
790 } // namespace Toolkit
791
792 } // namespace Dali