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