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