Fixed crash in case that overshoot scroll is not enabled
[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 <dali/public-api/events/touch-event.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/public-api/object/type-registry-helper.h>
25 #include <dali/public-api/actors/image-actor.h>
26 #include <dali/public-api/scripting/scripting.h>
27
28 // INTERNAL INCLUDES
29 #include <dali-toolkit/public-api/controls/text-view/text-view.h>
30
31 /**
32  * Button states and contents
33  *                                         (3) mSelectedContent
34  *  (2) mButtonContent                     (2) mSelectedBackgroundContent
35  *  (1) mBackgroundContent                 (1) mBackgroundContent
36  * < unselected > ----------------------- < selected >
37  *       |                OnSelect()            |
38  *       | OnDisabled()                         | OnDisabled()
39  *       |                                      |
40  * < disabled >                           < disabled-selected >
41  *  (2) mDisabledContent                   (2) mDisabledSelectedContent
42  *  (1) mDisabledBackgroundContent         (1) mDisabledBackgroundContent
43  *
44  * The drawing order of child actors is as follows.
45  *
46  *  Top      mLabel
47  *   |       mButtonContent / mSelectedContent / mDisabledContent / mDisabledSelectedContent
48  *   |       mSelectedBackgroundContent
49  * Bottom    mBackgroundContent / mDisabledBackgroundContent
50  *
51  * Some of contents may be missed.
52  * 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.
53  */
54
55 namespace Dali
56 {
57
58 namespace Toolkit
59 {
60
61 namespace Internal
62 {
63
64 namespace
65 {
66
67 BaseHandle Create()
68 {
69   // empty handle as we cannot create button (but type registered for clicked signal)
70   return BaseHandle();
71 }
72
73 // Setup properties, signals and actions using the type-registry.
74 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Button, Toolkit::Control, Create );
75
76 DALI_PROPERTY_REGISTRATION( Button, "disabled",                     BOOLEAN, DISABLED                     )
77 DALI_PROPERTY_REGISTRATION( Button, "auto-repeating",               BOOLEAN, AUTO_REPEATING               )
78 DALI_PROPERTY_REGISTRATION( Button, "initial-auto-repeating-delay", FLOAT,   INITIAL_AUTO_REPEATING_DELAY )
79 DALI_PROPERTY_REGISTRATION( Button, "next-auto-repeating-delay",    FLOAT,   NEXT_AUTO_REPEATING_DELAY    )
80 DALI_PROPERTY_REGISTRATION( Button, "togglable",                    BOOLEAN, TOGGLABLE                    )
81 DALI_PROPERTY_REGISTRATION( Button, "selected",                     BOOLEAN, SELECTED                     )
82 DALI_PROPERTY_REGISTRATION( Button, "normal-state-actor",           MAP,     NORMAL_STATE_ACTOR           )
83 DALI_PROPERTY_REGISTRATION( Button, "selected-state-actor",         MAP,     SELECTED_STATE_ACTOR         )
84 DALI_PROPERTY_REGISTRATION( Button, "disabled-state-actor",         MAP,     DISABLED_STATE_ACTOR         )
85 DALI_PROPERTY_REGISTRATION( Button, "label-actor",                  MAP,     LABEL_ACTOR                  )
86
87 DALI_SIGNAL_REGISTRATION(   Button, "pressed",                               SIGNAL_PRESSED               )
88 DALI_SIGNAL_REGISTRATION(   Button, "released",                              SIGNAL_RELEASED              )
89 DALI_SIGNAL_REGISTRATION(   Button, "clicked",                               SIGNAL_CLICKED               )
90 DALI_SIGNAL_REGISTRATION(   Button, "state-changed",                         SIGNAL_STATE_CHANGED         )
91
92 DALI_ACTION_REGISTRATION(   Button, "button-click",                          ACTION_BUTTON_CLICK          )
93
94 DALI_TYPE_REGISTRATION_END()
95
96 const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f );
97 const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f );
98
99 } // unnamed namespace
100
101 Button::Button()
102 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
103   mAutoRepeatingTimer(),
104   mDisabled( false ),
105   mAutoRepeating( false ),
106   mTogglableButton( false ),
107   mSelected( false ),
108   mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ),
109   mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ),
110   mAnimationTime( 0.0f ),
111   mClickActionPerforming( false ),
112   mState( ButtonUp ),
113   mPaintState( UnselectedState )
114 {
115 }
116
117 Button::~Button()
118 {
119   if( mAutoRepeatingTimer )
120   {
121     mAutoRepeatingTimer.Reset();
122   }
123 }
124
125 void Button::SetDisabled( bool disabled )
126 {
127   if( disabled != mDisabled )
128   {
129     unsigned int backgroundIndex;
130     unsigned int buttonIndex;
131
132     bool animationStarted = false;
133
134     mDisabled = disabled;
135
136     switch( mPaintState )
137     {
138       case UnselectedState:
139       {
140         buttonIndex = FindChildIndex( mLabel );
141         InsertChild( buttonIndex, mDisabledContent );
142
143         if( mBackgroundContent )
144         {
145           backgroundIndex = 1;
146         }
147         else
148         {
149           backgroundIndex = 0;
150         }
151
152         InsertChild( backgroundIndex, mDisabledBackgroundContent );
153
154         animationStarted = OnDisabled();
155
156         if( animationStarted )
157         {
158           mPaintState = UnselectedDisabledTransition;
159         }
160         else
161         {
162           mPaintState = DisabledUnselectedState;
163         }
164         break;
165       }
166       case SelectedState:
167       {
168         buttonIndex = FindChildIndex( mLabel );
169         InsertChild( buttonIndex, mDisabledSelectedContent );
170
171         if( mBackgroundContent )
172         {
173           backgroundIndex = 1;
174         }
175         else
176         {
177           backgroundIndex = 0;
178         }
179
180         InsertChild( backgroundIndex, mDisabledBackgroundContent );
181
182         animationStarted = OnDisabled();
183
184         if( animationStarted )
185         {
186           mPaintState = SelectedDisabledTransition;
187         }
188         else
189         {
190           mPaintState = DisabledSelectedState;
191         }
192         break;
193       }
194       case DisabledUnselectedState:
195       {
196         buttonIndex = FindChildIndex( mLabel );
197         InsertChild( buttonIndex, mButtonContent );
198
199         if( mDisabledBackgroundContent )
200         {
201           backgroundIndex = 1;
202         }
203         else
204         {
205           backgroundIndex = 0;
206         }
207
208         InsertChild( backgroundIndex, mBackgroundContent );
209
210         animationStarted = OnDisabled();
211
212         if( animationStarted )
213         {
214           mPaintState = DisabledUnselectedTransition;
215         }
216         else
217         {
218           mPaintState = UnselectedState;
219         }
220         break;
221       }
222       case DisabledSelectedState:
223       {
224         buttonIndex = FindChildIndex( mLabel );
225         InsertChild( buttonIndex, mSelectedContent );
226
227         if( mDisabledBackgroundContent )
228         {
229           backgroundIndex = 1;
230         }
231         else
232         {
233           backgroundIndex = 0;
234         }
235
236         InsertChild( backgroundIndex, mSelectedBackgroundContent );
237         InsertChild( backgroundIndex, mBackgroundContent );
238
239         animationStarted = OnDisabled();
240
241         if( animationStarted )
242         {
243           mPaintState = DisabledSelectedTransition;
244         }
245         else
246         {
247           mPaintState = SelectedState;
248         }
249         break;
250       }
251       case UnselectedSelectedTransition:
252       {
253         buttonIndex = FindChildIndex( mLabel );
254         InsertChild( buttonIndex, mDisabledSelectedContent );
255
256         if( mBackgroundContent )
257         {
258           backgroundIndex = 1;
259         }
260         else
261         {
262           backgroundIndex = 0;
263         }
264
265         InsertChild( backgroundIndex, mDisabledBackgroundContent );
266
267         animationStarted = OnDisabled();
268
269         if( animationStarted )
270         {
271           mPaintState = SelectedDisabledTransition;
272         }
273         else
274         {
275           mPaintState = DisabledSelectedState;
276         }
277         break;
278       }
279       case SelectedUnselectedTransition:
280       {
281         buttonIndex = FindChildIndex( mLabel );
282         InsertChild( buttonIndex, mDisabledContent );
283
284         if( mBackgroundContent )
285         {
286           backgroundIndex = 1;
287         }
288         else
289         {
290           backgroundIndex = 0;
291         }
292
293         InsertChild( backgroundIndex, mDisabledBackgroundContent );
294
295         animationStarted = OnDisabled();
296
297         if( animationStarted )
298         {
299           mPaintState = UnselectedDisabledTransition;
300         }
301         else
302         {
303           mPaintState = DisabledUnselectedState;
304         }
305         break;
306       }
307       case UnselectedDisabledTransition:
308       {
309         animationStarted = OnDisabled();
310
311         if( animationStarted )
312         {
313           mPaintState = DisabledUnselectedTransition;
314         }
315         else
316         {
317           mPaintState = UnselectedState;
318         }
319         break;
320       }
321       case DisabledUnselectedTransition:
322       {
323         animationStarted = OnDisabled();
324
325         if( animationStarted )
326         {
327           mPaintState = UnselectedDisabledTransition;
328         }
329         else
330         {
331           mPaintState = DisabledUnselectedState;
332         }
333         break;
334       }
335       case SelectedDisabledTransition:
336       {
337         animationStarted = OnDisabled();
338
339         if( animationStarted )
340         {
341           mPaintState = DisabledSelectedTransition;
342         }
343         else
344         {
345           mPaintState = SelectedState;
346         }
347         break;
348       }
349       case DisabledSelectedTransition:
350       {
351         animationStarted = OnDisabled();
352
353         if( animationStarted )
354         {
355           mPaintState = SelectedDisabledTransition;
356         }
357         else
358         {
359           mPaintState = DisabledSelectedState;
360         }
361         break;
362       }
363     }
364   }
365 }
366
367 bool Button::IsDisabled() const
368 {
369   return mDisabled;
370 }
371
372 void Button::SetAutoRepeating( bool autoRepeating )
373 {
374   mAutoRepeating = autoRepeating;
375
376   // An autorepeating button can't be a togglable button.
377   if( autoRepeating )
378   {
379     mTogglableButton = false;
380
381     if( mSelected )
382     {
383       // Emit a signal is not wanted, only change the appearance.
384       SetSelected( false, false );
385     }
386   }
387 }
388
389 bool Button::IsAutoRepeating() const
390 {
391   return mAutoRepeating;
392 }
393
394 void Button::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
395 {
396   DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
397   mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
398 }
399
400 float Button::GetInitialAutoRepeatingDelay() const
401 {
402   return mInitialAutoRepeatingDelay;
403 }
404
405 void Button::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
406 {
407   DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
408   mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
409 }
410
411 float Button::GetNextAutoRepeatingDelay() const
412 {
413   return mNextAutoRepeatingDelay;
414 }
415
416 void Button::SetTogglableButton( bool togglable )
417 {
418   mTogglableButton = togglable;
419
420   // A togglable button can't be an autorepeating button.
421   if( togglable )
422   {
423     mAutoRepeating = false;
424   }
425 }
426
427 bool Button::IsTogglableButton() const
428 {
429   return mTogglableButton;
430 }
431
432 void Button::SetSelected( bool selected )
433 {
434   if( !mDisabled && mTogglableButton && ( selected != mSelected ) )
435   {
436     SetSelected( selected, true );
437   }
438 }
439
440 void Button::SetSelected( bool selected, bool emitSignal )
441 {
442   unsigned int buttonIndex, backgroundIndex;
443   bool animationStarted = false;
444
445   mSelected = selected;
446
447   switch( mPaintState )
448   {
449     case UnselectedState:
450     {
451       buttonIndex = FindChildIndex( mLabel );
452       InsertChild( buttonIndex, mSelectedContent );
453
454       if( mBackgroundContent )
455       {
456         backgroundIndex = 1;
457       }
458       else
459       {
460         backgroundIndex = 0;
461       }
462
463       InsertChild( backgroundIndex, mSelectedBackgroundContent );
464
465       // Notifies the derived class the button has been selected.
466       animationStarted = OnSelected();
467
468       if( animationStarted )
469       {
470         mPaintState = UnselectedSelectedTransition;
471       }
472       else
473       {
474         mPaintState = SelectedState;
475       }
476       break;
477     }
478     case SelectedState:
479     {
480       buttonIndex = FindChildIndex( mLabel );
481       InsertChild( buttonIndex, mButtonContent );
482
483       // Notifies the derived class the button has been selected.
484       animationStarted = OnSelected();
485
486       if( animationStarted )
487       {
488         mPaintState = SelectedUnselectedTransition;
489       }
490       else
491       {
492         mPaintState = UnselectedState;
493       }
494       break;
495     }
496     case UnselectedSelectedTransition:
497     {
498       // Notifies the derived class the button has been selected.
499       animationStarted = OnSelected();
500
501       if( animationStarted )
502       {
503         mPaintState = SelectedUnselectedTransition;
504       }
505       else
506       {
507         mPaintState = UnselectedState;
508       }
509       break;
510     }
511     case SelectedUnselectedTransition:
512     {
513       // Notifies the derived class the button has been selected.
514       animationStarted = OnSelected();
515
516       if( animationStarted )
517       {
518         mPaintState = UnselectedSelectedTransition;
519       }
520       else
521       {
522         mPaintState = SelectedState;
523       }
524       break;
525     }
526     case DisabledUnselectedTransition:
527     {
528       buttonIndex = FindChildIndex( mLabel );
529       InsertChild( buttonIndex, mSelectedContent );
530
531       if( mDisabledBackgroundContent )
532       {
533         if(  mBackgroundContent )
534         {
535           backgroundIndex = 2;
536         }
537         else
538         {
539           backgroundIndex = 1;
540         }
541       }
542       else if( mBackgroundContent )
543       {
544         backgroundIndex = 1;
545       }
546       else
547       {
548         backgroundIndex = 0;
549       }
550
551       InsertChild( backgroundIndex, mSelectedBackgroundContent );
552
553       // Notifies the derived class the button has been selected.
554       animationStarted = OnSelected();
555
556       if( animationStarted )
557       {
558         mPaintState = UnselectedSelectedTransition;
559       }
560       else
561       {
562         mPaintState = SelectedState;
563       }
564       break;
565     }
566     case DisabledSelectedTransition:
567     {
568       buttonIndex = FindChildIndex( mLabel );
569       InsertChild( buttonIndex, mButtonContent );
570
571       // Notifies the derived class the button has been selected.
572       animationStarted = OnSelected();
573
574       if( animationStarted )
575       {
576         mPaintState = SelectedUnselectedTransition;
577       }
578       else
579       {
580         mPaintState = UnselectedState;
581       }
582       break;
583     }
584     default:
585     {
586       break;
587     }
588   }
589
590   if( emitSignal )
591   {
592     Toolkit::Button handle( GetOwner() );
593
594     // Emit signal.
595     mStateChangedSignal.Emit( handle );
596   }
597
598   RelayoutRequest();
599 }
600
601 bool Button::IsSelected() const
602 {
603   return mTogglableButton && mSelected;
604 }
605
606 void Button::SetAnimationTime( float animationTime )
607 {
608   mAnimationTime = animationTime;
609 }
610
611 float Button::GetAnimationTime() const
612 {
613   return mAnimationTime;
614 }
615
616 void Button::SetLabel( const std::string& label )
617 {
618   Toolkit::TextView textView = Toolkit::TextView::New( label );
619   textView.SetWidthExceedPolicy( Toolkit::TextView::ShrinkToFit ); // Make sure our text always fits inside the button
620   SetLabel( textView );
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