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