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