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