d1f30bcc5411f12666a0e0981aa6db1aad3d9139
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / buttons / button-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 "button-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23 #include <dali/public-api/events/touch-event.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/public-api/object/type-registry-helper.h>
26 #include <dali/public-api/actors/image-actor.h>
27 #include <dali/public-api/scripting/scripting.h>
28
29 // INTERNAL INCLUDES
30 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
31
32 /**
33  * Button states and contents
34  *                                         (3) mSelectedContent
35  *  (2) mButtonContent                     (2) mSelectedBackgroundContent
36  *  (1) mBackgroundContent                 (1) mBackgroundContent
37  * < unselected > ----------------------- < selected >
38  *       |                OnSelect()            |
39  *       | OnDisabled()                         | OnDisabled()
40  *       |                                      |
41  * < disabled >                           < disabled-selected >
42  *  (2) mDisabledContent                   (2) mDisabledSelectedContent
43  *  (1) mDisabledBackgroundContent         (1) mDisabledBackgroundContent
44  *
45  * The drawing order of child actors is as follows.
46  *
47  *  Top      mLabel
48  *   |       mButtonContent / mSelectedContent / mDisabledContent / mDisabledSelectedContent
49  *   |       mSelectedBackgroundContent
50  * Bottom    mBackgroundContent / mDisabledBackgroundContent
51  *
52  * Some of contents may be missed.
53  * And 2 images - fade-in image and fade-out image - in the same layer can be shown during the transition animation. Fade-in image should be above fade-out image.
54  */
55
56 namespace Dali
57 {
58
59 namespace Toolkit
60 {
61
62 namespace Internal
63 {
64
65 namespace
66 {
67
68 BaseHandle Create()
69 {
70   // empty handle as we cannot create button (but type registered for clicked signal)
71   return BaseHandle();
72 }
73
74 // Setup properties, signals and actions using the type-registry.
75 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Button, Toolkit::Control, Create );
76
77 DALI_PROPERTY_REGISTRATION( Button, "disabled",                     BOOLEAN, DISABLED                     )
78 DALI_PROPERTY_REGISTRATION( Button, "auto-repeating",               BOOLEAN, AUTO_REPEATING               )
79 DALI_PROPERTY_REGISTRATION( Button, "initial-auto-repeating-delay", FLOAT,   INITIAL_AUTO_REPEATING_DELAY )
80 DALI_PROPERTY_REGISTRATION( Button, "next-auto-repeating-delay",    FLOAT,   NEXT_AUTO_REPEATING_DELAY    )
81 DALI_PROPERTY_REGISTRATION( Button, "togglable",                    BOOLEAN, TOGGLABLE                    )
82 DALI_PROPERTY_REGISTRATION( Button, "selected",                     BOOLEAN, SELECTED                     )
83 DALI_PROPERTY_REGISTRATION( Button, "normal-state-actor",           MAP,     NORMAL_STATE_ACTOR           )
84 DALI_PROPERTY_REGISTRATION( Button, "selected-state-actor",         MAP,     SELECTED_STATE_ACTOR         )
85 DALI_PROPERTY_REGISTRATION( Button, "disabled-state-actor",         MAP,     DISABLED_STATE_ACTOR         )
86 DALI_PROPERTY_REGISTRATION( Button, "label-actor",                  MAP,     LABEL_ACTOR                  )
87
88 DALI_SIGNAL_REGISTRATION(   Button, "pressed",                               SIGNAL_PRESSED               )
89 DALI_SIGNAL_REGISTRATION(   Button, "released",                              SIGNAL_RELEASED              )
90 DALI_SIGNAL_REGISTRATION(   Button, "clicked",                               SIGNAL_CLICKED               )
91 DALI_SIGNAL_REGISTRATION(   Button, "state-changed",                         SIGNAL_STATE_CHANGED         )
92
93 DALI_ACTION_REGISTRATION(   Button, "button-click",                          ACTION_BUTTON_CLICK          )
94
95 DALI_TYPE_REGISTRATION_END()
96
97 const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f );
98 const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f );
99
100 } // unnamed namespace
101
102 Button::Button()
103 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
104   mAutoRepeatingTimer(),
105   mDisabled( false ),
106   mAutoRepeating( false ),
107   mTogglableButton( false ),
108   mSelected( false ),
109   mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ),
110   mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ),
111   mAnimationTime( 0.0f ),
112   mClickActionPerforming( false ),
113   mState( ButtonUp ),
114   mPaintState( UnselectedState )
115 {
116 }
117
118 Button::~Button()
119 {
120   if( mAutoRepeatingTimer )
121   {
122     mAutoRepeatingTimer.Reset();
123   }
124 }
125
126 void Button::SetDisabled( bool disabled )
127 {
128   if( disabled != mDisabled )
129   {
130     unsigned int backgroundIndex;
131     unsigned int buttonIndex;
132
133     bool animationStarted = false;
134
135     mDisabled = disabled;
136
137     switch( mPaintState )
138     {
139       case UnselectedState:
140       {
141         buttonIndex = FindChildIndex( mLabel );
142         InsertChild( buttonIndex, mDisabledContent );
143
144         if( mBackgroundContent )
145         {
146           backgroundIndex = 1;
147         }
148         else
149         {
150           backgroundIndex = 0;
151         }
152
153         InsertChild( backgroundIndex, mDisabledBackgroundContent );
154
155         animationStarted = OnDisabled();
156
157         if( animationStarted )
158         {
159           mPaintState = UnselectedDisabledTransition;
160         }
161         else
162         {
163           mPaintState = DisabledUnselectedState;
164         }
165         break;
166       }
167       case SelectedState:
168       {
169         buttonIndex = FindChildIndex( mLabel );
170         InsertChild( buttonIndex, mDisabledSelectedContent );
171
172         if( mBackgroundContent )
173         {
174           backgroundIndex = 1;
175         }
176         else
177         {
178           backgroundIndex = 0;
179         }
180
181         InsertChild( backgroundIndex, mDisabledBackgroundContent );
182
183         animationStarted = OnDisabled();
184
185         if( animationStarted )
186         {
187           mPaintState = SelectedDisabledTransition;
188         }
189         else
190         {
191           mPaintState = DisabledSelectedState;
192         }
193         break;
194       }
195       case DisabledUnselectedState:
196       {
197         buttonIndex = FindChildIndex( mLabel );
198         InsertChild( buttonIndex, mButtonContent );
199
200         if( mDisabledBackgroundContent )
201         {
202           backgroundIndex = 1;
203         }
204         else
205         {
206           backgroundIndex = 0;
207         }
208
209         InsertChild( backgroundIndex, mBackgroundContent );
210
211         animationStarted = OnDisabled();
212
213         if( animationStarted )
214         {
215           mPaintState = DisabledUnselectedTransition;
216         }
217         else
218         {
219           mPaintState = UnselectedState;
220         }
221         break;
222       }
223       case DisabledSelectedState:
224       {
225         buttonIndex = FindChildIndex( mLabel );
226         InsertChild( buttonIndex, mSelectedContent );
227
228         if( mDisabledBackgroundContent )
229         {
230           backgroundIndex = 1;
231         }
232         else
233         {
234           backgroundIndex = 0;
235         }
236
237         InsertChild( backgroundIndex, mSelectedBackgroundContent );
238         InsertChild( backgroundIndex, mBackgroundContent );
239
240         animationStarted = OnDisabled();
241
242         if( animationStarted )
243         {
244           mPaintState = DisabledSelectedTransition;
245         }
246         else
247         {
248           mPaintState = SelectedState;
249         }
250         break;
251       }
252       case UnselectedSelectedTransition:
253       {
254         buttonIndex = FindChildIndex( mLabel );
255         InsertChild( buttonIndex, mDisabledSelectedContent );
256
257         if( mBackgroundContent )
258         {
259           backgroundIndex = 1;
260         }
261         else
262         {
263           backgroundIndex = 0;
264         }
265
266         InsertChild( backgroundIndex, mDisabledBackgroundContent );
267
268         animationStarted = OnDisabled();
269
270         if( animationStarted )
271         {
272           mPaintState = SelectedDisabledTransition;
273         }
274         else
275         {
276           mPaintState = DisabledSelectedState;
277         }
278         break;
279       }
280       case SelectedUnselectedTransition:
281       {
282         buttonIndex = FindChildIndex( mLabel );
283         InsertChild( buttonIndex, mDisabledContent );
284
285         if( mBackgroundContent )
286         {
287           backgroundIndex = 1;
288         }
289         else
290         {
291           backgroundIndex = 0;
292         }
293
294         InsertChild( backgroundIndex, mDisabledBackgroundContent );
295
296         animationStarted = OnDisabled();
297
298         if( animationStarted )
299         {
300           mPaintState = UnselectedDisabledTransition;
301         }
302         else
303         {
304           mPaintState = DisabledUnselectedState;
305         }
306         break;
307       }
308       case UnselectedDisabledTransition:
309       {
310         animationStarted = OnDisabled();
311
312         if( animationStarted )
313         {
314           mPaintState = DisabledUnselectedTransition;
315         }
316         else
317         {
318           mPaintState = UnselectedState;
319         }
320         break;
321       }
322       case DisabledUnselectedTransition:
323       {
324         animationStarted = OnDisabled();
325
326         if( animationStarted )
327         {
328           mPaintState = UnselectedDisabledTransition;
329         }
330         else
331         {
332           mPaintState = DisabledUnselectedState;
333         }
334         break;
335       }
336       case SelectedDisabledTransition:
337       {
338         animationStarted = OnDisabled();
339
340         if( animationStarted )
341         {
342           mPaintState = DisabledSelectedTransition;
343         }
344         else
345         {
346           mPaintState = SelectedState;
347         }
348         break;
349       }
350       case DisabledSelectedTransition:
351       {
352         animationStarted = OnDisabled();
353
354         if( animationStarted )
355         {
356           mPaintState = SelectedDisabledTransition;
357         }
358         else
359         {
360           mPaintState = DisabledSelectedState;
361         }
362         break;
363       }
364     }
365   }
366 }
367
368 bool Button::IsDisabled() const
369 {
370   return mDisabled;
371 }
372
373 void Button::SetAutoRepeating( bool autoRepeating )
374 {
375   mAutoRepeating = autoRepeating;
376
377   // An autorepeating button can't be a togglable button.
378   if( autoRepeating )
379   {
380     mTogglableButton = false;
381
382     if( mSelected )
383     {
384       // Emit a signal is not wanted, only change the appearance.
385       SetSelected( false, false );
386     }
387   }
388 }
389
390 bool Button::IsAutoRepeating() const
391 {
392   return mAutoRepeating;
393 }
394
395 void Button::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
396 {
397   DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
398   mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
399 }
400
401 float Button::GetInitialAutoRepeatingDelay() const
402 {
403   return mInitialAutoRepeatingDelay;
404 }
405
406 void Button::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
407 {
408   DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
409   mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
410 }
411
412 float Button::GetNextAutoRepeatingDelay() const
413 {
414   return mNextAutoRepeatingDelay;
415 }
416
417 void Button::SetTogglableButton( bool togglable )
418 {
419   mTogglableButton = togglable;
420
421   // A togglable button can't be an autorepeating button.
422   if( togglable )
423   {
424     mAutoRepeating = false;
425   }
426 }
427
428 bool Button::IsTogglableButton() const
429 {
430   return mTogglableButton;
431 }
432
433 void Button::SetSelected( bool selected )
434 {
435   if( !mDisabled && mTogglableButton && ( selected != mSelected ) )
436   {
437     SetSelected( selected, true );
438   }
439 }
440
441 void Button::SetSelected( bool selected, bool emitSignal )
442 {
443   unsigned int buttonIndex, backgroundIndex;
444   bool animationStarted = false;
445
446   mSelected = selected;
447
448   switch( mPaintState )
449   {
450     case UnselectedState:
451     {
452       buttonIndex = FindChildIndex( mLabel );
453       InsertChild( buttonIndex, mSelectedContent );
454
455       if( mBackgroundContent )
456       {
457         backgroundIndex = 1;
458       }
459       else
460       {
461         backgroundIndex = 0;
462       }
463
464       InsertChild( backgroundIndex, mSelectedBackgroundContent );
465
466       // Notifies the derived class the button has been selected.
467       animationStarted = OnSelected();
468
469       if( animationStarted )
470       {
471         mPaintState = UnselectedSelectedTransition;
472       }
473       else
474       {
475         mPaintState = SelectedState;
476       }
477       break;
478     }
479     case SelectedState:
480     {
481       buttonIndex = FindChildIndex( mLabel );
482       InsertChild( buttonIndex, mButtonContent );
483
484       // Notifies the derived class the button has been selected.
485       animationStarted = OnSelected();
486
487       if( animationStarted )
488       {
489         mPaintState = SelectedUnselectedTransition;
490       }
491       else
492       {
493         mPaintState = UnselectedState;
494       }
495       break;
496     }
497     case UnselectedSelectedTransition:
498     {
499       // Notifies the derived class the button has been selected.
500       animationStarted = OnSelected();
501
502       if( animationStarted )
503       {
504         mPaintState = SelectedUnselectedTransition;
505       }
506       else
507       {
508         mPaintState = UnselectedState;
509       }
510       break;
511     }
512     case SelectedUnselectedTransition:
513     {
514       // Notifies the derived class the button has been selected.
515       animationStarted = OnSelected();
516
517       if( animationStarted )
518       {
519         mPaintState = UnselectedSelectedTransition;
520       }
521       else
522       {
523         mPaintState = SelectedState;
524       }
525       break;
526     }
527     case DisabledUnselectedTransition:
528     {
529       buttonIndex = FindChildIndex( mLabel );
530       InsertChild( buttonIndex, mSelectedContent );
531
532       if( mDisabledBackgroundContent )
533       {
534         if(  mBackgroundContent )
535         {
536           backgroundIndex = 2;
537         }
538         else
539         {
540           backgroundIndex = 1;
541         }
542       }
543       else if( mBackgroundContent )
544       {
545         backgroundIndex = 1;
546       }
547       else
548       {
549         backgroundIndex = 0;
550       }
551
552       InsertChild( backgroundIndex, mSelectedBackgroundContent );
553
554       // Notifies the derived class the button has been selected.
555       animationStarted = OnSelected();
556
557       if( animationStarted )
558       {
559         mPaintState = UnselectedSelectedTransition;
560       }
561       else
562       {
563         mPaintState = SelectedState;
564       }
565       break;
566     }
567     case DisabledSelectedTransition:
568     {
569       buttonIndex = FindChildIndex( mLabel );
570       InsertChild( buttonIndex, mButtonContent );
571
572       // Notifies the derived class the button has been selected.
573       animationStarted = OnSelected();
574
575       if( animationStarted )
576       {
577         mPaintState = SelectedUnselectedTransition;
578       }
579       else
580       {
581         mPaintState = UnselectedState;
582       }
583       break;
584     }
585     default:
586     {
587       break;
588     }
589   }
590
591   if( emitSignal )
592   {
593     Toolkit::Button handle( GetOwner() );
594
595     // Emit signal.
596     mStateChangedSignal.Emit( handle );
597   }
598
599   RelayoutRequest();
600 }
601
602 bool Button::IsSelected() const
603 {
604   return mTogglableButton && mSelected;
605 }
606
607 void Button::SetAnimationTime( float animationTime )
608 {
609   mAnimationTime = animationTime;
610 }
611
612 float Button::GetAnimationTime() const
613 {
614   return mAnimationTime;
615 }
616
617 void Button::SetLabel( const std::string& label )
618 {
619   Toolkit::TextLabel textLabel = Toolkit::TextLabel::New( label );
620   SetLabel( textLabel );
621 }
622
623 void Button::SetLabel( Actor label )
624 {
625   if( mLabel != label )
626   {
627     if( mLabel && mLabel.GetParent() )
628     {
629       mLabel.GetParent().Remove( mLabel );
630     }
631
632     mLabel = label;
633     mLabel.SetPosition( 0.f, 0.f );
634
635     // label should be the top of the button
636     Self().Add( mLabel );
637
638     OnLabelSet();
639
640     RelayoutRequest();
641   }
642 }
643
644 Actor Button::GetLabel() const
645 {
646   return mLabel;
647 }
648
649 Actor& Button::GetLabel()
650 {
651   return mLabel;
652 }
653
654 void Button::SetButtonImage( Actor image )
655 {
656   StopAllAnimations();
657
658   if( mButtonContent && mButtonContent.GetParent() )
659   {
660     Self().Remove( mButtonContent );
661   }
662
663   mButtonContent = image;
664
665   mButtonContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
666   mButtonContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
667   mButtonContent.SetPosition( 0.f, 0.f );
668
669   if( mPaintState == UnselectedState )
670   {
671     unsigned int index = FindChildIndex( mLabel );
672
673     Self().Insert( index, mButtonContent );
674   }
675
676   OnButtonImageSet();
677 }
678
679 Actor Button::GetButtonImage() const
680 {
681   return mButtonContent;
682 }
683
684 Actor& Button::GetButtonImage()
685 {
686   return mButtonContent;
687 }
688
689 void Button::SetSelectedImage( Actor image )
690 {
691   StopAllAnimations();
692
693   if( mSelectedContent && mSelectedContent.GetParent() )
694   {
695     Self().Remove( mSelectedContent );
696   }
697
698   mSelectedContent = image;
699
700   mSelectedContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
701   mSelectedContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
702   mSelectedContent.SetPosition( 0.f, 0.f );
703
704   if( mPaintState == SelectedState )
705   {
706     unsigned int index = FindChildIndex( mLabel );
707
708     Self().Insert( index, mSelectedContent );
709   }
710
711   OnSelectedImageSet();
712 }
713
714 Actor Button::GetSelectedImage() const
715 {
716   return mSelectedContent;
717 }
718
719 Actor& Button::GetSelectedImage()
720 {
721   return mSelectedContent;
722 }
723
724 void Button::SetBackgroundImage( Actor image )
725 {
726   StopAllAnimations();
727
728   if( mBackgroundContent && mBackgroundContent.GetParent() )
729   {
730     Self().Remove( mBackgroundContent );
731   }
732
733   mBackgroundContent = image;
734
735   mBackgroundContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
736   mBackgroundContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
737   mBackgroundContent.SetPosition( 0.f, 0.f );
738
739   if( mPaintState == UnselectedState || mPaintState == SelectedState )
740   {
741     Self().Insert( 0, mBackgroundContent );
742   }
743
744   OnBackgroundImageSet();
745 }
746
747 Actor Button::GetBackgroundImage() const
748 {
749   return mBackgroundContent;
750 }
751
752 Actor& Button::GetBackgroundImage()
753 {
754   return mBackgroundContent;
755 }
756
757 void Button::SetSelectedBackgroundImage( Actor image )
758 {
759   StopAllAnimations();
760
761   if( mSelectedBackgroundContent && mSelectedBackgroundContent.GetParent() )
762   {
763     Self().Remove( mSelectedBackgroundContent );
764   }
765
766   mSelectedBackgroundContent = image;
767
768   mSelectedBackgroundContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
769   mSelectedBackgroundContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
770   mSelectedBackgroundContent.SetPosition( 0.f, 0.f );
771
772   if( mPaintState == SelectedState )
773   {
774     if( mBackgroundContent )
775     {
776       Self().Insert( 1, mSelectedBackgroundContent );
777     }
778     else
779     {
780       Self().Insert( 0, mSelectedBackgroundContent );
781     }
782   }
783
784   OnSelectedBackgroundImageSet();
785 }
786
787 Actor Button::GetSelectedBackgroundImage() const
788 {
789   return mSelectedBackgroundContent;
790 }
791
792 Actor& Button::GetSelectedBackgroundImage()
793 {
794   return mSelectedBackgroundContent;
795 }
796
797 void Button::SetDisabledImage( Actor image )
798 {
799   StopAllAnimations();
800
801   if( mDisabledContent && mDisabledContent.GetParent() )
802   {
803     Self().Remove( mDisabledContent );
804   }
805
806   mDisabledContent = image;
807
808   mDisabledContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
809   mDisabledContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
810   mDisabledContent.SetPosition( 0.f, 0.f );
811
812   if( mPaintState == DisabledUnselectedState || mPaintState == DisabledSelectedState )
813   {
814     unsigned int index = FindChildIndex( mLabel );
815
816     Self().Insert( index, mDisabledContent );
817   }
818
819   OnDisabledImageSet();
820 }
821
822 Actor Button::GetDisabledImage() const
823 {
824   return mDisabledContent;
825 }
826
827 Actor& Button::GetDisabledImage()
828 {
829   return mDisabledContent;
830 }
831
832 void Button::SetDisabledSelectedImage( Actor image )
833 {
834   StopAllAnimations();
835
836   if( mDisabledSelectedContent && mDisabledSelectedContent.GetParent() )
837   {
838     Self().Remove( mDisabledSelectedContent );
839   }
840
841   mDisabledSelectedContent = image;
842
843   mDisabledSelectedContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
844   mDisabledSelectedContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
845   mDisabledSelectedContent.SetPosition( 0.f, 0.f );
846
847   if( mPaintState == DisabledSelectedState )
848   {
849     unsigned int index = FindChildIndex( mLabel );
850
851     Self().Insert( index, mDisabledSelectedContent );
852   }
853
854   OnDisabledSelectedImageSet();
855 }
856
857 Actor Button::GetDisabledSelectedImage() const
858 {
859   return mDisabledSelectedContent;
860 }
861
862 Actor& Button::GetDisabledSelectedImage()
863 {
864   return mDisabledSelectedContent;
865 }
866
867 void Button::SetDisabledBackgroundImage( Actor image )
868 {
869   StopAllAnimations();
870
871   if( mDisabledBackgroundContent && mDisabledBackgroundContent.GetParent() )
872   {
873     Self().Remove( mDisabledBackgroundContent );
874   }
875
876   mDisabledBackgroundContent = image;
877
878   mDisabledBackgroundContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
879   mDisabledBackgroundContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
880   mDisabledBackgroundContent.SetPosition( 0.f, 0.f );
881
882   if( mPaintState == DisabledUnselectedState || mPaintState == DisabledSelectedState )
883   {
884     Self().Insert( 0, mDisabledBackgroundContent );
885   }
886
887   OnDisabledBackgroundImageSet();
888 }
889
890 Actor Button::GetDisabledBackgroundImage() const
891 {
892   return mDisabledBackgroundContent;
893 }
894
895 Actor& Button::GetDisabledBackgroundImage()
896 {
897   return mDisabledBackgroundContent;
898 }
899
900 bool Button::DoAction( BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes )
901 {
902   bool ret = false;
903
904   Dali::BaseHandle handle( object );
905
906   Toolkit::Button button = Toolkit::Button::DownCast( handle );
907
908   DALI_ASSERT_ALWAYS( button );
909
910   if( 0 == strcmp( actionName.c_str(), ACTION_BUTTON_CLICK ) )
911   {
912     GetImplementation( button ).DoClickAction( attributes );
913     ret = true;
914   }
915
916   return ret;
917 }
918
919 void Button::DoClickAction( const PropertyValueContainer& attributes )
920 {
921   // Prevents the button signals from doing a recursive loop by sending an action
922   // and re-emitting the signals.
923   if( !mClickActionPerforming )
924   {
925     mClickActionPerforming = true;
926     OnButtonDown();
927     mState = ButtonDown;
928     OnButtonUp();
929     mClickActionPerforming = false;
930   }
931 }
932
933 void Button::UpdatePaintTransitionState()
934 {
935   switch( mPaintState )
936   {
937     case UnselectedSelectedTransition:
938     {
939       RemoveChild( mButtonContent );
940       mPaintState = SelectedState;
941       break;
942     }
943     case SelectedUnselectedTransition:
944     {
945       RemoveChild( mSelectedBackgroundContent );
946       RemoveChild( mSelectedContent );
947       mPaintState = UnselectedState;
948       break;
949     }
950     case UnselectedDisabledTransition:
951     {
952       RemoveChild( mBackgroundContent );
953       RemoveChild( mButtonContent );
954       mPaintState = DisabledUnselectedState;
955       break;
956     }
957     case DisabledUnselectedTransition:
958     {
959       RemoveChild( mDisabledBackgroundContent );
960       RemoveChild( mDisabledContent );
961       mPaintState = UnselectedState;
962       break;
963     }
964     case SelectedDisabledTransition:
965     {
966       RemoveChild( mBackgroundContent );
967       RemoveChild( mSelectedBackgroundContent );
968       RemoveChild( mSelectedContent );
969       mPaintState = DisabledSelectedState;
970       break;
971     }
972     case DisabledSelectedTransition:
973     {
974       RemoveChild( mDisabledBackgroundContent );
975       RemoveChild( mDisabledSelectedContent );
976       mPaintState = SelectedState;
977       break;
978     }
979     default:
980     {
981       break;
982     }
983   }
984 }
985
986 void Button::OnButtonStageDisconnection()
987 {
988   if( ButtonDown == mState )
989   {
990     if( !mTogglableButton )
991     {
992       Released();
993
994       if( mAutoRepeating )
995       {
996         mAutoRepeatingTimer.Reset();
997       }
998     }
999   }
1000 }
1001
1002 void Button::OnButtonDown()
1003 {
1004   if( !mTogglableButton )
1005   {
1006     Toolkit::Button handle( GetOwner() );
1007
1008     Pressed();
1009
1010     if( mAutoRepeating )
1011     {
1012       SetUpTimer( mInitialAutoRepeatingDelay );
1013     }
1014
1015     //Emit signal.
1016     mPressedSignal.Emit( handle );
1017   }
1018 }
1019
1020 void Button::OnButtonUp()
1021 {
1022   if( ButtonDown == mState )
1023   {
1024     if( mTogglableButton )
1025     {
1026       SetSelected( !mSelected );
1027     }
1028     else
1029     {
1030       Released();
1031
1032       if( mAutoRepeating )
1033       {
1034         mAutoRepeatingTimer.Reset();
1035       }
1036
1037       Toolkit::Button handle( GetOwner() );
1038
1039       //Emit signal.
1040       mReleasedSignal.Emit( handle );
1041       mClickedSignal.Emit( handle );
1042     }
1043   }
1044 }
1045
1046 void Button::OnTouchPointLeave()
1047 {
1048   if( ButtonDown == mState )
1049   {
1050     if( !mTogglableButton )
1051     {
1052       Toolkit::Button handle( GetOwner() );
1053
1054       Released();
1055
1056       if( mAutoRepeating )
1057       {
1058         mAutoRepeatingTimer.Reset();
1059       }
1060
1061       //Emit signal.
1062       mReleasedSignal.Emit( handle );
1063     }
1064   }
1065 }
1066
1067 void Button::OnTouchPointInterrupted()
1068 {
1069   OnTouchPointLeave();
1070 }
1071
1072 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
1073 {
1074   return mPressedSignal;
1075 }
1076
1077 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
1078 {
1079   return mReleasedSignal;
1080 }
1081
1082 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
1083 {
1084   return mClickedSignal;
1085 }
1086
1087 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
1088 {
1089   return mStateChangedSignal;
1090 }
1091
1092 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1093 {
1094   Dali::BaseHandle handle( object );
1095
1096   bool connected( true );
1097   Toolkit::Button button = Toolkit::Button::DownCast( handle );
1098
1099   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
1100   {
1101     button.PressedSignal().Connect( tracker, functor );
1102   }
1103   else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
1104   {
1105     button.ReleasedSignal().Connect( tracker, functor );
1106   }
1107   else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
1108   {
1109     button.ClickedSignal().Connect( tracker, functor );
1110   }
1111   else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
1112   {
1113     button.StateChangedSignal().Connect( tracker, functor );
1114   }
1115   else
1116   {
1117     // signalName does not match any signal
1118     connected = false;
1119   }
1120
1121   return connected;
1122 }
1123
1124 bool Button::OnTouchEvent(const TouchEvent& event)
1125 {
1126   // Only events are processed when the button is not disabled and the touch event has only
1127   // one touch point.
1128   if( ( !mDisabled ) && ( 1 == event.GetPointCount() ) )
1129   {
1130     switch( event.GetPoint(0).state )
1131     {
1132       case TouchPoint::Down:
1133       {
1134         OnButtonDown(); // Notification for derived classes.
1135
1136         // Sets the button state to ButtonDown.
1137         mState = ButtonDown;
1138         break;
1139       }
1140       case TouchPoint::Up:
1141       {
1142         OnButtonUp(); // Notification for derived classes.
1143
1144         // Sets the button state to ButtonUp.
1145         mState = ButtonUp;
1146         break;
1147       }
1148       case TouchPoint::Interrupted:
1149       {
1150         OnTouchPointInterrupted(); // Notification for derived classes.
1151
1152         // Sets the button state to the default (ButtonUp).
1153         mState = ButtonUp;
1154         break;
1155       }
1156       case TouchPoint::Leave:
1157       {
1158         OnTouchPointLeave(); // Notification for derived classes.
1159
1160         // Sets the button state to the default (ButtonUp).
1161         mState = ButtonUp;
1162         break;
1163       }
1164       case TouchPoint::Motion:
1165       case TouchPoint::Stationary: // FALLTHROUGH
1166       {
1167         // Nothing to do
1168         break;
1169       }
1170       default:
1171       {
1172         DALI_ASSERT_ALWAYS( !"Point status unhandled." );
1173         break;
1174       }
1175     }
1176   }
1177   else if( 1 < event.GetPointCount() )
1178   {
1179     OnTouchPointLeave(); // Notification for derived classes.
1180
1181     // Sets the button state to the default (ButtonUp).
1182     mState = ButtonUp;
1183   }
1184
1185   return false;
1186 }
1187
1188 void Button::OnInitialize()
1189 {
1190   Actor self = Self();
1191
1192   mTapDetector = TapGestureDetector::New();
1193   mTapDetector.Attach( self );
1194   mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
1195
1196   OnButtonInitialize();
1197
1198   self.SetDrawMode( DrawMode::OVERLAY );
1199   self.SetKeyboardFocusable( true );
1200 }
1201
1202 void Button::OnActivated()
1203 {
1204   // When the button is activated, it performs the click action
1205   PropertyValueContainer attributes;
1206   DoClickAction( attributes );
1207 }
1208
1209 void Button::OnControlStageDisconnection()
1210 {
1211   OnButtonStageDisconnection(); // Notification for derived classes.
1212   mState = ButtonUp;
1213 }
1214
1215 void Button::OnTap(Actor actor, const TapGesture& tap)
1216 {
1217   // Do nothing.
1218 }
1219
1220 void Button::SetUpTimer( float delay )
1221 {
1222   mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
1223   mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
1224   mAutoRepeatingTimer.Start();
1225 }
1226
1227 bool Button::AutoRepeatingSlot()
1228 {
1229   bool consumed = false;
1230   if( !mDisabled )
1231   {
1232     // Restart the autorepeat timer.
1233     SetUpTimer( mNextAutoRepeatingDelay );
1234
1235     Pressed();
1236
1237     Toolkit::Button handle( GetOwner() );
1238
1239     //Emit signal.
1240     consumed = mReleasedSignal.Emit( handle );
1241     consumed |= mClickedSignal.Emit( handle );
1242     consumed |= mPressedSignal.Emit( handle );
1243  }
1244
1245   return consumed;
1246 }
1247
1248 void Button::Pressed()
1249 {
1250   unsigned int buttonIndex, backgroundIndex;
1251   bool animationStarted = false;
1252
1253   switch( mPaintState )
1254   {
1255     case UnselectedState:
1256     {
1257       buttonIndex = FindChildIndex( mLabel );
1258       InsertChild( buttonIndex, mSelectedContent );
1259
1260       if( mBackgroundContent )
1261       {
1262         backgroundIndex = 1;
1263       }
1264       else
1265       {
1266         backgroundIndex = 0;
1267       }
1268
1269       InsertChild( backgroundIndex, mSelectedBackgroundContent );
1270
1271       // Notifies the derived class the button has been pressed.
1272       animationStarted = OnPressed();
1273
1274       if( animationStarted )
1275       {
1276         mPaintState = UnselectedSelectedTransition;
1277       }
1278       else
1279       {
1280         mPaintState = SelectedState;
1281       }
1282       break;
1283     }
1284     case SelectedUnselectedTransition:
1285     {
1286       // Notifies the derived class the button has been pressed.
1287       animationStarted = OnPressed();
1288
1289       if( animationStarted )
1290       {
1291         mPaintState = UnselectedSelectedTransition;
1292       }
1293       else
1294       {
1295         mPaintState = SelectedState;
1296       }
1297       break;
1298     }
1299     case DisabledUnselectedTransition:
1300     {
1301       buttonIndex = FindChildIndex( mLabel );
1302       InsertChild( buttonIndex, mSelectedContent );
1303
1304       if( mDisabledBackgroundContent )
1305       {
1306         if(  mBackgroundContent )
1307         {
1308           backgroundIndex = 2;
1309         }
1310         else
1311         {
1312           backgroundIndex = 1;
1313         }
1314       }
1315       else if( mBackgroundContent )
1316       {
1317         backgroundIndex = 1;
1318       }
1319       else
1320       {
1321         backgroundIndex = 0;
1322       }
1323
1324       InsertChild( backgroundIndex, mSelectedBackgroundContent );
1325
1326       // Notifies the derived class the button has been pressed.
1327       animationStarted = OnPressed();
1328
1329       if( animationStarted )
1330       {
1331         mPaintState = UnselectedSelectedTransition;
1332       }
1333       else
1334       {
1335         mPaintState = SelectedState;
1336       }
1337       break;
1338     }
1339     default:
1340       break;
1341   }
1342 }
1343
1344 void Button::Released()
1345 {
1346   unsigned int buttonIndex;
1347   bool animationStarted = false;
1348
1349   switch( mPaintState )
1350   {
1351     case SelectedState:
1352     {
1353       buttonIndex = FindChildIndex( mLabel );
1354       InsertChild( buttonIndex, mButtonContent );
1355
1356       // Notifies the derived class the button has been released.
1357       animationStarted = OnReleased();
1358
1359       if( animationStarted )
1360       {
1361         mPaintState = SelectedUnselectedTransition;
1362       }
1363       else
1364       {
1365         mPaintState = UnselectedState;
1366       }
1367       break;
1368     }
1369     case UnselectedSelectedTransition:
1370     {
1371       // Notifies the derived class the button has been released.
1372       animationStarted = OnReleased();
1373
1374       if( animationStarted )
1375       {
1376         mPaintState = SelectedUnselectedTransition;
1377       }
1378       else
1379       {
1380         mPaintState = UnselectedState;
1381       }
1382       break;
1383     }
1384     case DisabledSelectedTransition:
1385     {
1386       buttonIndex = FindChildIndex( mLabel );
1387       InsertChild( buttonIndex, mButtonContent );
1388
1389       // Notifies the derived class the button has been released.
1390       animationStarted = OnReleased();
1391
1392       if( animationStarted )
1393       {
1394         mPaintState = SelectedUnselectedTransition;
1395       }
1396       else
1397       {
1398         mPaintState = UnselectedState;
1399       }
1400       break;
1401     }
1402     default:
1403     {
1404       break;
1405     }
1406   }
1407 }
1408
1409 Button::ButtonState Button::GetState()
1410 {
1411   return mState;
1412 }
1413
1414 Button::PaintState Button::GetPaintState()
1415 {
1416   return mPaintState;
1417 }
1418
1419 void Button::InsertChild( unsigned int index, Actor& actor )
1420 {
1421   if( actor )
1422   {
1423     Self().Insert( index, actor);
1424   }
1425 }
1426
1427 void Button::RemoveChild( Actor& actor )
1428 {
1429   if( actor && actor.GetParent() )
1430   {
1431     Self().Remove( actor );
1432   }
1433 }
1434
1435 unsigned int Button::FindChildIndex( Actor& actor )
1436 {
1437   Actor self = Self();
1438   unsigned int childrenNum = self.GetChildCount();
1439
1440   for( unsigned int i = 0; i < childrenNum; i++ )
1441   {
1442     Actor child = self.GetChildAt( i );
1443     if( child == actor )
1444     {
1445       return i;
1446     }
1447   }
1448
1449   return childrenNum;
1450 }
1451
1452 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
1453 {
1454   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1455
1456   if ( button )
1457   {
1458     switch ( index )
1459     {
1460       case Toolkit::Button::Property::DISABLED:
1461       {
1462         GetImplementation( button ).SetDisabled( value.Get<bool>() );
1463         break;
1464       }
1465
1466       case Toolkit::Button::Property::AUTO_REPEATING:
1467       {
1468         GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
1469         break;
1470       }
1471
1472       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1473       {
1474         GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
1475         break;
1476       }
1477
1478       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1479       {
1480         GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
1481         break;
1482       }
1483
1484       case Toolkit::Button::Property::TOGGLABLE:
1485       {
1486         GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
1487         break;
1488       }
1489
1490       case Toolkit::Button::Property::SELECTED:
1491       {
1492         GetImplementation( button ).SetSelected( value.Get< bool >() );
1493         break;
1494       }
1495
1496       case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
1497       {
1498         GetImplementation( button ).SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1499         break;
1500       }
1501
1502       case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
1503       {
1504         GetImplementation( button ).SetSelectedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1505         break;
1506       }
1507
1508       case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
1509       {
1510         GetImplementation( button ).SetDisabledImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1511         break;
1512       }
1513
1514       case Toolkit::Button::Property::LABEL_ACTOR:
1515       {
1516         GetImplementation( button ).SetLabel( Scripting::NewActor( value.Get< Property::Map >() ) );
1517         break;
1518       }
1519     }
1520   }
1521 }
1522
1523 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
1524 {
1525   Property::Value value;
1526
1527   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1528
1529   if ( button )
1530   {
1531     switch ( propertyIndex )
1532     {
1533       case Toolkit::Button::Property::DISABLED:
1534       {
1535         value = GetImplementation( button ).mDisabled;
1536         break;
1537       }
1538
1539       case Toolkit::Button::Property::AUTO_REPEATING:
1540       {
1541         value = GetImplementation( button ).mAutoRepeating;
1542         break;
1543       }
1544
1545       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1546       {
1547         value = GetImplementation( button ).mInitialAutoRepeatingDelay;
1548         break;
1549       }
1550
1551       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1552       {
1553         value = GetImplementation( button ).mNextAutoRepeatingDelay;
1554         break;
1555       }
1556
1557       case Toolkit::Button::Property::TOGGLABLE:
1558       {
1559         value = GetImplementation( button ).mTogglableButton;
1560         break;
1561       }
1562
1563       case Toolkit::Button::Property::SELECTED:
1564       {
1565         value = GetImplementation( button ).mSelected;
1566         break;
1567       }
1568
1569       case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
1570       {
1571         Property::Map map;
1572         Scripting::CreatePropertyMap( GetImplementation( button ).mButtonContent, map );
1573         value = map;
1574         break;
1575       }
1576
1577       case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
1578       {
1579         Property::Map map;
1580         Scripting::CreatePropertyMap( GetImplementation( button ).mSelectedContent, map );
1581         value = map;
1582         break;
1583       }
1584
1585       case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
1586       {
1587         Property::Map map;
1588         Scripting::CreatePropertyMap( GetImplementation( button ).mDisabledContent, map );
1589         value = map;
1590         break;
1591       }
1592
1593       case Toolkit::Button::Property::LABEL_ACTOR:
1594       {
1595         Property::Map map;
1596         Scripting::CreatePropertyMap( GetImplementation( button ).mLabel, map );
1597         value = map;
1598         break;
1599       }
1600     }
1601   }
1602
1603   return value;
1604 }
1605
1606 } // namespace Internal
1607
1608 } // namespace Toolkit
1609
1610 } // namespace Dali