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