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