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