removing use of using namespace std;
[platform/core/uifw/dali-toolkit.git] / optional / dali-toolkit / internal / controls / slider / slider-impl.cpp
1 /*
2  * Copyright (c) 2014 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/slider/slider-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/events/touch-event.h>
23 #include <dali/public-api/object/type-registry.h>
24
25 // EXTERNAL INCLUDES
26 #include <dali-toolkit/public-api/controls/control-impl.h>
27
28 #include <sstream>
29
30 using namespace Dali;
31
32 namespace Dali
33 {
34
35 namespace Toolkit
36 {
37
38 // Properties
39 const Property::Index Slider::LOWER_BOUND_PROPERTY             = Internal::Slider::SLIDER_PROPERTY_START_INDEX;
40 const Property::Index Slider::UPPER_BOUND_PROPERTY             = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 1;
41
42 const Property::Index Slider::VALUE_PROPERTY                   = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 2;
43 const Property::Index Slider::HIT_REGION_PROPERTY              = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 3;
44 const Property::Index Slider::BACKING_REGION_PROPERTY          = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 4;
45 const Property::Index Slider::HANDLE_REGION_PROPERTY           = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 5;
46
47 const Property::Index Slider::BACKING_IMAGE_NAME_PROPERTY      = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 6;
48 const Property::Index Slider::HANDLE_IMAGE_NAME_PROPERTY       = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 7;
49 const Property::Index Slider::PROGRESS_IMAGE_NAME_PROPERTY     = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 8;
50 const Property::Index Slider::POPUP_IMAGE_NAME_PROPERTY        = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 9;
51 const Property::Index Slider::POPUP_ARROW_IMAGE_NAME_PROPERTY  = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 10;
52
53 const Property::Index Slider::DISABLE_COLOR_PROPERTY           = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 11;
54 const Property::Index Slider::POPUP_TEXT_COLOR_PROPERTY        = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 12;
55
56 const Property::Index Slider::VALUE_PRECISION_PROPERTY         = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 13;
57
58 const Property::Index Slider::SHOW_POPUP_PROPERTY              = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 14;
59 const Property::Index Slider::SHOW_VALUE_PROPERTY              = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 15;
60
61 const Property::Index Slider::ENABLED_PROPERTY                 = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 16;
62
63 const Property::Index Slider::MARKS_PROPERTY                   = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 17;
64 const Property::Index Slider::SNAP_TO_MARKS_PROPERTY           = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 18;
65 const Property::Index Slider::MARK_TOLERANCE_PROPERTY          = Internal::Slider::SLIDER_PROPERTY_START_INDEX + 19;
66
67 namespace Internal
68 {
69
70 namespace
71 {
72 const float BACKING_Z = -0.1f;
73 const float PROGRESS_Z = 0.1f;
74 const float HANDLE_Z = 1.0f;
75 const float VALUE_TEXT_INCREMENT = 0.01f;
76 const float HANDLE_VALUE_DISPLAY_TEXT_Z = HANDLE_Z + VALUE_TEXT_INCREMENT;
77 const float VALUE_DISPLAY_TEXT_Z = VALUE_TEXT_INCREMENT + VALUE_TEXT_INCREMENT;  // Put above HANDLE_VALUE_DISPLAY_TEXT_Z (parented to handle)
78
79 const float MARK_SNAP_TOLERANCE = 0.05f; // 5% of slider width
80
81 const int VALUE_VIEW_SHOW_DURATION = 1000;  // millisec
82 const int VALUE_VIEW_SHOW_DURATION_LONG = 2000;  // millisec
83
84 const float VALUE_VERTICAL_OFFSET = 48.0f;
85
86 const float DEFAULT_WIDTH = 0.0f;
87 const float DEFAULT_HEIGHT = 27.0f;
88 const float DEFAULT_HIT_HEIGHT = 72.0f;
89 const float DEFAULT_HANDLE_HEIGHT = DEFAULT_HIT_HEIGHT;
90
91 const char* SKINNED_BACKING_IMAGE_NAME = DALI_IMAGE_DIR "slider-skin.9.png";
92 const char* SKINNED_HANDLE_IMAGE_NAME = DALI_IMAGE_DIR "slider-skin-handle.png";;
93 const char* SKINNED_PROGRESS_IMAGE_NAME = DALI_IMAGE_DIR "slider-skin-progress.9.png";
94 const char* SKINNED_POPUP_IMAGE_NAME = DALI_IMAGE_DIR "slider-popup.9.png";
95 const char* SKINNED_POPUP_ARROW_IMAGE_NAME = DALI_IMAGE_DIR "slider-popup-arrow.png";
96
97 const Vector2 DEFAULT_HIT_REGION( DEFAULT_WIDTH, DEFAULT_HIT_HEIGHT );
98 const Vector2 DEFAULT_BACKING_REGION( DEFAULT_WIDTH, DEFAULT_HEIGHT );
99 const Vector2 DEFAULT_HANDLE_REGION( DEFAULT_HANDLE_HEIGHT, DEFAULT_HANDLE_HEIGHT );
100
101 const Vector4 DEFAULT_DISABLE_COLOR( 0.5f, 0.5f, 0.5f, 1.0f );
102 const Vector4 DEFAULT_POPUP_TEXT_COLOR( 0.5f, 0.5f, 0.5f, 1.0f );
103
104 const float VALUE_POPUP_MARGIN = 10.0f;
105 const float VALUE_POPUP_HEIGHT = 81.0f;
106 const float VALUE_POPUP_MIN_WIDTH = 54.0f;
107 const Vector2 VALUE_POPUP_ARROW_SIZE( 18.0f, 18.0f );
108
109 const float DEFAULT_LOWER_BOUND = 0.0f;
110 const float DEFAULT_UPPER_BOUND = 1.0f;
111 const float DEFAULT_VALUE = 0.0f;
112 const int DEFAULT_VALUE_PRECISION = 0;
113 const bool DEFAULT_SHOW_POPUP = false;
114 const bool DEFAULT_SHOW_VALUE = true;
115 const bool DEFAULT_ENABLED = true;
116 const bool DEFAULT_SNAP_TO_MARKS = false;
117
118 BaseHandle Create()
119 {
120   return Dali::Toolkit::Slider::New();
121 }
122
123 TypeRegistration typeRegistration( typeid(Dali::Toolkit::Slider), typeid(Dali::Toolkit::Control), Create );
124
125 SignalConnectorType signalConnector1( typeRegistration, Toolkit::Slider::SIGNAL_VALUE_CHANGED, &Toolkit::Internal::Slider::DoConnectSignal );
126 SignalConnectorType signalConnector2( typeRegistration, Toolkit::Slider::SIGNAL_MARK, &Toolkit::Internal::Slider::DoConnectSignal );
127
128 PropertyRegistration property1( typeRegistration, "lower-bound",  Toolkit::Slider::LOWER_BOUND_PROPERTY, Property::FLOAT, &Slider::SetProperty, &Slider::GetProperty );
129 PropertyRegistration property2( typeRegistration, "upper-bound",  Toolkit::Slider::UPPER_BOUND_PROPERTY, Property::FLOAT, &Slider::SetProperty, &Slider::GetProperty );
130 PropertyRegistration property3( typeRegistration, "value",        Toolkit::Slider::VALUE_PROPERTY,       Property::FLOAT, &Slider::SetProperty, &Slider::GetProperty );
131
132 PropertyRegistration property4( typeRegistration, "hit-region",     Toolkit::Slider::HIT_REGION_PROPERTY,      Property::VECTOR2, &Slider::SetProperty, &Slider::GetProperty );
133 PropertyRegistration property5( typeRegistration, "backing-region", Toolkit::Slider::BACKING_REGION_PROPERTY,  Property::VECTOR2, &Slider::SetProperty, &Slider::GetProperty );
134 PropertyRegistration property6( typeRegistration, "handle-region",  Toolkit::Slider::HANDLE_REGION_PROPERTY,   Property::VECTOR2, &Slider::SetProperty, &Slider::GetProperty );
135
136 PropertyRegistration property7( typeRegistration, "backing-image-name",       Toolkit::Slider::BACKING_IMAGE_NAME_PROPERTY,      Property::STRING, &Slider::SetProperty, &Slider::GetProperty );
137 PropertyRegistration property8( typeRegistration, "handle-image-name",        Toolkit::Slider::HANDLE_IMAGE_NAME_PROPERTY,       Property::STRING, &Slider::SetProperty, &Slider::GetProperty );
138 PropertyRegistration property9( typeRegistration, "progress-image-name",      Toolkit::Slider::PROGRESS_IMAGE_NAME_PROPERTY,     Property::STRING, &Slider::SetProperty, &Slider::GetProperty );
139 PropertyRegistration property10( typeRegistration, "popup-image-name",        Toolkit::Slider::POPUP_IMAGE_NAME_PROPERTY,        Property::STRING, &Slider::SetProperty, &Slider::GetProperty );
140 PropertyRegistration property11( typeRegistration, "popup-arrow-image-name",  Toolkit::Slider::POPUP_ARROW_IMAGE_NAME_PROPERTY,  Property::STRING, &Slider::SetProperty, &Slider::GetProperty );
141
142 PropertyRegistration property12( typeRegistration, "disable-color",       Toolkit::Slider::DISABLE_COLOR_PROPERTY,     Property::VECTOR4, &Slider::SetProperty, &Slider::GetProperty );
143 PropertyRegistration property13( typeRegistration, "popup-text-color",    Toolkit::Slider::POPUP_TEXT_COLOR_PROPERTY,  Property::VECTOR4, &Slider::SetProperty, &Slider::GetProperty );
144
145 PropertyRegistration property14( typeRegistration, "value-precision",    Toolkit::Slider::VALUE_PRECISION_PROPERTY,  Property::INTEGER, &Slider::SetProperty, &Slider::GetProperty );
146
147 PropertyRegistration property15( typeRegistration, "show-popup",    Toolkit::Slider::SHOW_POPUP_PROPERTY,  Property::BOOLEAN, &Slider::SetProperty, &Slider::GetProperty );
148 PropertyRegistration property16( typeRegistration, "show-value",    Toolkit::Slider::SHOW_VALUE_PROPERTY,  Property::BOOLEAN, &Slider::SetProperty, &Slider::GetProperty );
149
150 PropertyRegistration property17( typeRegistration, "enabled",       Toolkit::Slider::ENABLED_PROPERTY,  Property::BOOLEAN, &Slider::SetProperty, &Slider::GetProperty );
151
152 PropertyRegistration property18( typeRegistration, "marks",          Toolkit::Slider::MARKS_PROPERTY,          Property::ARRAY,    &Slider::SetProperty, &Slider::GetProperty );
153 PropertyRegistration property19( typeRegistration, "snap-to-marks",  Toolkit::Slider::SNAP_TO_MARKS_PROPERTY,  Property::BOOLEAN,  &Slider::SetProperty, &Slider::GetProperty );
154 PropertyRegistration property20( typeRegistration, "mark-tolerance", Toolkit::Slider::MARK_TOLERANCE_PROPERTY, Property::FLOAT,    &Slider::SetProperty, &Slider::GetProperty );
155
156 } // namespace
157
158 ///////////////////////////////////////////////////////////////////////////////////////////////////
159 // Slider
160 ///////////////////////////////////////////////////////////////////////////////////////////////////
161
162 Dali::Toolkit::Slider Slider::New()
163 {
164   // Create the implementation
165   SliderPtr slider( new Slider() );
166
167   // Pass ownership to CustomActor via derived handle
168   Dali::Toolkit::Slider handle( *slider );
169
170   // Second-phase init of the implementation
171   // This can only be done after the CustomActor connection has been made...
172   slider->Initialize();
173
174   return handle;
175 }
176
177 Slider::Slider()
178 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
179   mState( NORMAL ),
180   mDisableColor( 0.0f, 0.0f, 0.0f, 0.0f ),
181   mPopupTextColor( 0.0f, 0.0f, 0.0f, 0.0f ),
182   mHitRegion( 0.0f, 0.0f ),
183   mBackingRegion( 0.0f, 0.0f ),
184   mHandleRegionSize( 0.0f, 0.0f ),
185   mLowerBound( 0.0f ),
186   mUpperBound( 0.0f ),
187   mValue( 0.0f ),
188   mMarkTolerance( 0.0f ),
189   mValuePrecision( 0 ),
190   mShowPopup( false ),
191   mShowValue( false ),
192   mSnapToMarks( false )
193 {
194 }
195
196 Slider::~Slider()
197 {
198 }
199
200 void Slider::OnInitialize()
201 {
202   // Setup
203   CreateChildren();
204
205   // Properties
206   Actor self = Self();
207
208   SetHitRegion(     DEFAULT_HIT_REGION     );
209   SetBackingRegion( DEFAULT_BACKING_REGION );
210   SetHandleRegion(  DEFAULT_HANDLE_REGION  );
211
212   SetBackingImageName(    SKINNED_BACKING_IMAGE_NAME     );
213   SetHandleImageName(     SKINNED_HANDLE_IMAGE_NAME      );
214   SetProgressImageName(   SKINNED_PROGRESS_IMAGE_NAME    );
215   SetPopupImageName(      SKINNED_POPUP_IMAGE_NAME       );
216   SetPopupArrowImageName( SKINNED_POPUP_ARROW_IMAGE_NAME );
217
218   SetPopupTextColor( DEFAULT_POPUP_TEXT_COLOR );
219
220   SetShowPopup( DEFAULT_SHOW_POPUP );
221   SetShowValue( DEFAULT_SHOW_VALUE );
222
223   SetEnabled( DEFAULT_ENABLED );
224   SetDisableColor( DEFAULT_DISABLE_COLOR );
225
226   SetSnapToMarks( DEFAULT_SNAP_TO_MARKS );
227   SetMarkTolerance( MARK_SNAP_TOLERANCE );
228
229   SetLowerBound( DEFAULT_LOWER_BOUND );
230   SetUpperBound( DEFAULT_UPPER_BOUND );
231   UpdateSkin();
232   SetValuePrecision( DEFAULT_VALUE_PRECISION );
233   mValue = DEFAULT_VALUE;
234   DisplayValue( mValue, false );       // Run this last to display the correct value
235
236   // Size the Slider actor to a default
237   self.SetSize( DEFAULT_HIT_REGION.x, DEFAULT_HIT_REGION.y );
238 }
239
240 void Slider::OnControlSizeSet( const Vector3& size )
241 {
242   // Factor in handle overshoot into size of backing
243   SetHitRegion( Vector2( size.x, GetHitRegion().y ) );
244   SetBackingRegion( Vector2( size.x - GetHandleRegion().x, GetBackingRegion().y ) );
245 }
246
247 bool Slider::OnTouchEvent(Actor actor, const TouchEvent& event)
248 {
249   if( mState != DISABLED )
250   {
251     TouchPoint::State touchState = event.GetPoint(0).state;
252
253     if( touchState == TouchPoint::Down )
254     {
255       mState = PRESSED;
256
257       float percentage = MapPercentage( event.GetPoint(0).local );
258       float value = MapBounds( ( GetSnapToMarks() ) ? SnapToMark( percentage ) : MarkFilter( percentage ), GetLowerBound(), GetUpperBound() );
259       SetValue( value );
260       DisplayPopup( value );
261     }
262     else if( touchState == TouchPoint::Up)
263     {
264       if( mState == PRESSED )
265       {
266         mState = NORMAL;
267         mSlidingFinishedSignal.Emit( Toolkit::Slider::DownCast( Self() ), GetValue() );
268       }
269     }
270   }
271
272   return true;
273 }
274
275 void Slider::OnPan( Actor actor, const PanGesture& gesture )
276 {
277   // gesture.position is in local actor coordinates
278   if( mState != DISABLED )
279   {
280     switch( gesture.state )
281     {
282       case Gesture::Continuing:
283       {
284         if( mState == PRESSED )
285         {
286           float value = MapBounds( MarkFilter ( MapPercentage( gesture.position ) ), GetLowerBound(), GetUpperBound() );
287           SetValue( value );
288           DisplayPopup( value );
289         }
290         break;
291       }
292       case Gesture::Finished:
293       {
294         if( mState == PRESSED  )
295         {
296           if( GetSnapToMarks() )
297           {
298             float value = MapBounds( SnapToMark( MapPercentage( gesture.position ) ), GetLowerBound(), GetUpperBound() );
299             SetValue( value );
300             DisplayPopup( value );
301           }
302           mSlidingFinishedSignal.Emit( Toolkit::Slider::DownCast( Self() ), GetValue() );
303         }
304
305         mState = NORMAL;
306         break;
307       }
308       default:
309       {
310         break;
311       }
312     }
313   }
314 }
315
316 float Slider::HitSpaceToDomain( float x )
317 {
318   float halfRegionWidth = GetHitRegion().x * 0.5f;
319   float halfDomainWidth = ( mDomain.to.x - mDomain.from.x ) * 0.5f;
320   float endDiff = halfRegionWidth - halfDomainWidth;
321
322   return x - endDiff;
323 }
324
325 float Slider::MapPercentage( const Vector2& point )
326 {
327   return Clamp( ( HitSpaceToDomain( point.x ) - mDomain.from.x ) / ( mDomain.to.x - mDomain.from.x ), 0.0f, 1.0f );
328 }
329
330 float Slider::MapValuePercentage( float value )
331 {
332   return ( value - GetLowerBound() ) / ( GetUpperBound() - GetLowerBound() );
333 }
334
335 float Slider::MapBounds( float percent, float lowerBound, float upperBound )
336 {
337   return lowerBound + percent * ( upperBound - lowerBound );
338 }
339
340 Slider::Domain Slider::CalcDomain( const Vector2& currentSize )
341 {
342    return Domain( Vector2( 0.0f, 0.0f ), currentSize );
343 }
344
345 void Slider::DisplayValue( float value, bool raiseSignals )
346 {
347   float clampledValue = Clamp( value, GetLowerBound(), GetUpperBound() );
348
349   float percent = MapValuePercentage( clampledValue );
350
351   float x = mDomain.from.x + percent * ( mDomain.to.x - mDomain.from.x );
352
353   mHandle.SetPosition( x, 0.0f, HANDLE_Z );
354
355   // Progress bar
356   if( mProgress )
357   {
358     if( clampledValue > 0.0f )
359     {
360       mProgress.SetVisible( true ); // Deliberately set this in case multiple SetValues are fired at once
361       mProgress.SetSize( x, GetBackingRegion().y );
362     }
363     else
364     {
365       mProgress.SetVisible( false );
366     }
367   }
368
369   // Signals
370   if( raiseSignals )
371   {
372     Toolkit::Slider self = Toolkit::Slider::DownCast( Self() );
373     mValueChangedSignal.Emit( self, clampledValue );
374
375     int markIndex;
376     if( MarkReached( percent, markIndex ) )
377     {
378       mMarkSignal.Emit( self, markIndex );
379     }
380   }
381
382   if( mHandleValueTextView )
383   {
384     std::stringstream ss;
385     ss.precision( GetValuePrecision() );
386     ss << std::fixed << clampledValue;
387     mHandleValueTextView.SetText( ss.str() );
388   }
389 }
390
391 void Slider::SetMarks( const MarkList& marks )
392 {
393   float value;
394   for( MarkList::const_iterator it = marks.begin(), itEnd = marks.end(); it != itEnd; ++it )
395   {
396     const Property::Value& propertyValue = *it;
397     propertyValue.Get( value );
398
399     mMarks.push_back( value );
400   }
401 }
402
403 const Slider::MarkList& Slider::GetMarks() const
404 {
405   return mMarks;
406 }
407
408 void Slider::SetSnapToMarks( bool snap )
409 {
410   mSnapToMarks = snap;
411 }
412
413 bool Slider::GetSnapToMarks() const
414 {
415   return mSnapToMarks;
416 }
417
418 Actor Slider::CreateHitRegion()
419 {
420   Actor hitRegion = Actor::New();
421   hitRegion.SetParentOrigin( ParentOrigin::CENTER );
422   hitRegion.SetAnchorPoint( AnchorPoint::CENTER );
423   hitRegion.TouchedSignal().Connect( this, &Slider::OnTouchEvent );
424
425   return hitRegion;
426 }
427
428 ImageActor Slider::CreateBacking()
429 {
430   ImageActor backing = ImageActor::New();
431   backing.SetParentOrigin( ParentOrigin::CENTER );
432   backing.SetAnchorPoint( AnchorPoint::CENTER );
433   backing.SetZ( BACKING_Z );
434
435   return backing;
436 }
437
438 void Slider::SetBackingImageName( const std::string& imageName )
439 {
440   if( mBacking && imageName != String::EMPTY )
441   {
442     Image image = Image::New( imageName );
443     mBacking.SetImage( image );
444   }
445 }
446
447 std::string Slider::GetBackingImageName()
448 {
449   if( mBacking )
450   {
451     return mBacking.GetImage().GetFilename();
452   }
453
454   return std::string( "" );
455 }
456
457 ImageActor Slider::CreateProgress()
458 {
459   ImageActor progress = ImageActor::New();
460   progress.SetParentOrigin( ParentOrigin::CENTER_LEFT );
461   progress.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
462   progress.SetZ( PROGRESS_Z );
463
464   return progress;
465 }
466
467 void Slider::SetProgressImageName( const std::string& imageName )
468 {
469   if( mProgress && imageName != String::EMPTY )
470   {
471     Image image = Image::New( imageName );
472     mProgress.SetImage( image );
473   }
474 }
475
476 std::string Slider::GetProgressImageName()
477 {
478   if( mProgress )
479   {
480     return mProgress.GetImage().GetFilename();
481   }
482
483   return std::string( "" );
484 }
485
486 void Slider::SetPopupImageName( const std::string& imageName )
487 {
488   mPopupImageName = imageName;
489 }
490
491 std::string Slider::GetPopupImageName()
492 {
493   return mPopupImageName;
494 }
495
496 void Slider::CreatePopupImage( const std::string& imageName )
497 {
498   if( mPopup && imageName != String::EMPTY )
499   {
500     Image image = Image::New( imageName );
501     mPopup.SetImage( image );
502   }
503 }
504
505 void Slider::SetPopupArrowImageName( const std::string& imageName )
506 {
507   mPopupArrowImageName = imageName;
508 }
509
510 std::string Slider::GetPopupArrowImageName()
511 {
512   return mPopupArrowImageName;
513 }
514
515 void Slider::CreatePopupArrowImage( const std::string& imageName )
516 {
517   if( mPopupArrow && imageName != String::EMPTY )
518   {
519     Image image = Image::New( imageName );
520     mPopupArrow.SetImage( image );
521   }
522 }
523
524 void Slider::ResizeProgressRegion( const Vector2& region )
525 {
526   if( mProgress )
527   {
528     mProgress.SetSize( region );
529   }
530 }
531
532 ImageActor Slider::CreateHandle()
533 {
534   ImageActor handle = ImageActor::New();
535   handle.SetParentOrigin( ParentOrigin::CENTER_LEFT );
536   handle.SetAnchorPoint( AnchorPoint::CENTER );
537   handle.SetZ( HANDLE_Z );
538
539   return handle;
540 }
541
542 ImageActor Slider::CreatePopupArrow()
543 {
544   ImageActor arrow = ImageActor::New();
545   arrow.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
546   arrow.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
547   arrow.SetZ( HANDLE_Z );
548
549   return arrow;
550 }
551
552 Toolkit::TextView Slider::CreatePopupText()
553 {
554   Toolkit::TextView textView = Toolkit::TextView::New();
555   textView.SetParentOrigin( ParentOrigin::CENTER );
556   textView.SetAnchorPoint( AnchorPoint::CENTER );
557   textView.SetSizePolicy( Toolkit::Control::Flexible, Toolkit::Control::Flexible );
558   textView.SetZ( VALUE_DISPLAY_TEXT_Z );
559   return textView;
560 }
561
562 ImageActor Slider::CreatePopup()
563 {
564   ImageActor popup = ImageActor::New();
565   popup.SetParentOrigin( ParentOrigin::TOP_CENTER );
566   popup.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
567
568   mValueTextView = CreatePopupText();
569   popup.Add( mValueTextView );
570
571   return popup;
572 }
573
574 void Slider::SetHandleImageName( const std::string& imageName )
575 {
576   if( mHandle && imageName != String::EMPTY )
577   {
578     Image image = Image::New( imageName );
579     mHandle.SetImage( image );
580   }
581 }
582
583 std::string Slider::GetHandleImageName()
584 {
585   if( mHandle )
586   {
587     return mHandle.GetImage().GetFilename();
588   }
589
590   return std::string( "" );
591 }
592
593 void Slider::ResizeHandleRegion( const Vector2& region )
594 {
595   if( mHandle )
596   {
597     mHandle.SetSize( region );
598   }
599 }
600
601 void Slider::CreateHandleValueDisplay()
602 {
603   if( mHandle && !mHandleValueTextView )
604   {
605     mHandleValueTextView = Toolkit::TextView::New();
606     mHandleValueTextView.SetParentOrigin( ParentOrigin::CENTER );
607     mHandleValueTextView.SetAnchorPoint( AnchorPoint::CENTER );
608     mHandleValueTextView.SetSize( GetHandleRegion() );
609     mHandleValueTextView.SetZ( HANDLE_VALUE_DISPLAY_TEXT_Z );
610     mHandle.Add( mHandleValueTextView );
611   }
612 }
613
614 void Slider::DestroyHandleValueDisplay()
615 {
616   if(mHandleValueTextView)
617   {
618     mHandleValueTextView.Unparent();
619     mHandleValueTextView.Reset();
620   }
621 }
622
623 void Slider::SetPopupTextColor( const Vector4& color )
624 {
625   mPopupTextColor = color;
626 }
627
628 Actor Slider::CreateValueDisplay()
629 {
630   Actor popup = Actor::New();
631   popup.SetParentOrigin( ParentOrigin::TOP_CENTER );
632   popup.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
633
634   mPopupArrow = CreatePopupArrow();
635   popup.Add( mPopupArrow );
636
637   mPopup = CreatePopup();
638   mPopup.SetSize( 0.0f, VALUE_POPUP_HEIGHT );
639   mPopupArrow.Add( mPopup );
640
641   return popup;
642 }
643
644 Toolkit::Slider::ValueChangedSignalType& Slider::ValueChangedSignal()
645 {
646   return mValueChangedSignal;
647 }
648
649 Toolkit::Slider::ValueChangedSignalType& Slider::SlidingFinishedSignal()
650 {
651   return mSlidingFinishedSignal;
652 }
653
654 Toolkit::Slider::MarkSignalType& Slider::MarkSignal()
655 {
656   return mMarkSignal;
657 }
658
659 void Slider::UpdateSkin()
660 {
661   switch( mState )
662   {
663     case NORMAL:
664     {
665       mBacking.SetColor( Color::WHITE );
666       mHandle.SetColor( Color::WHITE );
667       mProgress.SetColor( Color::WHITE );
668       break;
669     }
670     case DISABLED:
671     {
672       Vector4 disableColor = GetDisableColor();
673       mBacking.SetColor( disableColor );
674       mHandle.SetColor( disableColor );
675       mProgress.SetColor( disableColor );
676       break;
677     }
678     case PRESSED:
679     {
680       break;
681     }
682     case FOCUSED:
683     {
684       break;
685     }
686   }
687 }
688
689 void Slider::CreateChildren()
690 {
691   Actor self = Self();
692
693   // Hit region
694   mHitArea = CreateHitRegion();
695   mPanDetector = PanGestureDetector::New();
696   mPanDetector.Attach( mHitArea );
697   mPanDetector.DetectedSignal().Connect( this, &Slider::OnPan );
698   self.Add( mHitArea );
699
700   // Background
701   mBacking = CreateBacking();
702   self.Add( mBacking );
703
704   // Progress bar
705   mProgress = CreateProgress();
706   mBacking.Add( mProgress );
707
708   // Handle
709   mHandle = CreateHandle();
710   mBacking.Add( mHandle );
711 }
712
713 void Slider::SetHitRegion( const Vector2& size )
714 {
715   mHitRegion = size;
716
717   if( mHitArea )
718   {
719     mHitArea.SetSize( mHitRegion );
720   }
721 }
722
723 const Vector2& Slider::GetHitRegion() const
724 {
725   return mHitRegion;
726 }
727
728 void Slider::AddPopup()
729 {
730   if( !mValueDisplay )
731   {
732     mValueDisplay = CreateValueDisplay();
733     mValueDisplay.SetVisible( false );
734     mHandle.Add( mValueDisplay );
735
736     CreatePopupImage( GetPopupImageName() );
737     CreatePopupArrowImage( GetPopupArrowImageName() );
738
739     mValueTimer = Timer::New( VALUE_VIEW_SHOW_DURATION );
740     mValueTimer.TickSignal().Connect( this, &Slider::HideValueView );
741   }
742 }
743
744 void Slider::RemovePopup()
745 {
746   if( mValueDisplay )
747   {
748     mPopup.Unparent();
749     mPopup.Reset();
750
751     mPopupArrow.Unparent();
752     mPopupArrow.Reset();
753
754     mValueDisplay.Unparent();
755     mValueDisplay.Reset();
756
757     mValueTimer.TickSignal().Disconnect( this, &Slider::HideValueView );
758     mValueTimer.Reset();
759   }
760 }
761
762
763 float Slider::MarkFilter( float value )
764 {
765   const float MARK_TOLERANCE = GetMarkTolerance();
766
767   float mark;
768   for( MarkList::iterator it = mMarks.begin(), itEnd = mMarks.end(); it != itEnd; ++it )
769   {
770     const Property::Value& propertyValue = *it;
771     propertyValue.Get( mark );
772     mark = MapValuePercentage( mark );
773
774     // If close to a mark, return the mark
775     if( fabsf( mark - value ) < MARK_TOLERANCE )
776     {
777       return mark;
778     }
779   }
780
781   return value;
782 }
783
784 float Slider::SnapToMark( float value )
785 {
786   float closestMark = value;
787   float closestDist = std::numeric_limits<float>::max();
788
789   float mark;
790   for( MarkList::iterator it = mMarks.begin(), itEnd = mMarks.end(); it != itEnd; ++it )
791   {
792     const Property::Value& propertyValue = *it;
793     propertyValue.Get( mark );
794     mark = MapValuePercentage( mark );
795
796     float dist = fabsf( mark - value );
797     if( dist < closestDist )
798     {
799       closestDist = dist;
800       closestMark = mark;
801     }
802   }
803
804   return closestMark;
805 }
806
807 bool Slider::MarkReached( float value, int& outIndex )
808 {
809   const float MARK_TOLERANCE = GetMarkTolerance();
810
811   // Binary search
812   int head = 0,
813       tail = mMarks.size() - 1;
814   int current;
815   float mark;
816
817   while( head <= tail )
818   {
819     current = head + ( tail - head ) / 2;
820
821     const Property::Value& propertyValue = mMarks[ current ];
822     propertyValue.Get( mark );
823     mark = MapValuePercentage( mark );
824
825     if( fabsf( mark - value ) < MARK_TOLERANCE )
826     {
827       outIndex = current;
828       return true;
829     }
830     else
831     {
832       if( value < mark )
833       {
834         tail = current - 1;
835       }
836       else
837       {
838         head = current + 1;
839       }
840     }
841   }
842
843   return false;
844 }
845
846 bool Slider::HideValueView()
847 {
848   if( mValueDisplay )
849   {
850     mValueDisplay.SetVisible( false );
851   }
852
853   return false;
854 }
855
856 void Slider::SetLowerBound( float bound )
857 {
858   mLowerBound = bound;
859   DisplayValue( GetValue(), false );
860 }
861
862 float Slider::GetLowerBound() const
863 {
864   return mLowerBound;
865 }
866
867 void Slider::SetUpperBound( float bound )
868 {
869   mUpperBound = bound;
870   DisplayValue( GetValue(), false );
871 }
872
873 float Slider::GetUpperBound() const
874 {
875   return mUpperBound;
876 }
877
878 void Slider::SetValue( float value )
879 {
880   mValue = value;
881   DisplayValue( mValue, true );
882 }
883
884 float Slider::GetValue() const
885 {
886   return mValue;
887 }
888
889 void Slider::SetBackingRegion( const Vector2& region )
890 {
891   mBackingRegion = region;
892
893   if( mBacking )
894   {
895     mBacking.SetSize( mBackingRegion );
896   }
897
898   ResizeProgressRegion( Vector2( 0.0f, mBackingRegion.y ) );
899
900   mDomain = CalcDomain( mBackingRegion );
901
902   DisplayValue( GetValue(), false );  // Set the progress bar to correct width
903 }
904
905 const Vector2& Slider::GetBackingRegion() const
906 {
907   return mBackingRegion;
908 }
909
910 void Slider::SetHandleRegion( const Vector2& region )
911 {
912   mHandleRegionSize = region;
913
914   ResizeHandleRegion( mHandleRegionSize );
915
916   Vector2 hitRegion = GetHitRegion();
917   hitRegion.x += mHandleRegionSize.x;
918   SetHitRegion( hitRegion );
919 }
920
921 const Vector2& Slider::GetHandleRegion() const
922 {
923   return mHandleRegionSize;
924 }
925
926 void Slider::SetDisableColor( const Vector4& color )
927 {
928   mDisableColor = color;
929
930   UpdateSkin();
931 }
932
933 Vector4 Slider::GetDisableColor() const
934 {
935   return mDisableColor;
936 }
937
938 Vector4 Slider::GetPopupTextColor() const
939 {
940   return mPopupTextColor;
941 }
942
943 void Slider::SetValuePrecision( int precision )
944 {
945   mValuePrecision = precision;
946 }
947
948 int Slider::GetValuePrecision() const
949 {
950   return mValuePrecision;
951 }
952
953 void Slider::SetShowPopup( bool showPopup )
954 {
955   mShowPopup = showPopup;
956
957   // Value display
958   if( mShowPopup )
959   {
960     AddPopup();
961   }
962   else
963   {
964     RemovePopup();
965   }
966 }
967
968 bool Slider::GetShowPopup() const
969 {
970   return mShowPopup;
971 }
972
973 void Slider::SetShowValue( bool showValue )
974 {
975   mShowValue = showValue;
976
977   if( mShowValue )
978   {
979     CreateHandleValueDisplay();
980   }
981   else
982   {
983     DestroyHandleValueDisplay();
984   }
985 }
986
987 bool Slider::GetShowValue() const
988 {
989   return mShowValue;
990 }
991
992 void Slider::SetEnabled( bool enabled )
993 {
994   if( enabled )
995   {
996     mState = NORMAL;
997   }
998   else
999   {
1000     mState = DISABLED;
1001   }
1002
1003   UpdateSkin();
1004 }
1005
1006 bool Slider::IsEnabled() const
1007 {
1008   return mState != DISABLED;
1009 }
1010
1011 void Slider::SetMarkTolerance( float tolerance )
1012 {
1013   mMarkTolerance = tolerance;
1014 }
1015
1016 float Slider::GetMarkTolerance() const
1017 {
1018   return mMarkTolerance;
1019 }
1020
1021 // static class method to support script connecting signals
1022
1023 bool Slider::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1024 {
1025   Dali::BaseHandle handle( object );
1026
1027   bool connected = true;
1028   Toolkit::Slider slider = Toolkit::Slider::DownCast( handle );
1029
1030   if( signalName == Dali::Toolkit::Slider::SIGNAL_VALUE_CHANGED )
1031   {
1032     slider.ValueChangedSignal().Connect( tracker, functor );
1033   }
1034   else if( signalName == Dali::Toolkit::Slider::SIGNAL_MARK )
1035   {
1036     slider.MarkSignal().Connect( tracker, functor );
1037   }
1038   else
1039   {
1040     // signalName does not match any signal
1041     connected = false;
1042   }
1043
1044   return connected;
1045 }
1046
1047 void Slider::DisplayPopup( float value )
1048 {
1049   // Value displayDoConnectSignal
1050   if( mValueTextView )
1051   {
1052     std::stringstream ss;
1053     ss.precision( GetValuePrecision() );
1054     ss << std::fixed << value;
1055     mValueTextView.SetText( ss.str() );
1056     TextStyle style;
1057     style.SetTextColor( GetPopupTextColor() );
1058     mValueTextView.SetStyleToCurrentText( style, TextStyle::COLOR);
1059
1060     if( mValueDisplay )
1061     {
1062       Font font = Font::New();
1063       float popupWidth = font.MeasureText( ss.str() ).x + VALUE_POPUP_MARGIN * 2.0f;
1064       if( popupWidth < VALUE_POPUP_MIN_WIDTH )
1065       {
1066         popupWidth = VALUE_POPUP_MIN_WIDTH;
1067       }
1068
1069       mPopup.SetSize( popupWidth, VALUE_POPUP_HEIGHT );
1070       mValueDisplay.SetVisible( true );
1071
1072       mValueTimer.SetInterval( VALUE_VIEW_SHOW_DURATION );
1073     }
1074   }
1075 }
1076
1077 void Slider::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
1078 {
1079   Toolkit::Slider slider = Toolkit::Slider::DownCast( Dali::BaseHandle( object ) );
1080
1081   if ( slider )
1082   {
1083     Slider& sliderImpl( GetImpl( slider ) );
1084
1085     switch ( propertyIndex )
1086     {
1087       case Toolkit::Slider::LOWER_BOUND_PROPERTY:
1088       {
1089         sliderImpl.SetLowerBound( value.Get< float >() );
1090         break;
1091       }
1092
1093       case Toolkit::Slider::UPPER_BOUND_PROPERTY:
1094       {
1095         sliderImpl.SetUpperBound( value.Get< float >() );
1096         break;
1097       }
1098
1099       case Toolkit::Slider::VALUE_PROPERTY:
1100       {
1101         sliderImpl.SetValue( value.Get< float >() );
1102         break;
1103       }
1104
1105       case Toolkit::Slider::HIT_REGION_PROPERTY:
1106       {
1107         sliderImpl.SetHitRegion( value.Get< Vector2 >() );
1108         break;
1109       }
1110
1111       case Toolkit::Slider::BACKING_REGION_PROPERTY:
1112       {
1113         sliderImpl.SetBackingRegion( value.Get< Vector2 >() );
1114         break;
1115       }
1116
1117       case Toolkit::Slider::HANDLE_REGION_PROPERTY:
1118       {
1119         sliderImpl.SetHandleRegion( value.Get< Vector2 >() );
1120         break;
1121       }
1122
1123       case Toolkit::Slider::BACKING_IMAGE_NAME_PROPERTY:
1124       {
1125         sliderImpl.SetBackingImageName( value.Get< std::string >() );
1126         break;
1127       }
1128
1129       case Toolkit::Slider::HANDLE_IMAGE_NAME_PROPERTY:
1130       {
1131         sliderImpl.SetHandleImageName( value.Get< std::string >() );
1132         break;
1133       }
1134
1135       case Toolkit::Slider::PROGRESS_IMAGE_NAME_PROPERTY:
1136       {
1137         sliderImpl.SetProgressImageName( value.Get< std::string >() );
1138         break;
1139       }
1140
1141       case Toolkit::Slider::POPUP_IMAGE_NAME_PROPERTY:
1142       {
1143         sliderImpl.SetPopupImageName( value.Get< std::string >() );
1144         break;
1145       }
1146
1147       case Toolkit::Slider::POPUP_ARROW_IMAGE_NAME_PROPERTY:
1148       {
1149         sliderImpl.SetPopupArrowImageName( value.Get< std::string >() );
1150         break;
1151       }
1152
1153       case Toolkit::Slider::DISABLE_COLOR_PROPERTY:
1154       {
1155         sliderImpl.SetDisableColor( value.Get< Vector4 >() );
1156         break;
1157       }
1158
1159       case Toolkit::Slider::POPUP_TEXT_COLOR_PROPERTY:
1160       {
1161         sliderImpl.SetPopupTextColor( value.Get< Vector4 >() );
1162         break;
1163       }
1164
1165       case Toolkit::Slider::VALUE_PRECISION_PROPERTY:
1166       {
1167         sliderImpl.SetValuePrecision( value.Get< int >() );
1168         break;
1169       }
1170
1171       case Toolkit::Slider::SHOW_POPUP_PROPERTY:
1172       {
1173         sliderImpl.SetShowPopup( value.Get< bool >() );
1174         break;
1175       }
1176
1177       case Toolkit::Slider::SHOW_VALUE_PROPERTY:
1178       {
1179         sliderImpl.SetShowValue( value.Get< bool >() );
1180         break;
1181       }
1182
1183       case Toolkit::Slider::ENABLED_PROPERTY:
1184       {
1185         sliderImpl.SetEnabled( value.Get< bool >() );
1186         break;
1187       }
1188
1189       case Toolkit::Slider::MARKS_PROPERTY:
1190       {
1191         sliderImpl.SetMarks( value.Get< Property::Array >() );
1192         break;
1193       }
1194
1195       case Toolkit::Slider::SNAP_TO_MARKS_PROPERTY:
1196       {
1197         sliderImpl.SetSnapToMarks( value.Get< bool >() );
1198         break;
1199       }
1200
1201       case Toolkit::Slider::MARK_TOLERANCE_PROPERTY:
1202       {
1203         sliderImpl.SetMarkTolerance( value.Get< float >() );
1204         break;
1205       }
1206     }
1207   }
1208 }
1209
1210 Property::Value Slider::GetProperty( BaseObject* object, Property::Index propertyIndex )
1211 {
1212   Property::Value value;
1213
1214   Toolkit::Slider slider = Toolkit::Slider::DownCast( Dali::BaseHandle( object ) );
1215
1216   if ( slider )
1217   {
1218     Slider& sliderImpl( GetImpl( slider ) );
1219
1220     switch ( propertyIndex )
1221     {
1222       case Toolkit::Slider::LOWER_BOUND_PROPERTY:
1223       {
1224         value = sliderImpl.GetLowerBound();
1225         break;
1226       }
1227
1228       case Toolkit::Slider::UPPER_BOUND_PROPERTY:
1229       {
1230         value = sliderImpl.GetUpperBound();
1231         break;
1232       }
1233
1234       case Toolkit::Slider::VALUE_PROPERTY:
1235       {
1236         value = sliderImpl.GetValue();
1237         break;
1238       }
1239
1240       case Toolkit::Slider::HIT_REGION_PROPERTY:
1241       {
1242         value = sliderImpl.GetHitRegion();
1243         break;
1244       }
1245
1246       case Toolkit::Slider::BACKING_REGION_PROPERTY:
1247       {
1248         value = sliderImpl.GetBackingRegion();
1249         break;
1250       }
1251
1252       case Toolkit::Slider::HANDLE_REGION_PROPERTY:
1253       {
1254         value = sliderImpl.GetHandleRegion();
1255         break;
1256       }
1257
1258       case Toolkit::Slider::BACKING_IMAGE_NAME_PROPERTY:
1259       {
1260         value = sliderImpl.GetBackingImageName();
1261         break;
1262       }
1263
1264       case Toolkit::Slider::HANDLE_IMAGE_NAME_PROPERTY:
1265       {
1266         value = sliderImpl.GetHandleImageName();
1267         break;
1268       }
1269
1270       case Toolkit::Slider::PROGRESS_IMAGE_NAME_PROPERTY:
1271       {
1272         value = sliderImpl.GetProgressImageName();
1273         break;
1274       }
1275
1276       case Toolkit::Slider::POPUP_IMAGE_NAME_PROPERTY:
1277       {
1278         value = sliderImpl.GetPopupImageName();
1279         break;
1280       }
1281
1282       case Toolkit::Slider::POPUP_ARROW_IMAGE_NAME_PROPERTY:
1283       {
1284         value = sliderImpl.GetPopupArrowImageName();
1285         break;
1286       }
1287
1288       case Toolkit::Slider::DISABLE_COLOR_PROPERTY:
1289       {
1290         value = sliderImpl.GetDisableColor();
1291         break;
1292       }
1293
1294       case Toolkit::Slider::POPUP_TEXT_COLOR_PROPERTY:
1295       {
1296         value = sliderImpl.GetPopupTextColor();
1297         break;
1298       }
1299
1300       case Toolkit::Slider::VALUE_PRECISION_PROPERTY:
1301       {
1302         value = sliderImpl.GetValuePrecision();
1303         break;
1304       }
1305
1306       case Toolkit::Slider::SHOW_POPUP_PROPERTY:
1307       {
1308         value = sliderImpl.GetShowPopup();
1309         break;
1310       }
1311
1312       case Toolkit::Slider::SHOW_VALUE_PROPERTY:
1313       {
1314         value = sliderImpl.GetShowValue();
1315         break;
1316       }
1317
1318       case Toolkit::Slider::ENABLED_PROPERTY:
1319       {
1320         value = sliderImpl.IsEnabled();
1321         break;
1322       }
1323
1324       case Toolkit::Slider::MARKS_PROPERTY:
1325       {
1326         // TODO: Need to be able to return a PropertyArray
1327         // value = sliderImpl.GetMarks();
1328         break;
1329       }
1330
1331       case Toolkit::Slider::SNAP_TO_MARKS_PROPERTY:
1332       {
1333         value = sliderImpl.GetSnapToMarks();
1334         break;
1335       }
1336
1337       case Toolkit::Slider::MARK_TOLERANCE_PROPERTY:
1338       {
1339         value = sliderImpl.GetMarkTolerance();
1340         break;
1341       }
1342     }
1343   }
1344
1345   return value;
1346 }
1347
1348 } // namespace Internal
1349
1350 } // namespace Toolkit
1351
1352 } // namespace Dali