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