OnActivated() change for Accessibility and KeyboardFocus
[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/devel-api/object/type-registry-helper.h>
26 #include <dali/public-api/actors/image-actor.h>
27 #include <dali/devel-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( Toolkit, Button, "disabled",                     BOOLEAN, DISABLED                     )
78 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "auto-repeating",               BOOLEAN, AUTO_REPEATING               )
79 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "initial-auto-repeating-delay", FLOAT,   INITIAL_AUTO_REPEATING_DELAY )
80 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "next-auto-repeating-delay",    FLOAT,   NEXT_AUTO_REPEATING_DELAY    )
81 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "togglable",                    BOOLEAN, TOGGLABLE                    )
82 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selected",                     BOOLEAN, SELECTED                     )
83 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "normal-state-actor",           MAP,     NORMAL_STATE_ACTOR           )
84 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selected-state-actor",         MAP,     SELECTED_STATE_ACTOR         )
85 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabled-state-actor",         MAP,     DISABLED_STATE_ACTOR         )
86 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "label-actor",                  MAP,     LABEL_ACTOR                  )
87
88 DALI_SIGNAL_REGISTRATION(   Toolkit, Button, "pressed",                               SIGNAL_PRESSED               )
89 DALI_SIGNAL_REGISTRATION(   Toolkit, Button, "released",                              SIGNAL_RELEASED              )
90 DALI_SIGNAL_REGISTRATION(   Toolkit, Button, "clicked",                               SIGNAL_CLICKED               )
91 DALI_SIGNAL_REGISTRATION(   Toolkit, Button, "state-changed",                         SIGNAL_STATE_CHANGED         )
92
93 DALI_ACTION_REGISTRATION(   Toolkit, 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 Property::Map& 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     ret = GetImplementation( button ).DoClickAction( attributes );
921   }
922
923   return ret;
924 }
925
926 bool Button::DoClickAction( const Property::Map& attributes )
927 {
928   // Prevents the button signals from doing a recursive loop by sending an action
929   // and re-emitting the signals.
930   if( !mClickActionPerforming )
931   {
932     mClickActionPerforming = true;
933     OnButtonDown();
934     mState = ButtonDown;
935     OnButtonUp();
936     mClickActionPerforming = false;
937
938     return true;
939   }
940
941   return false;
942 }
943
944 void Button::UpdatePaintTransitionState()
945 {
946   switch( mPaintState )
947   {
948     case UnselectedSelectedTransition:
949     {
950       RemoveChild( mButtonContent );
951       mPaintState = SelectedState;
952       break;
953     }
954     case SelectedUnselectedTransition:
955     {
956       RemoveChild( mSelectedBackgroundContent );
957       RemoveChild( mSelectedContent );
958       mPaintState = UnselectedState;
959       break;
960     }
961     case UnselectedDisabledTransition:
962     {
963       RemoveChild( mBackgroundContent );
964       RemoveChild( mButtonContent );
965       mPaintState = DisabledUnselectedState;
966       break;
967     }
968     case DisabledUnselectedTransition:
969     {
970       RemoveChild( mDisabledBackgroundContent );
971       RemoveChild( mDisabledContent );
972       mPaintState = UnselectedState;
973       break;
974     }
975     case SelectedDisabledTransition:
976     {
977       RemoveChild( mBackgroundContent );
978       RemoveChild( mSelectedBackgroundContent );
979       RemoveChild( mSelectedContent );
980       mPaintState = DisabledSelectedState;
981       break;
982     }
983     case DisabledSelectedTransition:
984     {
985       RemoveChild( mDisabledBackgroundContent );
986       RemoveChild( mDisabledSelectedContent );
987       mPaintState = SelectedState;
988       break;
989     }
990     default:
991     {
992       break;
993     }
994   }
995 }
996
997 void Button::OnButtonStageDisconnection()
998 {
999   if( ButtonDown == mState )
1000   {
1001     if( !mTogglableButton )
1002     {
1003       Released();
1004
1005       if( mAutoRepeating )
1006       {
1007         mAutoRepeatingTimer.Reset();
1008       }
1009     }
1010   }
1011 }
1012
1013 void Button::OnButtonDown()
1014 {
1015   if( !mTogglableButton )
1016   {
1017     Toolkit::Button handle( GetOwner() );
1018
1019     Pressed();
1020
1021     if( mAutoRepeating )
1022     {
1023       SetUpTimer( mInitialAutoRepeatingDelay );
1024     }
1025
1026     //Emit signal.
1027     mPressedSignal.Emit( handle );
1028   }
1029 }
1030
1031 void Button::OnButtonUp()
1032 {
1033   if( ButtonDown == mState )
1034   {
1035     if( mTogglableButton )
1036     {
1037       SetSelected( !mSelected );
1038     }
1039     else
1040     {
1041       Released();
1042
1043       if( mAutoRepeating )
1044       {
1045         mAutoRepeatingTimer.Reset();
1046       }
1047
1048       Toolkit::Button handle( GetOwner() );
1049
1050       //Emit signal.
1051       mReleasedSignal.Emit( handle );
1052       mClickedSignal.Emit( handle );
1053     }
1054   }
1055 }
1056
1057 void Button::OnTouchPointLeave()
1058 {
1059   if( ButtonDown == mState )
1060   {
1061     if( !mTogglableButton )
1062     {
1063       Toolkit::Button handle( GetOwner() );
1064
1065       Released();
1066
1067       if( mAutoRepeating )
1068       {
1069         mAutoRepeatingTimer.Reset();
1070       }
1071
1072       //Emit signal.
1073       mReleasedSignal.Emit( handle );
1074     }
1075   }
1076 }
1077
1078 void Button::OnTouchPointInterrupted()
1079 {
1080   OnTouchPointLeave();
1081 }
1082
1083 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
1084 {
1085   return mPressedSignal;
1086 }
1087
1088 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
1089 {
1090   return mReleasedSignal;
1091 }
1092
1093 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
1094 {
1095   return mClickedSignal;
1096 }
1097
1098 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
1099 {
1100   return mStateChangedSignal;
1101 }
1102
1103 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1104 {
1105   Dali::BaseHandle handle( object );
1106
1107   bool connected( true );
1108   Toolkit::Button button = Toolkit::Button::DownCast( handle );
1109
1110   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
1111   {
1112     button.PressedSignal().Connect( tracker, functor );
1113   }
1114   else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
1115   {
1116     button.ReleasedSignal().Connect( tracker, functor );
1117   }
1118   else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
1119   {
1120     button.ClickedSignal().Connect( tracker, functor );
1121   }
1122   else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
1123   {
1124     button.StateChangedSignal().Connect( tracker, functor );
1125   }
1126   else
1127   {
1128     // signalName does not match any signal
1129     connected = false;
1130   }
1131
1132   return connected;
1133 }
1134
1135 bool Button::OnTouchEvent(const TouchEvent& event)
1136 {
1137   // Only events are processed when the button is not disabled and the touch event has only
1138   // one touch point.
1139   if( ( !mDisabled ) && ( 1 == event.GetPointCount() ) )
1140   {
1141     switch( event.GetPoint(0).state )
1142     {
1143       case TouchPoint::Down:
1144       {
1145         OnButtonDown(); // Notification for derived classes.
1146
1147         // Sets the button state to ButtonDown.
1148         mState = ButtonDown;
1149         break;
1150       }
1151       case TouchPoint::Up:
1152       {
1153         OnButtonUp(); // Notification for derived classes.
1154
1155         // Sets the button state to ButtonUp.
1156         mState = ButtonUp;
1157         break;
1158       }
1159       case TouchPoint::Interrupted:
1160       {
1161         OnTouchPointInterrupted(); // Notification for derived classes.
1162
1163         // Sets the button state to the default (ButtonUp).
1164         mState = ButtonUp;
1165         break;
1166       }
1167       case TouchPoint::Leave:
1168       {
1169         OnTouchPointLeave(); // Notification for derived classes.
1170
1171         // Sets the button state to the default (ButtonUp).
1172         mState = ButtonUp;
1173         break;
1174       }
1175       case TouchPoint::Motion:
1176       case TouchPoint::Stationary: // FALLTHROUGH
1177       {
1178         // Nothing to do
1179         break;
1180       }
1181       default:
1182       {
1183         DALI_ASSERT_ALWAYS( !"Point status unhandled." );
1184         break;
1185       }
1186     }
1187   }
1188   else if( 1 < event.GetPointCount() )
1189   {
1190     OnTouchPointLeave(); // Notification for derived classes.
1191
1192     // Sets the button state to the default (ButtonUp).
1193     mState = ButtonUp;
1194   }
1195
1196   return false;
1197 }
1198
1199 void Button::OnInitialize()
1200 {
1201   Actor self = Self();
1202
1203   mTapDetector = TapGestureDetector::New();
1204   mTapDetector.Attach( self );
1205   mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
1206
1207   OnButtonInitialize();
1208
1209   self.SetKeyboardFocusable( true );
1210 }
1211
1212 bool Button::OnAccessibilityActivated()
1213 {
1214   return OnKeyboardEnter();
1215 }
1216
1217 bool Button::OnKeyboardEnter()
1218 {
1219   // When the enter key is pressed, or button is activated, the click action is performed.
1220   Property::Map attributes;
1221   bool ret = DoClickAction( attributes );
1222
1223   return ret;
1224 }
1225
1226 void Button::OnControlStageDisconnection()
1227 {
1228   OnButtonStageDisconnection(); // Notification for derived classes.
1229   mState = ButtonUp;
1230 }
1231
1232 void Button::OnTap(Actor actor, const TapGesture& tap)
1233 {
1234   // Do nothing.
1235 }
1236
1237 void Button::SetUpTimer( float delay )
1238 {
1239   mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
1240   mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
1241   mAutoRepeatingTimer.Start();
1242 }
1243
1244 bool Button::AutoRepeatingSlot()
1245 {
1246   bool consumed = false;
1247   if( !mDisabled )
1248   {
1249     // Restart the autorepeat timer.
1250     SetUpTimer( mNextAutoRepeatingDelay );
1251
1252     Pressed();
1253
1254     Toolkit::Button handle( GetOwner() );
1255
1256     //Emit signal.
1257     consumed = mReleasedSignal.Emit( handle );
1258     consumed |= mClickedSignal.Emit( handle );
1259     consumed |= mPressedSignal.Emit( handle );
1260  }
1261
1262   return consumed;
1263 }
1264
1265 void Button::Pressed()
1266 {
1267   unsigned int buttonIndex, backgroundIndex;
1268   bool animationStarted = false;
1269
1270   switch( mPaintState )
1271   {
1272     case UnselectedState:
1273     {
1274       buttonIndex = FindChildIndex( mLabel );
1275       InsertChild( buttonIndex, mSelectedContent );
1276
1277       if( mBackgroundContent )
1278       {
1279         backgroundIndex = 1;
1280       }
1281       else
1282       {
1283         backgroundIndex = 0;
1284       }
1285
1286       InsertChild( backgroundIndex, mSelectedBackgroundContent );
1287
1288       // Notifies the derived class the button has been pressed.
1289       animationStarted = OnPressed();
1290
1291       if( animationStarted )
1292       {
1293         mPaintState = UnselectedSelectedTransition;
1294       }
1295       else
1296       {
1297         mPaintState = SelectedState;
1298       }
1299       break;
1300     }
1301     case SelectedUnselectedTransition:
1302     {
1303       // Notifies the derived class the button has been pressed.
1304       animationStarted = OnPressed();
1305
1306       if( animationStarted )
1307       {
1308         mPaintState = UnselectedSelectedTransition;
1309       }
1310       else
1311       {
1312         mPaintState = SelectedState;
1313       }
1314       break;
1315     }
1316     case DisabledUnselectedTransition:
1317     {
1318       buttonIndex = FindChildIndex( mLabel );
1319       InsertChild( buttonIndex, mSelectedContent );
1320
1321       if( mDisabledBackgroundContent )
1322       {
1323         if(  mBackgroundContent )
1324         {
1325           backgroundIndex = 2;
1326         }
1327         else
1328         {
1329           backgroundIndex = 1;
1330         }
1331       }
1332       else if( mBackgroundContent )
1333       {
1334         backgroundIndex = 1;
1335       }
1336       else
1337       {
1338         backgroundIndex = 0;
1339       }
1340
1341       InsertChild( backgroundIndex, mSelectedBackgroundContent );
1342
1343       // Notifies the derived class the button has been pressed.
1344       animationStarted = OnPressed();
1345
1346       if( animationStarted )
1347       {
1348         mPaintState = UnselectedSelectedTransition;
1349       }
1350       else
1351       {
1352         mPaintState = SelectedState;
1353       }
1354       break;
1355     }
1356     default:
1357       break;
1358   }
1359 }
1360
1361 void Button::Released()
1362 {
1363   unsigned int buttonIndex;
1364   bool animationStarted = false;
1365
1366   switch( mPaintState )
1367   {
1368     case SelectedState:
1369     {
1370       buttonIndex = FindChildIndex( mLabel );
1371       InsertChild( buttonIndex, mButtonContent );
1372
1373       // Notifies the derived class the button has been released.
1374       animationStarted = OnReleased();
1375
1376       if( animationStarted )
1377       {
1378         mPaintState = SelectedUnselectedTransition;
1379       }
1380       else
1381       {
1382         mPaintState = UnselectedState;
1383       }
1384       break;
1385     }
1386     case UnselectedSelectedTransition:
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     case DisabledSelectedTransition:
1402     {
1403       buttonIndex = FindChildIndex( mLabel );
1404       InsertChild( buttonIndex, mButtonContent );
1405
1406       // Notifies the derived class the button has been released.
1407       animationStarted = OnReleased();
1408
1409       if( animationStarted )
1410       {
1411         mPaintState = SelectedUnselectedTransition;
1412       }
1413       else
1414       {
1415         mPaintState = UnselectedState;
1416       }
1417       break;
1418     }
1419     default:
1420     {
1421       break;
1422     }
1423   }
1424 }
1425
1426 Button::ButtonState Button::GetState()
1427 {
1428   return mState;
1429 }
1430
1431 Button::PaintState Button::GetPaintState()
1432 {
1433   return mPaintState;
1434 }
1435
1436 void Button::InsertChild( unsigned int index, Actor& actor )
1437 {
1438   if( actor )
1439   {
1440     Self().Insert( index, actor);
1441   }
1442 }
1443
1444 void Button::RemoveChild( Actor& actor )
1445 {
1446   if( actor && actor.GetParent() )
1447   {
1448     Self().Remove( actor );
1449   }
1450 }
1451
1452 unsigned int Button::FindChildIndex( Actor& actor )
1453 {
1454   Actor self = Self();
1455   unsigned int childrenNum = self.GetChildCount();
1456
1457   for( unsigned int i = 0; i < childrenNum; i++ )
1458   {
1459     Actor child = self.GetChildAt( i );
1460     if( child == actor )
1461     {
1462       return i;
1463     }
1464   }
1465
1466   return childrenNum;
1467 }
1468
1469 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
1470 {
1471   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1472
1473   if ( button )
1474   {
1475     switch ( index )
1476     {
1477       case Toolkit::Button::Property::DISABLED:
1478       {
1479         GetImplementation( button ).SetDisabled( value.Get<bool>() );
1480         break;
1481       }
1482
1483       case Toolkit::Button::Property::AUTO_REPEATING:
1484       {
1485         GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
1486         break;
1487       }
1488
1489       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1490       {
1491         GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
1492         break;
1493       }
1494
1495       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1496       {
1497         GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
1498         break;
1499       }
1500
1501       case Toolkit::Button::Property::TOGGLABLE:
1502       {
1503         GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
1504         break;
1505       }
1506
1507       case Toolkit::Button::Property::SELECTED:
1508       {
1509         GetImplementation( button ).SetSelected( value.Get< bool >() );
1510         break;
1511       }
1512
1513       case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
1514       {
1515         GetImplementation( button ).SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1516         break;
1517       }
1518
1519       case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
1520       {
1521         GetImplementation( button ).SetSelectedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1522         break;
1523       }
1524
1525       case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
1526       {
1527         GetImplementation( button ).SetDisabledImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1528         break;
1529       }
1530
1531       case Toolkit::Button::Property::LABEL_ACTOR:
1532       {
1533         GetImplementation( button ).SetLabel( Scripting::NewActor( value.Get< Property::Map >() ) );
1534         break;
1535       }
1536     }
1537   }
1538 }
1539
1540 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
1541 {
1542   Property::Value value;
1543
1544   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1545
1546   if ( button )
1547   {
1548     switch ( propertyIndex )
1549     {
1550       case Toolkit::Button::Property::DISABLED:
1551       {
1552         value = GetImplementation( button ).mDisabled;
1553         break;
1554       }
1555
1556       case Toolkit::Button::Property::AUTO_REPEATING:
1557       {
1558         value = GetImplementation( button ).mAutoRepeating;
1559         break;
1560       }
1561
1562       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1563       {
1564         value = GetImplementation( button ).mInitialAutoRepeatingDelay;
1565         break;
1566       }
1567
1568       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1569       {
1570         value = GetImplementation( button ).mNextAutoRepeatingDelay;
1571         break;
1572       }
1573
1574       case Toolkit::Button::Property::TOGGLABLE:
1575       {
1576         value = GetImplementation( button ).mTogglableButton;
1577         break;
1578       }
1579
1580       case Toolkit::Button::Property::SELECTED:
1581       {
1582         value = GetImplementation( button ).mSelected;
1583         break;
1584       }
1585
1586       case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
1587       {
1588         Property::Map map;
1589         Scripting::CreatePropertyMap( GetImplementation( button ).mButtonContent, map );
1590         value = map;
1591         break;
1592       }
1593
1594       case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
1595       {
1596         Property::Map map;
1597         Scripting::CreatePropertyMap( GetImplementation( button ).mSelectedContent, map );
1598         value = map;
1599         break;
1600       }
1601
1602       case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
1603       {
1604         Property::Map map;
1605         Scripting::CreatePropertyMap( GetImplementation( button ).mDisabledContent, map );
1606         value = map;
1607         break;
1608       }
1609
1610       case Toolkit::Button::Property::LABEL_ACTOR:
1611       {
1612         Property::Map map;
1613         Scripting::CreatePropertyMap( GetImplementation( button ).mLabel, map );
1614         value = map;
1615         break;
1616       }
1617     }
1618   }
1619
1620   return value;
1621 }
1622
1623 } // namespace Internal
1624
1625 } // namespace Toolkit
1626
1627 } // namespace Dali