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