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