2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/controls/slider/slider-impl.h>
22 #include <cstring> // for strcmp
25 #include <dali/public-api/events/touch-data.h>
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/public-api/object/type-registry-helper.h>
28 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
31 #include <dali-toolkit/public-api/controls/control-impl.h>
32 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
45 namespace // Unnamed namespace
50 return Dali::Toolkit::Slider::New();
53 // Setup properties, signals and actions using the type-registry.
54 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Slider, Toolkit::Control, Create )
56 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "lowerBound", FLOAT, LOWER_BOUND )
57 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "upperBound", FLOAT, UPPER_BOUND )
58 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "value", FLOAT, VALUE )
59 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "trackVisual", MAP, TRACK_VISUAL )
60 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "handleVisual", MAP, HANDLE_VISUAL )
61 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "progressVisual", MAP, PROGRESS_VISUAL )
62 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "popupVisual", MAP, POPUP_VISUAL )
63 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "popupArrowVisual", MAP, POPUP_ARROW_VISUAL )
64 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "disabledColor", VECTOR4, DISABLED_COLOR )
65 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "valuePrecision", INTEGER, VALUE_PRECISION )
66 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "showPopup", BOOLEAN, SHOW_POPUP )
67 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "showValue", BOOLEAN, SHOW_VALUE )
68 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "marks", ARRAY, MARKS )
69 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "snapToMarks", BOOLEAN, SNAP_TO_MARKS )
70 DALI_PROPERTY_REGISTRATION( Toolkit, Slider, "markTolerance", FLOAT, MARK_TOLERANCE )
72 DALI_SIGNAL_REGISTRATION( Toolkit, Slider, "valueChanged", SIGNAL_VALUE_CHANGED )
73 DALI_SIGNAL_REGISTRATION( Toolkit, Slider, "mark", SIGNAL_MARK )
75 DALI_TYPE_REGISTRATION_END()
77 const float MARK_SNAP_TOLERANCE = 0.05f; // 5% of slider width
79 const int VALUE_VIEW_SHOW_DURATION = 1000; // millisec
80 const int VALUE_VIEW_SHOW_DURATION_LONG = 2000; // millisec
82 const float VALUE_VERTICAL_OFFSET = 48.0f;
84 const float DEFAULT_WIDTH = 0.0f;
85 const float DEFAULT_HEIGHT = 27.0f;
86 const float DEFAULT_HIT_HEIGHT = 72.0f;
87 const float DEFAULT_HANDLE_HEIGHT = DEFAULT_HIT_HEIGHT;
88 const float POPUP_TEXT_PADDING = 10.0f;
90 const char* SKINNED_TRACK_VISUAL = DALI_IMAGE_DIR "slider-skin.9.png";
91 const char* SKINNED_HANDLE_VISUAL = DALI_IMAGE_DIR "slider-skin-handle.png";
92 const char* SKINNED_PROGRESS_VISUAL = DALI_IMAGE_DIR "slider-skin-progress.9.png";
93 const char* SKINNED_POPUP_VISUAL = DALI_IMAGE_DIR "slider-popup.9.png";
94 const char* SKINNED_POPUP_ARROW_VISUAL = DALI_IMAGE_DIR "slider-popup-arrow.png";
96 const Vector2 DEFAULT_HIT_REGION( DEFAULT_WIDTH, DEFAULT_HIT_HEIGHT );
97 const Vector2 DEFAULT_TRACK_REGION( DEFAULT_WIDTH, DEFAULT_HEIGHT );
98 const Vector2 DEFAULT_HANDLE_SIZE( DEFAULT_HANDLE_HEIGHT, DEFAULT_HANDLE_HEIGHT );
100 const Vector4 DEFAULT_DISABLED_COLOR( 0.5f, 0.5f, 0.5f, 1.0f );
102 const float VALUE_POPUP_MARGIN = 10.0f;
103 const float VALUE_POPUP_HEIGHT = 81.0f;
104 const float VALUE_POPUP_MIN_WIDTH = 54.0f;
106 const float DEFAULT_LOWER_BOUND = 0.0f;
107 const float DEFAULT_UPPER_BOUND = 1.0f;
108 const float DEFAULT_VALUE = 0.0f;
109 const int DEFAULT_VALUE_PRECISION = 0;
110 const bool DEFAULT_SHOW_POPUP = false;
111 const bool DEFAULT_SHOW_VALUE = true;
112 const bool DEFAULT_ENABLED = true;
113 const bool DEFAULT_SNAP_TO_MARKS = false;
115 } // Unnamed namespace
117 ///////////////////////////////////////////////////////////////////////////////////////////////////
119 ///////////////////////////////////////////////////////////////////////////////////////////////////
121 Dali::Toolkit::Slider Slider::New()
123 // Create the implementation
124 SliderPtr slider( new Slider() );
126 // Pass ownership to CustomActor via derived handle
127 Dali::Toolkit::Slider handle( *slider );
129 // Second-phase init of the implementation
130 // This can only be done after the CustomActor connection has been made...
131 slider->Initialize();
137 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
140 mPopupArrowVisual(""),
148 mDisabledColor( 0.0f, 0.0f, 0.0f, 0.0f ),
149 mHitRegion( 0.0f, 0.0f ),
150 mTrackRegion( 0.0f, 0.0f ),
151 mHandleSize( 0.0f, 0.0f ),
155 mMarkTolerance( 0.0f ),
156 mValuePrecision( 0 ),
159 mSnapToMarks( false )
161 DevelControl::SetAccessibilityConstructor( Self(), []( Dali::Actor actor ) {
162 return std::unique_ptr< Dali::Accessibility::Accessible >(
163 new AccessibleImpl( actor, Dali::Accessibility::Role::SLIDER ) );
171 void Slider::OnInitialize()
179 SetHitRegion( DEFAULT_HIT_REGION );
180 SetTrackRegion( DEFAULT_TRACK_REGION );
181 SetHandleSize( DEFAULT_HANDLE_SIZE );
183 SetTrackVisual( SKINNED_TRACK_VISUAL );
184 SetHandleVisual( SKINNED_HANDLE_VISUAL );
185 SetProgressVisual( SKINNED_PROGRESS_VISUAL );
186 SetPopupVisual( SKINNED_POPUP_VISUAL );
187 SetPopupArrowVisual( SKINNED_POPUP_ARROW_VISUAL );
189 SetShowPopup( DEFAULT_SHOW_POPUP );
190 SetShowValue( DEFAULT_SHOW_VALUE );
192 SetEnabled( DEFAULT_ENABLED );
193 SetDisabledColor( DEFAULT_DISABLED_COLOR );
195 SetSnapToMarks( DEFAULT_SNAP_TO_MARKS );
196 SetMarkTolerance( MARK_SNAP_TOLERANCE );
198 SetLowerBound( DEFAULT_LOWER_BOUND );
199 SetUpperBound( DEFAULT_UPPER_BOUND );
201 SetValuePrecision( DEFAULT_VALUE_PRECISION );
202 mValue = DEFAULT_VALUE;
203 DisplayValue( mValue, false ); // Run this last to display the correct value
205 // Size the Slider actor to a default
206 self.SetSize( DEFAULT_HIT_REGION.x, DEFAULT_HIT_REGION.y );
208 // Connect to the touch signal
209 self.TouchSignal().Connect( this, &Slider::OnTouch );
212 void Slider::OnRelayout( const Vector2& size, RelayoutContainer& container )
214 SetHitRegion( Vector2( size.x, GetHitRegion().y ) );
215 // Factor in handle overshoot into size of backing
216 SetTrackRegion( Vector2( size.x - GetHandleSize().x, GetTrackRegion().y ) );
217 Control::OnRelayout( size, container );
220 bool Slider::OnTouch(Actor actor, const TouchData& touch)
222 if( mState != DISABLED )
224 const PointState::Type touchState = touch.GetState(0);
226 if( touchState == PointState::DOWN )
230 float percentage = MapPercentage( touch.GetLocalPosition( 0 ) );
231 float value = MapBounds( ( GetSnapToMarks() ) ? SnapToMark( percentage ) : MarkFilter( percentage ), GetLowerBound(), GetUpperBound() );
233 DisplayPopup( value );
235 else if( touchState == PointState::UP )
237 if( mState == PRESSED )
240 mSlidingFinishedSignal.Emit( Toolkit::Slider::DownCast( Self() ), GetValue() );
248 void Slider::OnPan( Actor actor, const PanGesture& gesture )
250 // gesture.position is in local actor coordinates
251 if( mState != DISABLED )
253 switch( gesture.state )
255 case Gesture::Continuing:
257 if( mState == PRESSED )
259 float value = MapBounds( MarkFilter ( MapPercentage( gesture.position ) ), GetLowerBound(), GetUpperBound() );
261 DisplayPopup( value );
265 case Gesture::Finished:
267 if( mState == PRESSED )
269 if( GetSnapToMarks() )
271 float value = MapBounds( SnapToMark( MapPercentage( gesture.position ) ), GetLowerBound(), GetUpperBound() );
273 DisplayPopup( value );
275 mSlidingFinishedSignal.Emit( Toolkit::Slider::DownCast( Self() ), GetValue() );
289 float Slider::HitSpaceToDomain( float x )
291 float halfRegionWidth = GetHitRegion().x * 0.5f;
292 float halfDomainWidth = ( mDomain.to.x - mDomain.from.x ) * 0.5f;
293 float endDiff = halfRegionWidth - halfDomainWidth;
298 float Slider::MapPercentage( const Vector2& point )
300 return Clamp( ( HitSpaceToDomain( point.x ) - mDomain.from.x ) / ( mDomain.to.x - mDomain.from.x ), 0.0f, 1.0f );
303 float Slider::MapValuePercentage( float value )
305 return ( value - GetLowerBound() ) / ( GetUpperBound() - GetLowerBound() );
308 float Slider::MapBounds( float percent, float lowerBound, float upperBound )
310 return lowerBound + percent * ( upperBound - lowerBound );
313 Slider::Domain Slider::CalcDomain( const Vector2& currentSize )
315 return Domain( Vector2( 0.0f, 0.0f ), currentSize );
318 void Slider::DisplayValue( float value, bool raiseSignals )
320 float clampedValue = Clamp( value, GetLowerBound(), GetUpperBound() );
322 float percent = MapValuePercentage( clampedValue );
324 float x = mDomain.from.x + percent * ( mDomain.to.x - mDomain.from.x );
331 mProgress.SetSize( x, GetTrackRegion().y );
337 Toolkit::Slider self = Toolkit::Slider::DownCast( Self() );
338 mValueChangedSignal.Emit( self, clampedValue );
341 if( MarkReached( percent, markIndex ) )
343 mMarkReachedSignal.Emit( self, markIndex );
347 if( mHandleValueTextLabel )
349 std::stringstream ss;
350 ss.precision( GetValuePrecision() );
351 ss << std::fixed << clampedValue;
353 std::string label = mHandleValueTextLabel.GetProperty<std::string>( Toolkit::TextLabel::Property::TEXT );
354 if( label.compare(ss.str()) )
356 mHandleValueTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, ss.str() );
361 void Slider::SetMarks( const MarkList& marks )
366 const Slider::MarkList& Slider::GetMarks() const
371 void Slider::SetSnapToMarks( bool snap )
376 bool Slider::GetSnapToMarks() const
381 Actor Slider::CreateHitRegion()
383 Actor hitRegion = Actor::New();
384 hitRegion.SetParentOrigin( ParentOrigin::CENTER );
385 hitRegion.SetAnchorPoint( AnchorPoint::CENTER );
386 hitRegion.TouchSignal().Connect( this, &Slider::OnTouch );
391 Toolkit::ImageView Slider::CreateTrack()
393 Toolkit::ImageView track = Toolkit::ImageView::New();
394 track.SetName("SliderTrack");
395 track.SetParentOrigin( ParentOrigin::CENTER );
396 track.SetAnchorPoint( AnchorPoint::CENTER );
400 void Slider::SetTrackVisual( const std::string& filename )
402 if( mHandle && ( filename.size() > 0 ) )
404 mTrack.SetImage( filename );
405 mTrackVisual = filename;
409 void Slider::SetTrackVisual( Property::Map map )
411 Property::Value* imageValue = map.Find( "url" );
414 mTrackVisual.clear();
415 std::string filename;
416 if( imageValue->Get( filename ) )
418 if( mTrack && ( filename.size() > 0 ) )
420 mTrack.SetImage( filename );
426 Property::Value* sizeValue = map.Find( "size" );
430 if( sizeValue->Get( size ) )
435 mTrack.SetSize( mTrackRegion );
438 ResizeProgressRegion( Vector2( 0.0f, mTrackRegion.y ) );
440 mDomain = CalcDomain( mTrackRegion );
442 // Set the progress bar to correct width
443 DisplayValue( GetValue(), false );
448 std::string Slider::GetTrackVisual()
453 Toolkit::ImageView Slider::CreateProgress()
455 Toolkit::ImageView progress = Toolkit::ImageView::New();
456 progress.SetName("SliderProgress");
457 progress.SetParentOrigin( ParentOrigin::CENTER_LEFT );
458 progress.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
463 void Slider::SetProgressVisual( const std::string& filename )
465 if( mProgress && ( filename.size() > 0 ) )
467 mProgress.SetImage( filename );
468 mProgressVisual = filename;
472 void Slider::SetProgressVisual( Property::Map map )
474 Property::Value* imageValue = map.Find( "url" );
477 mProgressVisual.clear();
478 std::string filename;
479 if( imageValue->Get( filename ) )
481 if( mProgress && ( filename.size() > 0 ) )
483 mProgress.SetImage( filename );
490 std::string Slider::GetProgressVisual()
492 return mProgressVisual;
495 void Slider::SetPopupVisual( const std::string& filename )
497 mPopupVisual = filename;
500 void Slider::SetPopupVisual( Property::Map map )
502 Property::Value* imageValue = map.Find( "url" );
505 mPopupVisual.clear();
506 std::string filename;
507 if( imageValue->Get( filename ) )
509 if( mPopup && ( filename.size() > 0 ) )
511 mPopup.SetImage( filename );
518 std::string Slider::GetPopupVisual()
523 void Slider::CreatePopupImage( const std::string& filename )
525 if( mPopup && ( filename.size() > 0 ) )
528 map[Toolkit::ImageVisual::Property::URL] = filename;
529 mPopup.SetProperty( Toolkit::ImageView::Property::IMAGE, map );
533 void Slider::SetPopupArrowVisual( const std::string& filename )
535 mPopupArrowVisual = filename;
538 void Slider::SetPopupArrowVisual( Property::Map map )
540 Property::Value* imageValue = map.Find( "url" );
543 mPopupArrowVisual.clear();
544 std::string filename;
545 if( imageValue->Get( filename ) )
547 if( mPopupArrow && ( filename.size() > 0 ) )
549 mPopupArrow.SetImage( filename );
550 mPopupArrowMap = map;
556 std::string Slider::GetPopupArrowVisual()
558 return mPopupArrowVisual;
561 void Slider::CreatePopupArrowImage( const std::string& filename )
563 if( mPopupArrow && ( filename.size() > 0 ) )
566 map[Toolkit::ImageVisual::Property::URL] = filename;
567 mPopupArrow.SetProperty( Toolkit::ImageView::Property::IMAGE, map );
571 void Slider::ResizeProgressRegion( const Vector2& region )
575 mProgress.SetSize( region );
579 Toolkit::ImageView Slider::CreateHandle()
581 Toolkit::ImageView handle = Toolkit::ImageView::New();
582 handle.SetName("SliderHandle");
583 handle.SetParentOrigin( ParentOrigin::CENTER_LEFT );
584 handle.SetAnchorPoint( AnchorPoint::CENTER );
589 Toolkit::ImageView Slider::CreatePopupArrow()
591 Toolkit::ImageView arrow = Toolkit::ImageView::New();
592 arrow.SetStyleName("SliderPopupArrow");
593 arrow.SetName("SliderPopupArrow");
594 arrow.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
595 arrow.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
600 Toolkit::TextLabel Slider::CreatePopupText()
602 Toolkit::TextLabel textLabel = Toolkit::TextLabel::New();
603 textLabel.SetName( "SliderPopupTextLabel" );
604 textLabel.SetStyleName( "SliderPopupTextLabel" );
605 textLabel.SetParentOrigin( ParentOrigin::CENTER );
606 textLabel.SetAnchorPoint( AnchorPoint::CENTER );
607 textLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
608 textLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
609 textLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
610 textLabel.SetPadding( Padding( POPUP_TEXT_PADDING, POPUP_TEXT_PADDING, 0.0f, 0.0f ) );
614 Toolkit::ImageView Slider::CreatePopup()
616 Toolkit::ImageView popup = Toolkit::ImageView::New();
617 popup.SetName( "SliderPopup" );
618 popup.SetParentOrigin( ParentOrigin::TOP_CENTER );
619 popup.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
620 popup.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::WIDTH );
622 mValueTextLabel = CreatePopupText();
623 popup.Add( mValueTextLabel );
628 void Slider::SetHandleVisual( const std::string& filename )
630 if( mHandle && ( filename.size() > 0 ) )
632 mHandle.SetImage( filename );
633 mHandleVisual = filename;
637 void Slider::SetHandleVisual( Property::Map map )
639 Property::Value* imageValue = map.Find( "url" );
642 mHandleVisual.clear();
643 std::string filename;
644 if( imageValue->Get( filename ) )
646 if( mHandle && ( filename.size() > 0 ) )
648 mHandle.SetImage( filename );
654 Property::Value* sizeValue = map.Find( "size" );
658 if( sizeValue->Get( size ) )
661 ResizeHandleSize( mHandleSize );
663 Vector2 hitRegion = GetHitRegion();
664 hitRegion.x += mHandleSize.x;
665 SetHitRegion( hitRegion );
670 std::string Slider::GetHandleVisual()
672 return mHandleVisual;
675 void Slider::ResizeHandleSize( const Vector2& size )
679 mHandle.SetSize( size );
683 void Slider::CreateHandleValueDisplay()
685 if( mHandle && !mHandleValueTextLabel )
687 mHandleValueTextLabel = Toolkit::TextLabel::New();
688 mHandleValueTextLabel.SetName("SliderHandleTextLabel");
689 mHandleValueTextLabel.SetStyleName("SliderHandleTextLabel");
690 mHandleValueTextLabel.SetParentOrigin( ParentOrigin::CENTER );
691 mHandleValueTextLabel.SetAnchorPoint( AnchorPoint::CENTER );
692 mHandleValueTextLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
693 mHandleValueTextLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
694 mHandle.Add( mHandleValueTextLabel );
698 void Slider::DestroyHandleValueDisplay()
700 UnparentAndReset(mHandleValueTextLabel);
703 Actor Slider::CreateValueDisplay()
705 Actor popup = Actor::New();
706 popup.SetParentOrigin( ParentOrigin::TOP_CENTER );
707 popup.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
709 mPopupArrow = CreatePopupArrow();
710 popup.Add( mPopupArrow );
712 mPopup = CreatePopup();
713 mPopup.SetSize( 0.0f, VALUE_POPUP_HEIGHT );
714 mPopupArrow.Add( mPopup );
719 Toolkit::Slider::ValueChangedSignalType& Slider::ValueChangedSignal()
721 return mValueChangedSignal;
724 Toolkit::Slider::ValueChangedSignalType& Slider::SlidingFinishedSignal()
726 return mSlidingFinishedSignal;
729 Toolkit::Slider::MarkReachedSignalType& Slider::MarkReachedSignal()
731 return mMarkReachedSignal;
734 void Slider::UpdateSkin()
740 mTrack.SetColor( Color::WHITE );
741 mHandle.SetColor( Color::WHITE );
742 mProgress.SetColor( Color::WHITE );
747 Vector4 disabledColor = GetDisabledColor();
748 mTrack.SetColor( disabledColor );
749 mHandle.SetColor( disabledColor );
750 mProgress.SetColor( disabledColor );
764 void Slider::CreateChildren()
769 mHitArea = CreateHitRegion();
770 mPanDetector = PanGestureDetector::New();
771 mPanDetector.Attach( mHitArea );
772 mPanDetector.DetectedSignal().Connect( this, &Slider::OnPan );
773 self.Add( mHitArea );
776 mTrack = CreateTrack();
780 mProgress = CreateProgress();
781 mTrack.Add( mProgress );
784 mHandle = CreateHandle();
785 mProgress.Add( mHandle );
788 void Slider::SetHitRegion( const Vector2& size )
794 mHitArea.SetSize( mHitRegion );
798 const Vector2& Slider::GetHitRegion() const
803 void Slider::AddPopup()
807 mValueDisplay = CreateValueDisplay();
808 mValueDisplay.SetVisible( false );
809 mHandle.Add( mValueDisplay );
811 CreatePopupImage( GetPopupVisual() );
812 CreatePopupArrowImage( GetPopupArrowVisual() );
814 mValueTimer = Timer::New( VALUE_VIEW_SHOW_DURATION );
815 mValueTimer.TickSignal().Connect( this, &Slider::HideValueView );
819 void Slider::RemovePopup()
826 mPopupArrow.Unparent();
829 mValueDisplay.Unparent();
830 mValueDisplay.Reset();
832 mValueTimer.TickSignal().Disconnect( this, &Slider::HideValueView );
838 float Slider::MarkFilter( float value )
840 const float MARK_TOLERANCE = GetMarkTolerance();
843 for( MarkList::SizeType i = 0; i < mMarks.Count(); ++i)
845 const Property::Value& propertyValue = mMarks[i];
846 propertyValue.Get( mark );
847 mark = MapValuePercentage( mark );
849 // If close to a mark, return the mark
850 if( fabsf( mark - value ) < MARK_TOLERANCE )
859 float Slider::SnapToMark( float value )
861 float closestMark = value;
862 float closestDist = std::numeric_limits<float>::max();
865 for( MarkList::SizeType i = 0; i < mMarks.Count(); ++i)
867 const Property::Value& propertyValue = mMarks[i];
868 propertyValue.Get( mark );
869 mark = MapValuePercentage( mark );
871 float dist = fabsf( mark - value );
872 if( dist < closestDist )
882 bool Slider::MarkReached( float value, int& outIndex )
884 const float MARK_TOLERANCE = GetMarkTolerance();
888 tail = mMarks.Size() - 1;
892 while( head <= tail )
894 current = head + ( tail - head ) / 2;
896 const Property::Value& propertyValue = mMarks[ current ];
897 propertyValue.Get( mark );
898 mark = MapValuePercentage( mark );
900 if( fabsf( mark - value ) < MARK_TOLERANCE )
919 bool Slider::HideValueView()
923 mValueDisplay.SetVisible( false );
929 void Slider::SetLowerBound( float bound )
932 DisplayValue( GetValue(), false );
935 float Slider::GetLowerBound() const
940 void Slider::SetUpperBound( float bound )
943 DisplayValue( GetValue(), false );
946 float Slider::GetUpperBound() const
951 void Slider::SetValue( float value )
954 DisplayValue( mValue, true );
957 float Slider::GetValue() const
962 void Slider::SetTrackRegion( const Vector2& region )
964 mTrackRegion = region;
968 mTrack.SetSize( mTrackRegion );
971 ResizeProgressRegion( Vector2( 0.0f, mTrackRegion.y ) );
973 mDomain = CalcDomain( mTrackRegion );
975 DisplayValue( GetValue(), false ); // Set the progress bar to correct width
978 const Vector2& Slider::GetTrackRegion() const
983 void Slider::SetHandleSize( const Vector2& size )
987 ResizeHandleSize( mHandleSize );
989 Vector2 hitRegion = GetHitRegion();
990 hitRegion.x += mHandleSize.x;
991 SetHitRegion( hitRegion );
994 const Vector2& Slider::GetHandleSize() const
999 void Slider::SetDisabledColor( const Vector4& color )
1001 mDisabledColor = color;
1006 Vector4 Slider::GetDisabledColor() const
1008 return mDisabledColor;
1011 void Slider::SetValuePrecision( int precision )
1013 mValuePrecision = precision;
1016 int Slider::GetValuePrecision() const
1018 return mValuePrecision;
1021 void Slider::SetShowPopup( bool showPopup )
1023 mShowPopup = showPopup;
1036 bool Slider::GetShowPopup() const
1041 void Slider::SetShowValue( bool showValue )
1043 mShowValue = showValue;
1047 CreateHandleValueDisplay();
1051 DestroyHandleValueDisplay();
1055 bool Slider::GetShowValue() const
1060 void Slider::SetEnabled( bool enabled )
1074 bool Slider::IsEnabled() const
1076 return mState != DISABLED;
1079 void Slider::SetMarkTolerance( float tolerance )
1081 mMarkTolerance = tolerance;
1084 float Slider::GetMarkTolerance() const
1086 return mMarkTolerance;
1089 // Static class method to support script connecting signals
1090 bool Slider::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1092 Dali::BaseHandle handle( object );
1094 bool connected = true;
1095 Toolkit::Slider slider = Toolkit::Slider::DownCast( handle );
1097 if( 0 == strcmp( signalName.c_str(), SIGNAL_VALUE_CHANGED ) )
1099 slider.ValueChangedSignal().Connect( tracker, functor );
1101 else if( 0 == strcmp( signalName.c_str(), SIGNAL_MARK ) )
1103 slider.MarkReachedSignal().Connect( tracker, functor );
1107 // signalName does not match any signal
1114 void Slider::DisplayPopup( float value )
1116 // Value displayDoConnectSignal
1117 if( mValueTextLabel )
1119 std::stringstream ss;
1120 ss.precision( GetValuePrecision() );
1121 ss << std::fixed << value;
1122 mValueTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, ss.str() );
1126 mValueDisplay.SetVisible( true );
1128 mValueTimer.SetInterval( VALUE_VIEW_SHOW_DURATION );
1133 void Slider::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
1135 Toolkit::Slider slider = Toolkit::Slider::DownCast( Dali::BaseHandle( object ) );
1139 Slider& sliderImpl( GetImpl( slider ) );
1141 switch ( propertyIndex )
1143 case Toolkit::Slider::Property::LOWER_BOUND:
1145 sliderImpl.SetLowerBound( value.Get< float >() );
1149 case Toolkit::Slider::Property::UPPER_BOUND:
1151 sliderImpl.SetUpperBound( value.Get< float >() );
1155 case Toolkit::Slider::Property::VALUE:
1157 sliderImpl.SetValue( value.Get< float >() );
1161 case Toolkit::Slider::Property::TRACK_VISUAL:
1164 if( value.Get( map ) )
1166 sliderImpl.SetTrackVisual( map );
1171 case Toolkit::Slider::Property::HANDLE_VISUAL:
1174 if( value.Get( map ) )
1176 sliderImpl.SetHandleVisual( map );
1181 case Toolkit::Slider::Property::PROGRESS_VISUAL:
1184 if( value.Get( map ) )
1186 sliderImpl.SetProgressVisual( map );
1191 case Toolkit::Slider::Property::POPUP_VISUAL:
1193 std::string imageUrl;
1194 if( value.Get( imageUrl ) )
1196 sliderImpl.SetPopupVisual( imageUrl );
1199 // If it is not a string, then get a Property::Map from the property if possible.
1201 if( value.Get( map ) )
1203 sliderImpl.SetPopupVisual( map );
1209 case Toolkit::Slider::Property::POPUP_ARROW_VISUAL:
1212 if( value.Get( map ) )
1214 sliderImpl.SetPopupArrowVisual( map );
1219 case Toolkit::Slider::Property::DISABLED_COLOR:
1221 sliderImpl.SetDisabledColor( value.Get< Vector4 >() );
1225 case Toolkit::Slider::Property::VALUE_PRECISION:
1227 sliderImpl.SetValuePrecision( value.Get< int >() );
1231 case Toolkit::Slider::Property::SHOW_POPUP:
1233 sliderImpl.SetShowPopup( value.Get< bool >() );
1237 case Toolkit::Slider::Property::SHOW_VALUE:
1239 sliderImpl.SetShowValue( value.Get< bool >() );
1243 case Toolkit::Slider::Property::MARKS:
1245 sliderImpl.SetMarks( value.Get< Property::Array >() );
1249 case Toolkit::Slider::Property::SNAP_TO_MARKS:
1251 sliderImpl.SetSnapToMarks( value.Get< bool >() );
1255 case Toolkit::Slider::Property::MARK_TOLERANCE:
1257 sliderImpl.SetMarkTolerance( value.Get< float >() );
1264 Property::Value Slider::GetProperty( BaseObject* object, Property::Index propertyIndex )
1266 Property::Value value;
1268 Toolkit::Slider slider = Toolkit::Slider::DownCast( Dali::BaseHandle( object ) );
1272 Slider& sliderImpl( GetImpl( slider ) );
1274 switch ( propertyIndex )
1276 case Toolkit::Slider::Property::LOWER_BOUND:
1278 value = sliderImpl.GetLowerBound();
1282 case Toolkit::Slider::Property::UPPER_BOUND:
1284 value = sliderImpl.GetUpperBound();
1288 case Toolkit::Slider::Property::VALUE:
1290 value = sliderImpl.GetValue();
1294 case Toolkit::Slider::Property::TRACK_VISUAL:
1296 if( !sliderImpl.mTrackVisual.empty() )
1298 value = sliderImpl.GetTrackVisual();
1300 else if( !sliderImpl.mTrackMap.Empty() )
1302 value = sliderImpl.mTrackMap;
1307 case Toolkit::Slider::Property::HANDLE_VISUAL:
1309 if( !sliderImpl.mHandleVisual.empty() )
1311 value = sliderImpl.GetHandleVisual();
1313 else if( !sliderImpl.mHandleMap.Empty() )
1315 value = sliderImpl.mHandleMap;
1320 case Toolkit::Slider::Property::PROGRESS_VISUAL:
1322 if( !sliderImpl.mProgressVisual.empty() )
1324 value = sliderImpl.GetProgressVisual();
1326 else if( !sliderImpl.mProgressMap.Empty() )
1328 value = sliderImpl.mProgressMap;
1333 case Toolkit::Slider::Property::POPUP_VISUAL:
1335 if( !sliderImpl.mPopupVisual.empty() )
1337 value = sliderImpl.GetPopupVisual();
1339 else if( !sliderImpl.mPopupMap.Empty() )
1341 value = sliderImpl.mPopupMap;
1346 case Toolkit::Slider::Property::POPUP_ARROW_VISUAL:
1348 if( !sliderImpl.mPopupArrowVisual.empty() )
1350 value = sliderImpl.GetPopupArrowVisual();
1352 else if( !sliderImpl.mPopupArrowMap.Empty() )
1354 value = sliderImpl.mPopupArrowMap;
1359 case Toolkit::Slider::Property::DISABLED_COLOR:
1361 value = sliderImpl.GetDisabledColor();
1365 case Toolkit::Slider::Property::VALUE_PRECISION:
1367 value = sliderImpl.GetValuePrecision();
1371 case Toolkit::Slider::Property::SHOW_POPUP:
1373 value = sliderImpl.GetShowPopup();
1377 case Toolkit::Slider::Property::SHOW_VALUE:
1379 value = sliderImpl.GetShowValue();
1383 case Toolkit::Slider::Property::MARKS:
1385 Property::Value value1( Property::ARRAY );
1386 Property::Array* markArray = value1.GetArray();
1390 *markArray = sliderImpl.GetMarks();
1397 case Toolkit::Slider::Property::SNAP_TO_MARKS:
1399 value = sliderImpl.GetSnapToMarks();
1403 case Toolkit::Slider::Property::MARK_TOLERANCE:
1405 value = sliderImpl.GetMarkTolerance();
1414 double Slider::AccessibleImpl::GetMinimum()
1416 auto p = Toolkit::Slider::DownCast( self );
1417 return p.GetProperty( Toolkit::Slider::Property::LOWER_BOUND ).Get< float >();
1420 double Slider::AccessibleImpl::GetCurrent()
1422 auto p = Toolkit::Slider::DownCast( self );
1423 return p.GetProperty( Toolkit::Slider::Property::VALUE ).Get< float >();
1426 double Slider::AccessibleImpl::GetMaximum()
1428 auto p = Toolkit::Slider::DownCast( self );
1429 return p.GetProperty( Toolkit::Slider::Property::UPPER_BOUND ).Get< float >();
1432 bool Slider::AccessibleImpl::SetCurrent( double current )
1434 if( current < GetMinimum() || current > GetMaximum() )
1436 auto p = Toolkit::Slider::DownCast( self );
1437 p.SetProperty( Toolkit::Slider::Property::VALUE, static_cast< float >( current ) );
1441 double Slider::AccessibleImpl::GetMinimumIncrement()
1443 auto p = Toolkit::Slider::DownCast( self );
1444 return p.GetProperty( Toolkit::Slider::Property::MARK_TOLERANCE ).Get< float >();
1447 } // namespace Internal
1449 } // namespace Toolkit