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