Merge "Increased test coverage on TextLabel and TextField" into tizen
[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   RelayoutRequest();
679 }
680
681 Actor Button::GetButtonImage() const
682 {
683   return mButtonContent;
684 }
685
686 Actor& Button::GetButtonImage()
687 {
688   return mButtonContent;
689 }
690
691 void Button::SetSelectedImage( Actor image )
692 {
693   StopAllAnimations();
694
695   if( mSelectedContent && mSelectedContent.GetParent() )
696   {
697     Self().Remove( mSelectedContent );
698   }
699
700   mSelectedContent = image;
701
702   mSelectedContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
703   mSelectedContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
704   mSelectedContent.SetPosition( 0.f, 0.f );
705
706   if( mPaintState == SelectedState )
707   {
708     unsigned int index = FindChildIndex( mLabel );
709
710     Self().Insert( index, mSelectedContent );
711   }
712
713   OnSelectedImageSet();
714
715   RelayoutRequest();
716 }
717
718 Actor Button::GetSelectedImage() const
719 {
720   return mSelectedContent;
721 }
722
723 Actor& Button::GetSelectedImage()
724 {
725   return mSelectedContent;
726 }
727
728 void Button::SetBackgroundImage( Actor image )
729 {
730   StopAllAnimations();
731
732   if( mBackgroundContent && mBackgroundContent.GetParent() )
733   {
734     Self().Remove( mBackgroundContent );
735   }
736
737   mBackgroundContent = image;
738
739   mBackgroundContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
740   mBackgroundContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
741   mBackgroundContent.SetPosition( 0.f, 0.f );
742
743   if( mPaintState == UnselectedState || mPaintState == SelectedState )
744   {
745     Self().Insert( 0, mBackgroundContent );
746   }
747
748   OnBackgroundImageSet();
749
750   RelayoutRequest();
751 }
752
753 Actor Button::GetBackgroundImage() const
754 {
755   return mBackgroundContent;
756 }
757
758 Actor& Button::GetBackgroundImage()
759 {
760   return mBackgroundContent;
761 }
762
763 void Button::SetSelectedBackgroundImage( Actor image )
764 {
765   StopAllAnimations();
766
767   if( mSelectedBackgroundContent && mSelectedBackgroundContent.GetParent() )
768   {
769     Self().Remove( mSelectedBackgroundContent );
770   }
771
772   mSelectedBackgroundContent = image;
773
774   mSelectedBackgroundContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
775   mSelectedBackgroundContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
776   mSelectedBackgroundContent.SetPosition( 0.f, 0.f );
777
778   if( mPaintState == SelectedState )
779   {
780     if( mBackgroundContent )
781     {
782       Self().Insert( 1, mSelectedBackgroundContent );
783     }
784     else
785     {
786       Self().Insert( 0, mSelectedBackgroundContent );
787     }
788   }
789
790   OnSelectedBackgroundImageSet();
791
792   RelayoutRequest();
793 }
794
795 Actor Button::GetSelectedBackgroundImage() const
796 {
797   return mSelectedBackgroundContent;
798 }
799
800 Actor& Button::GetSelectedBackgroundImage()
801 {
802   return mSelectedBackgroundContent;
803 }
804
805 void Button::SetDisabledImage( Actor image )
806 {
807   StopAllAnimations();
808
809   if( mDisabledContent && mDisabledContent.GetParent() )
810   {
811     Self().Remove( mDisabledContent );
812   }
813
814   mDisabledContent = image;
815
816   mDisabledContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
817   mDisabledContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
818   mDisabledContent.SetPosition( 0.f, 0.f );
819
820   if( mPaintState == DisabledUnselectedState || mPaintState == DisabledSelectedState )
821   {
822     unsigned int index = FindChildIndex( mLabel );
823
824     Self().Insert( index, mDisabledContent );
825   }
826
827   OnDisabledImageSet();
828 }
829
830 Actor Button::GetDisabledImage() const
831 {
832   return mDisabledContent;
833 }
834
835 Actor& Button::GetDisabledImage()
836 {
837   return mDisabledContent;
838 }
839
840 void Button::SetDisabledSelectedImage( Actor image )
841 {
842   StopAllAnimations();
843
844   if( mDisabledSelectedContent && mDisabledSelectedContent.GetParent() )
845   {
846     Self().Remove( mDisabledSelectedContent );
847   }
848
849   mDisabledSelectedContent = image;
850
851   mDisabledSelectedContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
852   mDisabledSelectedContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
853   mDisabledSelectedContent.SetPosition( 0.f, 0.f );
854
855   if( mPaintState == DisabledSelectedState )
856   {
857     unsigned int index = FindChildIndex( mLabel );
858
859     Self().Insert( index, mDisabledSelectedContent );
860   }
861
862   OnDisabledSelectedImageSet();
863 }
864
865 Actor Button::GetDisabledSelectedImage() const
866 {
867   return mDisabledSelectedContent;
868 }
869
870 Actor& Button::GetDisabledSelectedImage()
871 {
872   return mDisabledSelectedContent;
873 }
874
875 void Button::SetDisabledBackgroundImage( Actor image )
876 {
877   StopAllAnimations();
878
879   if( mDisabledBackgroundContent && mDisabledBackgroundContent.GetParent() )
880   {
881     Self().Remove( mDisabledBackgroundContent );
882   }
883
884   mDisabledBackgroundContent = image;
885
886   mDisabledBackgroundContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
887   mDisabledBackgroundContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
888   mDisabledBackgroundContent.SetPosition( 0.f, 0.f );
889
890   if( mPaintState == DisabledUnselectedState || mPaintState == DisabledSelectedState )
891   {
892     Self().Insert( 0, mDisabledBackgroundContent );
893   }
894
895   OnDisabledBackgroundImageSet();
896 }
897
898 Actor Button::GetDisabledBackgroundImage() const
899 {
900   return mDisabledBackgroundContent;
901 }
902
903 Actor& Button::GetDisabledBackgroundImage()
904 {
905   return mDisabledBackgroundContent;
906 }
907
908 bool Button::DoAction( BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes )
909 {
910   bool ret = false;
911
912   Dali::BaseHandle handle( object );
913
914   Toolkit::Button button = Toolkit::Button::DownCast( handle );
915
916   DALI_ASSERT_ALWAYS( button );
917
918   if( 0 == strcmp( actionName.c_str(), ACTION_BUTTON_CLICK ) )
919   {
920     GetImplementation( button ).DoClickAction( attributes );
921     ret = true;
922   }
923
924   return ret;
925 }
926
927 void Button::DoClickAction( const PropertyValueContainer& attributes )
928 {
929   // Prevents the button signals from doing a recursive loop by sending an action
930   // and re-emitting the signals.
931   if( !mClickActionPerforming )
932   {
933     mClickActionPerforming = true;
934     OnButtonDown();
935     mState = ButtonDown;
936     OnButtonUp();
937     mClickActionPerforming = false;
938   }
939 }
940
941 void Button::UpdatePaintTransitionState()
942 {
943   switch( mPaintState )
944   {
945     case UnselectedSelectedTransition:
946     {
947       RemoveChild( mButtonContent );
948       mPaintState = SelectedState;
949       break;
950     }
951     case SelectedUnselectedTransition:
952     {
953       RemoveChild( mSelectedBackgroundContent );
954       RemoveChild( mSelectedContent );
955       mPaintState = UnselectedState;
956       break;
957     }
958     case UnselectedDisabledTransition:
959     {
960       RemoveChild( mBackgroundContent );
961       RemoveChild( mButtonContent );
962       mPaintState = DisabledUnselectedState;
963       break;
964     }
965     case DisabledUnselectedTransition:
966     {
967       RemoveChild( mDisabledBackgroundContent );
968       RemoveChild( mDisabledContent );
969       mPaintState = UnselectedState;
970       break;
971     }
972     case SelectedDisabledTransition:
973     {
974       RemoveChild( mBackgroundContent );
975       RemoveChild( mSelectedBackgroundContent );
976       RemoveChild( mSelectedContent );
977       mPaintState = DisabledSelectedState;
978       break;
979     }
980     case DisabledSelectedTransition:
981     {
982       RemoveChild( mDisabledBackgroundContent );
983       RemoveChild( mDisabledSelectedContent );
984       mPaintState = SelectedState;
985       break;
986     }
987     default:
988     {
989       break;
990     }
991   }
992 }
993
994 void Button::OnButtonStageDisconnection()
995 {
996   if( ButtonDown == mState )
997   {
998     if( !mTogglableButton )
999     {
1000       Released();
1001
1002       if( mAutoRepeating )
1003       {
1004         mAutoRepeatingTimer.Reset();
1005       }
1006     }
1007   }
1008 }
1009
1010 void Button::OnButtonDown()
1011 {
1012   if( !mTogglableButton )
1013   {
1014     Toolkit::Button handle( GetOwner() );
1015
1016     Pressed();
1017
1018     if( mAutoRepeating )
1019     {
1020       SetUpTimer( mInitialAutoRepeatingDelay );
1021     }
1022
1023     //Emit signal.
1024     mPressedSignal.Emit( handle );
1025   }
1026 }
1027
1028 void Button::OnButtonUp()
1029 {
1030   if( ButtonDown == mState )
1031   {
1032     if( mTogglableButton )
1033     {
1034       SetSelected( !mSelected );
1035     }
1036     else
1037     {
1038       Released();
1039
1040       if( mAutoRepeating )
1041       {
1042         mAutoRepeatingTimer.Reset();
1043       }
1044
1045       Toolkit::Button handle( GetOwner() );
1046
1047       //Emit signal.
1048       mReleasedSignal.Emit( handle );
1049       mClickedSignal.Emit( handle );
1050     }
1051   }
1052 }
1053
1054 void Button::OnTouchPointLeave()
1055 {
1056   if( ButtonDown == mState )
1057   {
1058     if( !mTogglableButton )
1059     {
1060       Toolkit::Button handle( GetOwner() );
1061
1062       Released();
1063
1064       if( mAutoRepeating )
1065       {
1066         mAutoRepeatingTimer.Reset();
1067       }
1068
1069       //Emit signal.
1070       mReleasedSignal.Emit( handle );
1071     }
1072   }
1073 }
1074
1075 void Button::OnTouchPointInterrupted()
1076 {
1077   OnTouchPointLeave();
1078 }
1079
1080 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
1081 {
1082   return mPressedSignal;
1083 }
1084
1085 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
1086 {
1087   return mReleasedSignal;
1088 }
1089
1090 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
1091 {
1092   return mClickedSignal;
1093 }
1094
1095 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
1096 {
1097   return mStateChangedSignal;
1098 }
1099
1100 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1101 {
1102   Dali::BaseHandle handle( object );
1103
1104   bool connected( true );
1105   Toolkit::Button button = Toolkit::Button::DownCast( handle );
1106
1107   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
1108   {
1109     button.PressedSignal().Connect( tracker, functor );
1110   }
1111   else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
1112   {
1113     button.ReleasedSignal().Connect( tracker, functor );
1114   }
1115   else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
1116   {
1117     button.ClickedSignal().Connect( tracker, functor );
1118   }
1119   else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
1120   {
1121     button.StateChangedSignal().Connect( tracker, functor );
1122   }
1123   else
1124   {
1125     // signalName does not match any signal
1126     connected = false;
1127   }
1128
1129   return connected;
1130 }
1131
1132 bool Button::OnTouchEvent(const TouchEvent& event)
1133 {
1134   // Only events are processed when the button is not disabled and the touch event has only
1135   // one touch point.
1136   if( ( !mDisabled ) && ( 1 == event.GetPointCount() ) )
1137   {
1138     switch( event.GetPoint(0).state )
1139     {
1140       case TouchPoint::Down:
1141       {
1142         OnButtonDown(); // Notification for derived classes.
1143
1144         // Sets the button state to ButtonDown.
1145         mState = ButtonDown;
1146         break;
1147       }
1148       case TouchPoint::Up:
1149       {
1150         OnButtonUp(); // Notification for derived classes.
1151
1152         // Sets the button state to ButtonUp.
1153         mState = ButtonUp;
1154         break;
1155       }
1156       case TouchPoint::Interrupted:
1157       {
1158         OnTouchPointInterrupted(); // Notification for derived classes.
1159
1160         // Sets the button state to the default (ButtonUp).
1161         mState = ButtonUp;
1162         break;
1163       }
1164       case TouchPoint::Leave:
1165       {
1166         OnTouchPointLeave(); // Notification for derived classes.
1167
1168         // Sets the button state to the default (ButtonUp).
1169         mState = ButtonUp;
1170         break;
1171       }
1172       case TouchPoint::Motion:
1173       case TouchPoint::Stationary: // FALLTHROUGH
1174       {
1175         // Nothing to do
1176         break;
1177       }
1178       default:
1179       {
1180         DALI_ASSERT_ALWAYS( !"Point status unhandled." );
1181         break;
1182       }
1183     }
1184   }
1185   else if( 1 < event.GetPointCount() )
1186   {
1187     OnTouchPointLeave(); // Notification for derived classes.
1188
1189     // Sets the button state to the default (ButtonUp).
1190     mState = ButtonUp;
1191   }
1192
1193   return false;
1194 }
1195
1196 void Button::OnInitialize()
1197 {
1198   Actor self = Self();
1199
1200   mTapDetector = TapGestureDetector::New();
1201   mTapDetector.Attach( self );
1202   mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
1203
1204   OnButtonInitialize();
1205
1206   self.SetDrawMode( DrawMode::OVERLAY );
1207   self.SetKeyboardFocusable( true );
1208 }
1209
1210 void Button::OnActivated()
1211 {
1212   // When the button is activated, it performs the click action
1213   PropertyValueContainer attributes;
1214   DoClickAction( attributes );
1215 }
1216
1217 void Button::OnControlStageDisconnection()
1218 {
1219   OnButtonStageDisconnection(); // Notification for derived classes.
1220   mState = ButtonUp;
1221 }
1222
1223 void Button::OnTap(Actor actor, const TapGesture& tap)
1224 {
1225   // Do nothing.
1226 }
1227
1228 void Button::SetUpTimer( float delay )
1229 {
1230   mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
1231   mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
1232   mAutoRepeatingTimer.Start();
1233 }
1234
1235 bool Button::AutoRepeatingSlot()
1236 {
1237   bool consumed = false;
1238   if( !mDisabled )
1239   {
1240     // Restart the autorepeat timer.
1241     SetUpTimer( mNextAutoRepeatingDelay );
1242
1243     Pressed();
1244
1245     Toolkit::Button handle( GetOwner() );
1246
1247     //Emit signal.
1248     consumed = mReleasedSignal.Emit( handle );
1249     consumed |= mClickedSignal.Emit( handle );
1250     consumed |= mPressedSignal.Emit( handle );
1251  }
1252
1253   return consumed;
1254 }
1255
1256 void Button::Pressed()
1257 {
1258   unsigned int buttonIndex, backgroundIndex;
1259   bool animationStarted = false;
1260
1261   switch( mPaintState )
1262   {
1263     case UnselectedState:
1264     {
1265       buttonIndex = FindChildIndex( mLabel );
1266       InsertChild( buttonIndex, mSelectedContent );
1267
1268       if( mBackgroundContent )
1269       {
1270         backgroundIndex = 1;
1271       }
1272       else
1273       {
1274         backgroundIndex = 0;
1275       }
1276
1277       InsertChild( backgroundIndex, mSelectedBackgroundContent );
1278
1279       // Notifies the derived class the button has been pressed.
1280       animationStarted = OnPressed();
1281
1282       if( animationStarted )
1283       {
1284         mPaintState = UnselectedSelectedTransition;
1285       }
1286       else
1287       {
1288         mPaintState = SelectedState;
1289       }
1290       break;
1291     }
1292     case SelectedUnselectedTransition:
1293     {
1294       // Notifies the derived class the button has been pressed.
1295       animationStarted = OnPressed();
1296
1297       if( animationStarted )
1298       {
1299         mPaintState = UnselectedSelectedTransition;
1300       }
1301       else
1302       {
1303         mPaintState = SelectedState;
1304       }
1305       break;
1306     }
1307     case DisabledUnselectedTransition:
1308     {
1309       buttonIndex = FindChildIndex( mLabel );
1310       InsertChild( buttonIndex, mSelectedContent );
1311
1312       if( mDisabledBackgroundContent )
1313       {
1314         if(  mBackgroundContent )
1315         {
1316           backgroundIndex = 2;
1317         }
1318         else
1319         {
1320           backgroundIndex = 1;
1321         }
1322       }
1323       else if( mBackgroundContent )
1324       {
1325         backgroundIndex = 1;
1326       }
1327       else
1328       {
1329         backgroundIndex = 0;
1330       }
1331
1332       InsertChild( backgroundIndex, mSelectedBackgroundContent );
1333
1334       // Notifies the derived class the button has been pressed.
1335       animationStarted = OnPressed();
1336
1337       if( animationStarted )
1338       {
1339         mPaintState = UnselectedSelectedTransition;
1340       }
1341       else
1342       {
1343         mPaintState = SelectedState;
1344       }
1345       break;
1346     }
1347     default:
1348       break;
1349   }
1350 }
1351
1352 void Button::Released()
1353 {
1354   unsigned int buttonIndex;
1355   bool animationStarted = false;
1356
1357   switch( mPaintState )
1358   {
1359     case SelectedState:
1360     {
1361       buttonIndex = FindChildIndex( mLabel );
1362       InsertChild( buttonIndex, mButtonContent );
1363
1364       // Notifies the derived class the button has been released.
1365       animationStarted = OnReleased();
1366
1367       if( animationStarted )
1368       {
1369         mPaintState = SelectedUnselectedTransition;
1370       }
1371       else
1372       {
1373         mPaintState = UnselectedState;
1374       }
1375       break;
1376     }
1377     case UnselectedSelectedTransition:
1378     {
1379       // Notifies the derived class the button has been released.
1380       animationStarted = OnReleased();
1381
1382       if( animationStarted )
1383       {
1384         mPaintState = SelectedUnselectedTransition;
1385       }
1386       else
1387       {
1388         mPaintState = UnselectedState;
1389       }
1390       break;
1391     }
1392     case DisabledSelectedTransition:
1393     {
1394       buttonIndex = FindChildIndex( mLabel );
1395       InsertChild( buttonIndex, mButtonContent );
1396
1397       // Notifies the derived class the button has been released.
1398       animationStarted = OnReleased();
1399
1400       if( animationStarted )
1401       {
1402         mPaintState = SelectedUnselectedTransition;
1403       }
1404       else
1405       {
1406         mPaintState = UnselectedState;
1407       }
1408       break;
1409     }
1410     default:
1411     {
1412       break;
1413     }
1414   }
1415 }
1416
1417 Button::ButtonState Button::GetState()
1418 {
1419   return mState;
1420 }
1421
1422 Button::PaintState Button::GetPaintState()
1423 {
1424   return mPaintState;
1425 }
1426
1427 void Button::InsertChild( unsigned int index, Actor& actor )
1428 {
1429   if( actor )
1430   {
1431     Self().Insert( index, actor);
1432   }
1433 }
1434
1435 void Button::RemoveChild( Actor& actor )
1436 {
1437   if( actor && actor.GetParent() )
1438   {
1439     Self().Remove( actor );
1440   }
1441 }
1442
1443 unsigned int Button::FindChildIndex( Actor& actor )
1444 {
1445   Actor self = Self();
1446   unsigned int childrenNum = self.GetChildCount();
1447
1448   for( unsigned int i = 0; i < childrenNum; i++ )
1449   {
1450     Actor child = self.GetChildAt( i );
1451     if( child == actor )
1452     {
1453       return i;
1454     }
1455   }
1456
1457   return childrenNum;
1458 }
1459
1460 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
1461 {
1462   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1463
1464   if ( button )
1465   {
1466     switch ( index )
1467     {
1468       case Toolkit::Button::Property::DISABLED:
1469       {
1470         GetImplementation( button ).SetDisabled( value.Get<bool>() );
1471         break;
1472       }
1473
1474       case Toolkit::Button::Property::AUTO_REPEATING:
1475       {
1476         GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
1477         break;
1478       }
1479
1480       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1481       {
1482         GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
1483         break;
1484       }
1485
1486       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1487       {
1488         GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
1489         break;
1490       }
1491
1492       case Toolkit::Button::Property::TOGGLABLE:
1493       {
1494         GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
1495         break;
1496       }
1497
1498       case Toolkit::Button::Property::SELECTED:
1499       {
1500         GetImplementation( button ).SetSelected( value.Get< bool >() );
1501         break;
1502       }
1503
1504       case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
1505       {
1506         GetImplementation( button ).SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1507         break;
1508       }
1509
1510       case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
1511       {
1512         GetImplementation( button ).SetSelectedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1513         break;
1514       }
1515
1516       case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
1517       {
1518         GetImplementation( button ).SetDisabledImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1519         break;
1520       }
1521
1522       case Toolkit::Button::Property::LABEL_ACTOR:
1523       {
1524         GetImplementation( button ).SetLabel( Scripting::NewActor( value.Get< Property::Map >() ) );
1525         break;
1526       }
1527     }
1528   }
1529 }
1530
1531 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
1532 {
1533   Property::Value value;
1534
1535   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1536
1537   if ( button )
1538   {
1539     switch ( propertyIndex )
1540     {
1541       case Toolkit::Button::Property::DISABLED:
1542       {
1543         value = GetImplementation( button ).mDisabled;
1544         break;
1545       }
1546
1547       case Toolkit::Button::Property::AUTO_REPEATING:
1548       {
1549         value = GetImplementation( button ).mAutoRepeating;
1550         break;
1551       }
1552
1553       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1554       {
1555         value = GetImplementation( button ).mInitialAutoRepeatingDelay;
1556         break;
1557       }
1558
1559       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1560       {
1561         value = GetImplementation( button ).mNextAutoRepeatingDelay;
1562         break;
1563       }
1564
1565       case Toolkit::Button::Property::TOGGLABLE:
1566       {
1567         value = GetImplementation( button ).mTogglableButton;
1568         break;
1569       }
1570
1571       case Toolkit::Button::Property::SELECTED:
1572       {
1573         value = GetImplementation( button ).mSelected;
1574         break;
1575       }
1576
1577       case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
1578       {
1579         Property::Map map;
1580         Scripting::CreatePropertyMap( GetImplementation( button ).mButtonContent, map );
1581         value = map;
1582         break;
1583       }
1584
1585       case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
1586       {
1587         Property::Map map;
1588         Scripting::CreatePropertyMap( GetImplementation( button ).mSelectedContent, map );
1589         value = map;
1590         break;
1591       }
1592
1593       case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
1594       {
1595         Property::Map map;
1596         Scripting::CreatePropertyMap( GetImplementation( button ).mDisabledContent, map );
1597         value = map;
1598         break;
1599       }
1600
1601       case Toolkit::Button::Property::LABEL_ACTOR:
1602       {
1603         Property::Map map;
1604         Scripting::CreatePropertyMap( GetImplementation( button ).mLabel, map );
1605         value = map;
1606         break;
1607       }
1608     }
1609   }
1610
1611   return value;
1612 }
1613
1614 } // namespace Internal
1615
1616 } // namespace Toolkit
1617
1618 } // namespace Dali