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