Refactored Button and derived classes, moving state change and transition logic to...
[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) mUnselectedContent                 (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  *   |       mUnselectedContent / 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 }
121
122 void Button::SetDisabled( bool disabled )
123 {
124   if( disabled == mDisabled )
125   {
126     return;
127   }
128
129   StopTransitionAnimation();
130
131   mDisabled = disabled;
132
133   // Notifies the derived class the button has been disabled.
134   OnDisabled();
135
136   switch( mPaintState )
137   {
138     case UnselectedState:
139     {
140       //Layer Order
141       //(3) mDisabledContent (Inserted)
142       //(4) mUnselectedContent
143       //(2) mDisabledBackgroundContent (Inserted)
144       //(1) mBackgroundContent
145
146       TransitionInBetween( mUnselectedContent, mLabel, mDisabledContent );
147       TransitionInAbove( mBackgroundContent, mDisabledBackgroundContent );
148
149       TransitionOut( mUnselectedContent );
150       TransitionOut( mSelectedContent );
151       TransitionOut( mBackgroundContent );
152       TransitionOut( mSelectedBackgroundContent );
153       TransitionOut( mDisabledSelectedContent );
154
155       mPaintState = DisabledUnselectedState;
156       break;
157     }
158     case SelectedState:
159     {
160       //Layer Order
161       //(5) mDisabledSelectedContent (Inserted)
162       //(4) mSelectedContent
163       //(3) mDisabledBackgroundContent (Inserted)
164       //(2) mSelectedBackgroundContent
165       //(1) mBackgroundContent
166
167       TransitionInBetween( mSelectedContent, mLabel, mDisabledSelectedContent );
168       TransitionInAbove( mSelectedBackgroundContent, mDisabledBackgroundContent );
169
170       TransitionOut( mUnselectedContent );
171       TransitionOut( mSelectedContent );
172       TransitionOut( mBackgroundContent );
173       TransitionOut( mSelectedBackgroundContent );
174       TransitionOut( mDisabledContent );
175
176       mPaintState = DisabledSelectedState;
177       break;
178     }
179     case DisabledUnselectedState:
180     {
181       //Layer Order
182       //(3) mUnselectedContent (Inserted)
183       //(4) mDisabledContent
184       //(2) mBackgroundContent (Inserted)
185       //(1) mDisabledBackgroundContent
186
187       TransitionInBetween( mDisabledContent, mLabel, mUnselectedContent );
188       TransitionInAbove( mDisabledBackgroundContent, mBackgroundContent );
189
190       TransitionOut( mSelectedContent );
191       TransitionOut( mSelectedBackgroundContent );
192       TransitionOut( mDisabledContent );
193       TransitionOut( mDisabledSelectedContent );
194       TransitionOut( mDisabledBackgroundContent );
195
196       mPaintState = UnselectedState;
197       break;
198     }
199     case DisabledSelectedState:
200     {
201       //Layer Order
202       //(4) mSelectedContent (Inserted)
203       //(5) mDisabledSelectedContent
204       //(3) mSelectedBackgroundContent (Inserted)
205       //(2) mBackgroundContent (Inserted)
206       //(1) mDisabledBackgroundContent
207
208       TransitionInBetween( mDisabledSelectedContent, mLabel, mSelectedContent );
209       TransitionInAbove( mDisabledBackgroundContent, mSelectedBackgroundContent );
210       TransitionInAbove( mDisabledBackgroundContent, mBackgroundContent );
211
212       TransitionOut( mUnselectedContent );
213       TransitionOut( mDisabledContent );
214       TransitionOut( mDisabledSelectedContent );
215       TransitionOut( mDisabledBackgroundContent );
216
217       mPaintState = SelectedState;
218       break;
219     }
220   }
221
222   StartTransitionAnimation();
223 }
224
225 bool Button::IsDisabled() const
226 {
227   return mDisabled;
228 }
229
230 void Button::SetAutoRepeating( bool autoRepeating )
231 {
232   mAutoRepeating = autoRepeating;
233
234   // An autorepeating button can't be a togglable button.
235   if( autoRepeating )
236   {
237     mTogglableButton = false;
238
239     if( mSelected )
240     {
241       // Emit a signal is not wanted, only change the appearance.
242       SetSelected( false, false );
243     }
244   }
245 }
246
247 bool Button::IsAutoRepeating() const
248 {
249   return mAutoRepeating;
250 }
251
252 void Button::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
253 {
254   DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
255   mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
256 }
257
258 float Button::GetInitialAutoRepeatingDelay() const
259 {
260   return mInitialAutoRepeatingDelay;
261 }
262
263 void Button::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
264 {
265   DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
266   mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
267 }
268
269 float Button::GetNextAutoRepeatingDelay() const
270 {
271   return mNextAutoRepeatingDelay;
272 }
273
274 void Button::SetTogglableButton( bool togglable )
275 {
276   mTogglableButton = togglable;
277
278   // A togglable button can't be an autorepeating button.
279   if( togglable )
280   {
281     mAutoRepeating = false;
282   }
283 }
284
285 bool Button::IsTogglableButton() const
286 {
287   return mTogglableButton;
288 }
289
290 void Button::SetSelected( bool selected )
291 {
292   if( !mDisabled && mTogglableButton && ( selected != mSelected ) )
293   {
294     SetSelected( selected, true );
295   }
296 }
297
298 void Button::SetSelected( bool selected, bool emitSignal )
299 {
300   StopTransitionAnimation();
301
302   mSelected = selected;
303
304   // Notifies the derived class the button has been selected.
305   OnSelected();
306
307   switch( mPaintState )
308   {
309     case UnselectedState:
310     {
311       //Layer Order
312       //(3) mSelectedContent (Inserted)
313       //(4) mUnselectedContent
314       //(2) mSelectedBackgroundContent (Inserted)
315       //(1) mBackgroundContent
316
317       TransitionInBetween( mUnselectedContent, mLabel, mSelectedContent );
318       TransitionInAbove( mBackgroundContent, mSelectedBackgroundContent );
319       TransitionInAtIndex( 0, mBackgroundContent );
320
321       TransitionOut( mUnselectedContent );
322       TransitionOut( mDisabledContent );
323       TransitionOut( mDisabledSelectedContent );
324       TransitionOut( mDisabledBackgroundContent );
325
326       mPaintState = SelectedState;
327       break;
328     }
329     case SelectedState:
330     {
331       //Layer Order
332       //(3) mUnselectedContent (Inserted)
333       //(2) mSelectedContent
334       //(1) mBackgroundContent
335
336       TransitionInBetween( mSelectedContent, mLabel, mUnselectedContent );
337       TransitionInAtIndex( 0, mBackgroundContent );
338
339       TransitionOut( mSelectedContent );
340       TransitionOut( mSelectedBackgroundContent );
341       TransitionOut( mDisabledContent );
342       TransitionOut( mDisabledSelectedContent );
343       TransitionOut( mDisabledBackgroundContent );
344
345       mPaintState = UnselectedState;
346       break;
347     }
348     case DisabledUnselectedState:
349     case DisabledSelectedState:
350     {
351       DALI_ASSERT_DEBUG( 0 && "Shouldn't be able to change paint state if the button is disabled." );
352       break;
353     }
354   }
355
356   StartTransitionAnimation();
357
358   if( emitSignal )
359   {
360     Toolkit::Button handle( GetOwner() );
361
362     // Emit signal.
363     mStateChangedSignal.Emit( handle );
364   }
365
366   RelayoutRequest();
367 }
368
369 bool Button::IsSelected() const
370 {
371   return mTogglableButton && mSelected;
372 }
373
374 void Button::SetAnimationTime( float animationTime )
375 {
376   mAnimationTime = animationTime;
377 }
378
379 float Button::GetAnimationTime() const
380 {
381   return mAnimationTime;
382 }
383
384 void Button::SetLabel( const std::string& label )
385 {
386   Toolkit::TextLabel textLabel = Toolkit::TextLabel::New( label );
387   SetLabel( textLabel );
388 }
389
390 void Button::SetLabel( Actor label )
391 {
392   if( mLabel != label )
393   {
394     if( mLabel && mLabel.GetParent() )
395     {
396       mLabel.GetParent().Remove( mLabel );
397     }
398
399     mLabel = label;
400     mLabel.SetPosition( 0.f, 0.f );
401
402     // label should be the top of the button
403     Self().Add( mLabel );
404
405     OnLabelSet();
406
407     RelayoutRequest();
408   }
409 }
410
411 Actor Button::GetLabel() const
412 {
413   return mLabel;
414 }
415
416 Actor& Button::GetLabel()
417 {
418   return mLabel;
419 }
420
421 void Button::SetButtonImage( Actor image )
422 {
423   StopTransitionAnimation();
424
425   if( mUnselectedContent && mUnselectedContent.GetParent() )
426   {
427     Self().Remove( mUnselectedContent );
428   }
429
430   mUnselectedContent = image;
431   if( mUnselectedContent )
432   {
433     mUnselectedContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
434     mUnselectedContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
435     mUnselectedContent.SetPosition( 0.f, 0.f );
436   }
437   ResetImageLayers();
438   OnButtonImageSet();
439
440   RelayoutRequest();
441 }
442
443 Actor Button::GetButtonImage() const
444 {
445   return mUnselectedContent;
446 }
447
448 Actor& Button::GetButtonImage()
449 {
450   return mUnselectedContent;
451 }
452
453 void Button::SetSelectedImage( Actor image )
454 {
455   StopTransitionAnimation();
456
457   if( mSelectedContent && mSelectedContent.GetParent() )
458   {
459     Self().Remove( mSelectedContent );
460   }
461
462   mSelectedContent = image;
463   if( mSelectedContent )
464   {
465     mSelectedContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
466     mSelectedContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
467     mSelectedContent.SetPosition( 0.f, 0.f );
468   }
469   ResetImageLayers();
470   OnSelectedImageSet();
471
472   RelayoutRequest();
473 }
474
475 Actor Button::GetSelectedImage() const
476 {
477   return mSelectedContent;
478 }
479
480 Actor& Button::GetSelectedImage()
481 {
482   return mSelectedContent;
483 }
484
485 void Button::SetBackgroundImage( Actor image )
486 {
487   StopTransitionAnimation();
488
489   if( mBackgroundContent && mBackgroundContent.GetParent() )
490   {
491     Self().Remove( mBackgroundContent );
492   }
493
494   mBackgroundContent = image;
495   if( mBackgroundContent )
496   {
497     mBackgroundContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
498     mBackgroundContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
499     mBackgroundContent.SetPosition( 0.f, 0.f );
500   }
501   ResetImageLayers();
502   OnBackgroundImageSet();
503
504   RelayoutRequest();
505 }
506
507 Actor Button::GetBackgroundImage() const
508 {
509   return mBackgroundContent;
510 }
511
512 Actor& Button::GetBackgroundImage()
513 {
514   return mBackgroundContent;
515 }
516
517 void Button::SetSelectedBackgroundImage( Actor image )
518 {
519   StopTransitionAnimation();
520
521   if( mSelectedBackgroundContent && mSelectedBackgroundContent.GetParent() )
522   {
523     Self().Remove( mSelectedBackgroundContent );
524   }
525
526   mSelectedBackgroundContent = image;
527   if( mSelectedBackgroundContent )
528   {
529     mSelectedBackgroundContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
530     mSelectedBackgroundContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
531     mSelectedBackgroundContent.SetPosition( 0.f, 0.f );
532   }
533   ResetImageLayers();
534   OnSelectedBackgroundImageSet();
535
536   RelayoutRequest();
537 }
538
539 Actor Button::GetSelectedBackgroundImage() const
540 {
541   return mSelectedBackgroundContent;
542 }
543
544 Actor& Button::GetSelectedBackgroundImage()
545 {
546   return mSelectedBackgroundContent;
547 }
548
549 void Button::SetDisabledImage( Actor image )
550 {
551   StopTransitionAnimation();
552
553   if( mDisabledContent && mDisabledContent.GetParent() )
554   {
555     Self().Remove( mDisabledContent );
556   }
557
558   mDisabledContent = image;
559   if( mDisabledContent )
560   {
561     mDisabledContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
562     mDisabledContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
563     mDisabledContent.SetPosition( 0.f, 0.f );
564   }
565
566   ResetImageLayers();
567   OnDisabledImageSet();
568 }
569
570 Actor Button::GetDisabledImage() const
571 {
572   return mDisabledContent;
573 }
574
575 Actor& Button::GetDisabledImage()
576 {
577   return mDisabledContent;
578 }
579
580 void Button::SetDisabledSelectedImage( Actor image )
581 {
582   StopTransitionAnimation();
583
584   if( mDisabledSelectedContent && mDisabledSelectedContent.GetParent() )
585   {
586     Self().Remove( mDisabledSelectedContent );
587   }
588
589   mDisabledSelectedContent = image;
590   if( mDisabledSelectedContent )
591   {
592     mDisabledSelectedContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
593     mDisabledSelectedContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
594     mDisabledSelectedContent.SetPosition( 0.f, 0.f );
595   }
596
597   ResetImageLayers();
598   OnDisabledSelectedImageSet();
599 }
600
601 Actor Button::GetDisabledSelectedImage() const
602 {
603   return mDisabledSelectedContent;
604 }
605
606 Actor& Button::GetDisabledSelectedImage()
607 {
608   return mDisabledSelectedContent;
609 }
610
611 void Button::SetDisabledBackgroundImage( Actor image )
612 {
613   StopTransitionAnimation();
614
615   if( mDisabledBackgroundContent && mDisabledBackgroundContent.GetParent() )
616   {
617     Self().Remove( mDisabledBackgroundContent );
618   }
619
620   mDisabledBackgroundContent = image;
621   if( mDisabledBackgroundContent )
622   {
623     mDisabledBackgroundContent.SetAnchorPoint( AnchorPoint::TOP_LEFT );
624     mDisabledBackgroundContent.SetParentOrigin( ParentOrigin::TOP_LEFT );
625     mDisabledBackgroundContent.SetPosition( 0.f, 0.f );
626   }
627   ResetImageLayers();
628   OnDisabledBackgroundImageSet();
629 }
630
631 Actor Button::GetDisabledBackgroundImage() const
632 {
633   return mDisabledBackgroundContent;
634 }
635
636 Actor& Button::GetDisabledBackgroundImage()
637 {
638   return mDisabledBackgroundContent;
639 }
640
641 bool Button::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
642 {
643   bool ret = false;
644
645   Dali::BaseHandle handle( object );
646
647   Toolkit::Button button = Toolkit::Button::DownCast( handle );
648
649   DALI_ASSERT_ALWAYS( button );
650
651   if( 0 == strcmp( actionName.c_str(), ACTION_BUTTON_CLICK ) )
652   {
653     ret = GetImplementation( button ).DoClickAction( attributes );
654   }
655
656   return ret;
657 }
658
659 bool Button::DoClickAction( const Property::Map& attributes )
660 {
661   // Prevents the button signals from doing a recursive loop by sending an action
662   // and re-emitting the signals.
663   if( !mClickActionPerforming )
664   {
665     mClickActionPerforming = true;
666     OnButtonDown();
667     mState = ButtonDown;
668     OnButtonUp();
669     mClickActionPerforming = false;
670
671     return true;
672   }
673
674   return false;
675 }
676
677 void Button::OnButtonStageDisconnection()
678 {
679   if( ButtonDown == mState )
680   {
681     if( !mTogglableButton )
682     {
683       Released();
684
685       if( mAutoRepeating )
686       {
687         mAutoRepeatingTimer.Reset();
688       }
689     }
690   }
691 }
692
693 void Button::OnButtonDown()
694 {
695   if( !mTogglableButton )
696   {
697     Toolkit::Button handle( GetOwner() );
698
699     Pressed();
700
701     if( mAutoRepeating )
702     {
703       SetUpTimer( mInitialAutoRepeatingDelay );
704     }
705
706     //Emit signal.
707     mPressedSignal.Emit( handle );
708   }
709 }
710
711 void Button::OnButtonUp()
712 {
713   if( ButtonDown == mState )
714   {
715     if( mTogglableButton )
716     {
717       SetSelected( !mSelected );
718     }
719     else
720     {
721       Released();
722
723       if( mAutoRepeating )
724       {
725         mAutoRepeatingTimer.Reset();
726       }
727
728       Toolkit::Button handle( GetOwner() );
729
730       //Emit signal.
731       mReleasedSignal.Emit( handle );
732       mClickedSignal.Emit( handle );
733     }
734   }
735 }
736
737 void Button::OnTouchPointLeave()
738 {
739   if( ButtonDown == mState )
740   {
741     if( !mTogglableButton )
742     {
743       Toolkit::Button handle( GetOwner() );
744
745       Released();
746
747       if( mAutoRepeating )
748       {
749         mAutoRepeatingTimer.Reset();
750       }
751
752       //Emit signal.
753       mReleasedSignal.Emit( handle );
754     }
755   }
756 }
757
758 void Button::OnTouchPointInterrupted()
759 {
760   OnTouchPointLeave();
761 }
762
763 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
764 {
765   return mPressedSignal;
766 }
767
768 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
769 {
770   return mReleasedSignal;
771 }
772
773 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
774 {
775   return mClickedSignal;
776 }
777
778 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
779 {
780   return mStateChangedSignal;
781 }
782
783 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
784 {
785   Dali::BaseHandle handle( object );
786
787   bool connected( true );
788   Toolkit::Button button = Toolkit::Button::DownCast( handle );
789
790   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
791   {
792     button.PressedSignal().Connect( tracker, functor );
793   }
794   else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
795   {
796     button.ReleasedSignal().Connect( tracker, functor );
797   }
798   else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
799   {
800     button.ClickedSignal().Connect( tracker, functor );
801   }
802   else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
803   {
804     button.StateChangedSignal().Connect( tracker, functor );
805   }
806   else
807   {
808     // signalName does not match any signal
809     connected = false;
810   }
811
812   return connected;
813 }
814
815 bool Button::OnTouchEvent(const TouchEvent& event)
816 {
817   // Only events are processed when the button is not disabled and the touch event has only
818   // one touch point.
819   if( ( !mDisabled ) && ( 1 == event.GetPointCount() ) )
820   {
821     switch( event.GetPoint(0).state )
822     {
823       case TouchPoint::Down:
824       {
825         OnButtonDown(); // Notification for derived classes.
826
827         // Sets the button state to ButtonDown.
828         mState = ButtonDown;
829         break;
830       }
831       case TouchPoint::Up:
832       {
833         OnButtonUp(); // Notification for derived classes.
834
835         // Sets the button state to ButtonUp.
836         mState = ButtonUp;
837         break;
838       }
839       case TouchPoint::Interrupted:
840       {
841         OnTouchPointInterrupted(); // Notification for derived classes.
842
843         // Sets the button state to the default (ButtonUp).
844         mState = ButtonUp;
845         break;
846       }
847       case TouchPoint::Leave:
848       {
849         OnTouchPointLeave(); // Notification for derived classes.
850
851         // Sets the button state to the default (ButtonUp).
852         mState = ButtonUp;
853         break;
854       }
855       case TouchPoint::Motion:
856       case TouchPoint::Stationary: // FALLTHROUGH
857       {
858         // Nothing to do
859         break;
860       }
861       default:
862       {
863         DALI_ASSERT_ALWAYS( !"Point status unhandled." );
864         break;
865       }
866     }
867   }
868   else if( 1 < event.GetPointCount() )
869   {
870     OnTouchPointLeave(); // Notification for derived classes.
871
872     // Sets the button state to the default (ButtonUp).
873     mState = ButtonUp;
874   }
875
876   return false;
877 }
878
879 void Button::OnInitialize()
880 {
881   Actor self = Self();
882
883   mTapDetector = TapGestureDetector::New();
884   mTapDetector.Attach( self );
885   mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
886
887   OnButtonInitialize();
888
889   self.SetKeyboardFocusable( true );
890 }
891
892 bool Button::OnAccessibilityActivated()
893 {
894   return OnKeyboardEnter();
895 }
896
897 bool Button::OnKeyboardEnter()
898 {
899   // When the enter key is pressed, or button is activated, the click action is performed.
900   Property::Map attributes;
901   bool ret = DoClickAction( attributes );
902
903   return ret;
904 }
905
906 void Button::OnControlStageDisconnection()
907 {
908   OnButtonStageDisconnection(); // Notification for derived classes.
909   mState = ButtonUp;
910 }
911
912 void Button::OnTap(Actor actor, const TapGesture& tap)
913 {
914   // Do nothing.
915 }
916
917 void Button::SetUpTimer( float delay )
918 {
919   mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
920   mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
921   mAutoRepeatingTimer.Start();
922 }
923
924 bool Button::AutoRepeatingSlot()
925 {
926   bool consumed = false;
927   if( !mDisabled )
928   {
929     // Restart the autorepeat timer.
930     SetUpTimer( mNextAutoRepeatingDelay );
931
932     Pressed();
933
934     Toolkit::Button handle( GetOwner() );
935
936     //Emit signal.
937     consumed = mReleasedSignal.Emit( handle );
938     consumed |= mClickedSignal.Emit( handle );
939     consumed |= mPressedSignal.Emit( handle );
940  }
941
942   return consumed;
943 }
944
945 void Button::Pressed()
946 {
947   if( mPaintState == UnselectedState )
948   {
949     StopTransitionAnimation();
950
951     // Notifies the derived class the button has been pressed.
952      OnPressed();
953
954      //Layer Order
955     //(4) mSelectedContent (Inserted)
956     //(3) mUnselectedContent
957     //(2) mSelectedBackgroundContent (Inserted)
958     //(1) mBackgroundContent
959
960     TransitionInBetween( mUnselectedContent, mLabel, mSelectedContent );
961     TransitionInAbove( mBackgroundContent, mSelectedBackgroundContent );
962     TransitionInAtIndex( 0, mBackgroundContent );
963
964     TransitionOut( mUnselectedContent );
965     TransitionOut( mDisabledContent );
966     TransitionOut( mDisabledSelectedContent );
967     TransitionOut( mDisabledBackgroundContent );
968
969     mPaintState = SelectedState;
970
971     StartTransitionAnimation();
972   }
973 }
974
975 void Button::Released()
976 {
977   if( mPaintState == SelectedState )
978   {
979     StopTransitionAnimation();
980
981     // Notifies the derived class the button has been released.
982     OnReleased();
983
984     //Layer Order
985     //(3) mUnselectedContent (Inserted)
986     //(2) mSelectedContent
987     //(1) mBackgroundContent
988
989     TransitionInBetween( mSelectedContent, mLabel, mUnselectedContent );
990     TransitionInAtIndex( 0, mBackgroundContent );
991
992     TransitionOut( mSelectedContent );
993     TransitionOut( mSelectedBackgroundContent );
994     TransitionOut( mDisabledContent );
995     TransitionOut( mDisabledSelectedContent );
996     TransitionOut( mDisabledBackgroundContent );
997
998     mPaintState = UnselectedState;
999
1000     StartTransitionAnimation();
1001   }
1002 }
1003
1004 Button::ButtonState Button::GetState()
1005 {
1006   return mState;
1007 }
1008
1009 Button::PaintState Button::GetPaintState()
1010 {
1011   return mPaintState;
1012 }
1013
1014 bool Button::InsertButtonImage( unsigned int index, Actor& actor )
1015 {
1016   if( actor )
1017   {
1018     Self().Insert( index, actor );
1019     PrepareForTranstionOut( actor );
1020     return true;
1021   }
1022
1023   return false;
1024 }
1025
1026 void Button::RemoveButtonImage( Actor& actor )
1027 {
1028   if( actor )
1029   {
1030     if( actor.GetParent() )
1031     {
1032       Self().Remove( actor );
1033     }
1034     PrepareForTranstionIn( actor );
1035   }
1036 }
1037
1038 unsigned int Button::FindChildIndex( Actor& actor )
1039 {
1040   Actor self = Self();
1041   unsigned int childrenNum = self.GetChildCount();
1042
1043   for( unsigned int i = 0; i < childrenNum; i++ )
1044   {
1045     Actor child = self.GetChildAt( i );
1046     if( child == actor )
1047     {
1048       return i;
1049     }
1050   }
1051
1052   return childrenNum;
1053 }
1054
1055 void Button::TransitionInBetween(  Actor childLower, Actor childUpper, Actor actor )
1056 {
1057   unsigned int index = childLower ? FindChildIndex( childLower ) + 1 : FindChildIndex( childUpper );
1058   TransitionInAtIndex( index, actor );
1059 }
1060
1061 void Button::TransitionInAbove( Actor child, Actor actor )
1062 {
1063   unsigned int index = child ? FindChildIndex( child ) + 1 : 0;
1064   TransitionInAtIndex( index, actor );
1065 }
1066
1067 void Button::TransitionInAtIndex( unsigned int index, Actor actor )
1068 {
1069   if( actor )
1070   {
1071     if( !actor.GetParent() )
1072     {
1073       Self().Insert( index, actor );
1074     }
1075
1076     OnTransitionIn( actor );
1077   }
1078 }
1079
1080 void Button::TransitionOut( Actor actor )
1081 {
1082   OnTransitionOut( actor );
1083 }
1084
1085 void Button::ResetImageLayers()
1086 {
1087   //ensure that all layers are in the correct order and state according to the paint state
1088
1089   int index = 0;
1090   switch( mPaintState )
1091   {
1092     case UnselectedState:
1093     {
1094       //Layer Order
1095       //(2) mUnselectedContent
1096       //(1) mBackgroundContent
1097
1098       RemoveButtonImage( mSelectedContent );
1099       RemoveButtonImage( mSelectedBackgroundContent );
1100       RemoveButtonImage( mDisabledContent );
1101       RemoveButtonImage( mDisabledSelectedContent );
1102       RemoveButtonImage( mDisabledBackgroundContent );
1103
1104       if( InsertButtonImage( index, mBackgroundContent ) )
1105       {
1106         ++index;
1107       }
1108       if( InsertButtonImage( index, mUnselectedContent ) )
1109       {
1110         ++index;
1111       }
1112       break;
1113     }
1114     case SelectedState:
1115     {
1116       //Layer Order
1117       //(3) mSelectedContent
1118       //(2) mSelectedBackgroundContent
1119       //(1) mBackgroundContent
1120
1121       RemoveButtonImage( mUnselectedContent );
1122       RemoveButtonImage( mDisabledContent );
1123       RemoveButtonImage( mDisabledSelectedContent );
1124       RemoveButtonImage( mDisabledBackgroundContent );
1125
1126       if( InsertButtonImage( index, mBackgroundContent ) )
1127       {
1128         ++index;
1129       }
1130       if( InsertButtonImage( index, mSelectedBackgroundContent ) )
1131       {
1132         ++index;
1133       }
1134       if( InsertButtonImage( index, mSelectedContent ) )
1135       {
1136         ++index;
1137       }
1138       break;
1139     }
1140     case DisabledUnselectedState:
1141     {
1142       //Layer Order
1143       //(2) mDisabledContent
1144       //(1) mDisabledBackgroundContent
1145
1146       RemoveButtonImage( mUnselectedContent );
1147       RemoveButtonImage( mBackgroundContent );
1148       RemoveButtonImage( mSelectedContent );
1149       RemoveButtonImage( mDisabledSelectedContent );
1150       RemoveButtonImage( mSelectedBackgroundContent );
1151
1152       if( InsertButtonImage( index, mDisabledBackgroundContent ? mDisabledBackgroundContent : mBackgroundContent ) )
1153       {
1154         ++index;
1155       }
1156       if( InsertButtonImage( index, mDisabledContent ? mDisabledContent : mUnselectedContent ) )
1157       {
1158         ++index;
1159       }
1160       break;
1161     }
1162     case DisabledSelectedState:
1163     {
1164       //Layer Order
1165       // (2) mDisabledSelectedContent
1166       // (1) mDisabledBackgroundContent
1167
1168       RemoveButtonImage( mUnselectedContent );
1169       RemoveButtonImage( mSelectedContent );
1170       RemoveButtonImage( mBackgroundContent );
1171       RemoveButtonImage( mSelectedBackgroundContent );
1172       RemoveButtonImage( mDisabledContent );
1173
1174       if( mDisabledBackgroundContent )
1175       {
1176         if( InsertButtonImage( index, mDisabledBackgroundContent) )
1177         {
1178           ++index;
1179         }
1180       }
1181       else
1182       {
1183         if( InsertButtonImage( index, mBackgroundContent ) )
1184         {
1185           ++index;
1186         }
1187         if( InsertButtonImage( index, mSelectedBackgroundContent ) )
1188         {
1189           ++index;
1190         }
1191       }
1192
1193       if( InsertButtonImage( index, mDisabledSelectedContent ? mDisabledSelectedContent : mSelectedContent) )
1194       {
1195         ++index;
1196       }
1197       break;
1198     }
1199   }
1200 }
1201
1202 void Button::StartTransitionAnimation()
1203 {
1204   if( mTransitionAnimation )
1205   {
1206     mTransitionAnimation.Play();
1207   }
1208   else
1209   {
1210     ResetImageLayers();
1211   }
1212 }
1213
1214 void Button::StopTransitionAnimation()
1215 {
1216   if( mTransitionAnimation )
1217   {
1218     mTransitionAnimation.Clear();
1219     mTransitionAnimation.Reset();
1220   }
1221 }
1222
1223 Dali::Animation Button::GetTransitionAnimation()
1224 {
1225   if( !mTransitionAnimation )
1226   {
1227     mTransitionAnimation = Dali::Animation::New( GetAnimationTime() );
1228     mTransitionAnimation.FinishedSignal().Connect( this, &Button::TransitionAnimationFinished );
1229   }
1230
1231   return mTransitionAnimation;
1232 }
1233
1234 void Button::TransitionAnimationFinished( Dali::Animation& source )
1235 {
1236   StopTransitionAnimation();
1237   ResetImageLayers();
1238 }
1239
1240 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
1241 {
1242   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1243
1244   if ( button )
1245   {
1246     switch ( index )
1247     {
1248       case Toolkit::Button::Property::DISABLED:
1249       {
1250         GetImplementation( button ).SetDisabled( value.Get< bool >() );
1251         break;
1252       }
1253
1254       case Toolkit::Button::Property::AUTO_REPEATING:
1255       {
1256         GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
1257         break;
1258       }
1259
1260       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1261       {
1262         GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
1263         break;
1264       }
1265
1266       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1267       {
1268         GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
1269         break;
1270       }
1271
1272       case Toolkit::Button::Property::TOGGLABLE:
1273       {
1274         GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
1275         break;
1276       }
1277
1278       case Toolkit::Button::Property::SELECTED:
1279       {
1280         GetImplementation( button ).SetSelected( value.Get< bool >() );
1281         break;
1282       }
1283
1284       case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
1285       {
1286         GetImplementation( button ).SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1287         break;
1288       }
1289
1290       case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
1291       {
1292         GetImplementation( button ).SetSelectedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1293         break;
1294       }
1295
1296       case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
1297       {
1298         GetImplementation( button ).SetDisabledImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1299         break;
1300       }
1301
1302       case Toolkit::Button::Property::LABEL_ACTOR:
1303       {
1304         GetImplementation( button ).SetLabel( Scripting::NewActor( value.Get< Property::Map >() ) );
1305         break;
1306       }
1307     }
1308   }
1309 }
1310
1311 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
1312 {
1313   Property::Value value;
1314
1315   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1316
1317   if ( button )
1318   {
1319     switch ( propertyIndex )
1320     {
1321       case Toolkit::Button::Property::DISABLED:
1322       {
1323         value = GetImplementation( button ).mDisabled;
1324         break;
1325       }
1326
1327       case Toolkit::Button::Property::AUTO_REPEATING:
1328       {
1329         value = GetImplementation( button ).mAutoRepeating;
1330         break;
1331       }
1332
1333       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1334       {
1335         value = GetImplementation( button ).mInitialAutoRepeatingDelay;
1336         break;
1337       }
1338
1339       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1340       {
1341         value = GetImplementation( button ).mNextAutoRepeatingDelay;
1342         break;
1343       }
1344
1345       case Toolkit::Button::Property::TOGGLABLE:
1346       {
1347         value = GetImplementation( button ).mTogglableButton;
1348         break;
1349       }
1350
1351       case Toolkit::Button::Property::SELECTED:
1352       {
1353         value = GetImplementation( button ).mSelected;
1354         break;
1355       }
1356
1357       case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
1358       {
1359         Property::Map map;
1360         Scripting::CreatePropertyMap( GetImplementation( button ).mUnselectedContent, map );
1361         value = map;
1362         break;
1363       }
1364
1365       case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
1366       {
1367         Property::Map map;
1368         Scripting::CreatePropertyMap( GetImplementation( button ).mSelectedContent, map );
1369         value = map;
1370         break;
1371       }
1372
1373       case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
1374       {
1375         Property::Map map;
1376         Scripting::CreatePropertyMap( GetImplementation( button ).mDisabledContent, map );
1377         value = map;
1378         break;
1379       }
1380
1381       case Toolkit::Button::Property::LABEL_ACTOR:
1382       {
1383         Property::Map map;
1384         Scripting::CreatePropertyMap( GetImplementation( button ).mLabel, map );
1385         value = map;
1386         break;
1387       }
1388     }
1389   }
1390
1391   return value;
1392 }
1393
1394 } // namespace Internal
1395
1396 } // namespace Toolkit
1397
1398 } // namespace Dali