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