Merge "Fix for the layout engine." into devel/master
[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     Pressed();
698
699     if( mAutoRepeating )
700     {
701       SetUpTimer( mInitialAutoRepeatingDelay );
702     }
703   }
704
705   // The pressed signal should be emitted regardless of toggle mode.
706   Toolkit::Button handle( GetOwner() );
707   mPressedSignal.Emit( handle );
708 }
709
710 void Button::OnButtonUp()
711 {
712   if( ButtonDown == mState )
713   {
714     if( mTogglableButton )
715     {
716       SetSelected( !mSelected );
717     }
718     else
719     {
720       Released();
721
722       if( mAutoRepeating )
723       {
724         mAutoRepeatingTimer.Reset();
725       }
726     }
727
728     // The clicked and released signals should be emitted regardless of toggle mode.
729     Toolkit::Button handle( GetOwner() );
730     mReleasedSignal.Emit( handle );
731     mClickedSignal.Emit( handle );
732   }
733 }
734
735 void Button::OnTouchPointLeave()
736 {
737   if( ButtonDown == mState )
738   {
739     if( !mTogglableButton )
740     {
741       Released();
742
743       if( mAutoRepeating )
744       {
745         mAutoRepeatingTimer.Reset();
746       }
747     }
748
749     // The released signal should be emitted regardless of toggle mode.
750     Toolkit::Button handle( GetOwner() );
751     mReleasedSignal.Emit( handle );
752   }
753 }
754
755 void Button::OnTouchPointInterrupted()
756 {
757   OnTouchPointLeave();
758 }
759
760 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
761 {
762   return mPressedSignal;
763 }
764
765 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
766 {
767   return mReleasedSignal;
768 }
769
770 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
771 {
772   return mClickedSignal;
773 }
774
775 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
776 {
777   return mStateChangedSignal;
778 }
779
780 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
781 {
782   Dali::BaseHandle handle( object );
783
784   bool connected( true );
785   Toolkit::Button button = Toolkit::Button::DownCast( handle );
786
787   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
788   {
789     button.PressedSignal().Connect( tracker, functor );
790   }
791   else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
792   {
793     button.ReleasedSignal().Connect( tracker, functor );
794   }
795   else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
796   {
797     button.ClickedSignal().Connect( tracker, functor );
798   }
799   else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
800   {
801     button.StateChangedSignal().Connect( tracker, functor );
802   }
803   else
804   {
805     // signalName does not match any signal
806     connected = false;
807   }
808
809   return connected;
810 }
811
812 bool Button::OnTouchEvent(const TouchEvent& event)
813 {
814   // Only events are processed when the button is not disabled and the touch event has only
815   // one touch point.
816   if( ( !mDisabled ) && ( 1 == event.GetPointCount() ) )
817   {
818     switch( event.GetPoint(0).state )
819     {
820       case TouchPoint::Down:
821       {
822         OnButtonDown(); // Notification for derived classes.
823
824         // Sets the button state to ButtonDown.
825         mState = ButtonDown;
826         break;
827       }
828       case TouchPoint::Up:
829       {
830         OnButtonUp(); // Notification for derived classes.
831
832         // Sets the button state to ButtonUp.
833         mState = ButtonUp;
834         break;
835       }
836       case TouchPoint::Interrupted:
837       {
838         OnTouchPointInterrupted(); // Notification for derived classes.
839
840         // Sets the button state to the default (ButtonUp).
841         mState = ButtonUp;
842         break;
843       }
844       case TouchPoint::Leave:
845       {
846         OnTouchPointLeave(); // Notification for derived classes.
847
848         // Sets the button state to the default (ButtonUp).
849         mState = ButtonUp;
850         break;
851       }
852       case TouchPoint::Motion:
853       case TouchPoint::Stationary: // FALLTHROUGH
854       {
855         // Nothing to do
856         break;
857       }
858       default:
859       {
860         DALI_ASSERT_ALWAYS( !"Point status unhandled." );
861         break;
862       }
863     }
864   }
865   else if( 1 < event.GetPointCount() )
866   {
867     OnTouchPointLeave(); // Notification for derived classes.
868
869     // Sets the button state to the default (ButtonUp).
870     mState = ButtonUp;
871   }
872
873   return false;
874 }
875
876 void Button::OnInitialize()
877 {
878   Actor self = Self();
879
880   mTapDetector = TapGestureDetector::New();
881   mTapDetector.Attach( self );
882   mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
883
884   OnButtonInitialize();
885
886   self.SetKeyboardFocusable( true );
887 }
888
889 bool Button::OnAccessibilityActivated()
890 {
891   return OnKeyboardEnter();
892 }
893
894 bool Button::OnKeyboardEnter()
895 {
896   // When the enter key is pressed, or button is activated, the click action is performed.
897   Property::Map attributes;
898   bool ret = DoClickAction( attributes );
899
900   return ret;
901 }
902
903 void Button::OnControlStageDisconnection()
904 {
905   OnButtonStageDisconnection(); // Notification for derived classes.
906   mState = ButtonUp;
907 }
908
909 void Button::OnTap(Actor actor, const TapGesture& tap)
910 {
911   // Do nothing.
912 }
913
914 void Button::SetUpTimer( float delay )
915 {
916   mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
917   mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
918   mAutoRepeatingTimer.Start();
919 }
920
921 bool Button::AutoRepeatingSlot()
922 {
923   bool consumed = false;
924   if( !mDisabled )
925   {
926     // Restart the autorepeat timer.
927     SetUpTimer( mNextAutoRepeatingDelay );
928
929     Pressed();
930
931     Toolkit::Button handle( GetOwner() );
932
933     //Emit signal.
934     consumed = mReleasedSignal.Emit( handle );
935     consumed |= mClickedSignal.Emit( handle );
936     consumed |= mPressedSignal.Emit( handle );
937  }
938
939   return consumed;
940 }
941
942 void Button::Pressed()
943 {
944   if( mPaintState == UnselectedState )
945   {
946     StopTransitionAnimation();
947
948     // Notifies the derived class the button has been pressed.
949      OnPressed();
950
951      //Layer Order
952     //(4) mSelectedContent (Inserted)
953     //(3) mUnselectedContent
954     //(2) mSelectedBackgroundContent (Inserted)
955     //(1) mBackgroundContent
956
957     TransitionInBetween( mUnselectedContent, mLabel, mSelectedContent );
958     TransitionInAbove( mBackgroundContent, mSelectedBackgroundContent );
959     TransitionInAtIndex( 0, mBackgroundContent );
960
961     TransitionOut( mUnselectedContent );
962     TransitionOut( mDisabledContent );
963     TransitionOut( mDisabledSelectedContent );
964     TransitionOut( mDisabledBackgroundContent );
965
966     mPaintState = SelectedState;
967
968     StartTransitionAnimation();
969   }
970 }
971
972 void Button::Released()
973 {
974   if( mPaintState == SelectedState )
975   {
976     StopTransitionAnimation();
977
978     // Notifies the derived class the button has been released.
979     OnReleased();
980
981     //Layer Order
982     //(3) mUnselectedContent (Inserted)
983     //(2) mSelectedContent
984     //(1) mBackgroundContent
985
986     TransitionInBetween( mSelectedContent, mLabel, mUnselectedContent );
987     TransitionInAtIndex( 0, mBackgroundContent );
988
989     TransitionOut( mSelectedContent );
990     TransitionOut( mSelectedBackgroundContent );
991     TransitionOut( mDisabledContent );
992     TransitionOut( mDisabledSelectedContent );
993     TransitionOut( mDisabledBackgroundContent );
994
995     mPaintState = UnselectedState;
996
997     StartTransitionAnimation();
998   }
999 }
1000
1001 Button::ButtonState Button::GetState()
1002 {
1003   return mState;
1004 }
1005
1006 Button::PaintState Button::GetPaintState()
1007 {
1008   return mPaintState;
1009 }
1010
1011 bool Button::InsertButtonImage( unsigned int index, Actor& actor )
1012 {
1013   if( actor )
1014   {
1015     Self().Insert( index, actor );
1016     PrepareForTranstionOut( actor );
1017     return true;
1018   }
1019
1020   return false;
1021 }
1022
1023 void Button::RemoveButtonImage( Actor& actor )
1024 {
1025   if( actor )
1026   {
1027     if( actor.GetParent() )
1028     {
1029       Self().Remove( actor );
1030     }
1031     PrepareForTranstionIn( actor );
1032   }
1033 }
1034
1035 unsigned int Button::FindChildIndex( Actor& actor )
1036 {
1037   Actor self = Self();
1038   unsigned int childrenNum = self.GetChildCount();
1039
1040   for( unsigned int i = 0; i < childrenNum; i++ )
1041   {
1042     Actor child = self.GetChildAt( i );
1043     if( child == actor )
1044     {
1045       return i;
1046     }
1047   }
1048
1049   return childrenNum;
1050 }
1051
1052 void Button::TransitionInBetween(  Actor childLower, Actor childUpper, Actor actor )
1053 {
1054   unsigned int index = childLower ? FindChildIndex( childLower ) + 1 : FindChildIndex( childUpper );
1055   TransitionInAtIndex( index, actor );
1056 }
1057
1058 void Button::TransitionInAbove( Actor child, Actor actor )
1059 {
1060   unsigned int index = child ? FindChildIndex( child ) + 1 : 0;
1061   TransitionInAtIndex( index, actor );
1062 }
1063
1064 void Button::TransitionInAtIndex( unsigned int index, Actor actor )
1065 {
1066   if( actor )
1067   {
1068     if( !actor.GetParent() )
1069     {
1070       Self().Insert( index, actor );
1071     }
1072
1073     OnTransitionIn( actor );
1074   }
1075 }
1076
1077 void Button::TransitionOut( Actor actor )
1078 {
1079   OnTransitionOut( actor );
1080 }
1081
1082 void Button::ResetImageLayers()
1083 {
1084   //ensure that all layers are in the correct order and state according to the paint state
1085
1086   int index = 0;
1087   switch( mPaintState )
1088   {
1089     case UnselectedState:
1090     {
1091       //Layer Order
1092       //(2) mUnselectedContent
1093       //(1) mBackgroundContent
1094
1095       RemoveButtonImage( mSelectedContent );
1096       RemoveButtonImage( mSelectedBackgroundContent );
1097       RemoveButtonImage( mDisabledContent );
1098       RemoveButtonImage( mDisabledSelectedContent );
1099       RemoveButtonImage( mDisabledBackgroundContent );
1100
1101       if( InsertButtonImage( index, mBackgroundContent ) )
1102       {
1103         ++index;
1104       }
1105       if( InsertButtonImage( index, mUnselectedContent ) )
1106       {
1107         ++index;
1108       }
1109       break;
1110     }
1111     case SelectedState:
1112     {
1113       //Layer Order
1114       //(3) mSelectedContent
1115       //(2) mSelectedBackgroundContent
1116       //(1) mBackgroundContent
1117
1118       RemoveButtonImage( mUnselectedContent );
1119       RemoveButtonImage( mDisabledContent );
1120       RemoveButtonImage( mDisabledSelectedContent );
1121       RemoveButtonImage( mDisabledBackgroundContent );
1122
1123       if( InsertButtonImage( index, mBackgroundContent ) )
1124       {
1125         ++index;
1126       }
1127       if( InsertButtonImage( index, mSelectedBackgroundContent ) )
1128       {
1129         ++index;
1130       }
1131       if( InsertButtonImage( index, mSelectedContent ) )
1132       {
1133         ++index;
1134       }
1135       break;
1136     }
1137     case DisabledUnselectedState:
1138     {
1139       //Layer Order
1140       //(2) mDisabledContent
1141       //(1) mDisabledBackgroundContent
1142
1143       RemoveButtonImage( mUnselectedContent );
1144       RemoveButtonImage( mBackgroundContent );
1145       RemoveButtonImage( mSelectedContent );
1146       RemoveButtonImage( mDisabledSelectedContent );
1147       RemoveButtonImage( mSelectedBackgroundContent );
1148
1149       if( InsertButtonImage( index, mDisabledBackgroundContent ? mDisabledBackgroundContent : mBackgroundContent ) )
1150       {
1151         ++index;
1152       }
1153       if( InsertButtonImage( index, mDisabledContent ? mDisabledContent : mUnselectedContent ) )
1154       {
1155         ++index;
1156       }
1157       break;
1158     }
1159     case DisabledSelectedState:
1160     {
1161       //Layer Order
1162       // (2) mDisabledSelectedContent
1163       // (1) mDisabledBackgroundContent
1164
1165       RemoveButtonImage( mUnselectedContent );
1166       RemoveButtonImage( mSelectedContent );
1167       RemoveButtonImage( mBackgroundContent );
1168       RemoveButtonImage( mSelectedBackgroundContent );
1169       RemoveButtonImage( mDisabledContent );
1170
1171       if( mDisabledBackgroundContent )
1172       {
1173         if( InsertButtonImage( index, mDisabledBackgroundContent) )
1174         {
1175           ++index;
1176         }
1177       }
1178       else
1179       {
1180         if( InsertButtonImage( index, mBackgroundContent ) )
1181         {
1182           ++index;
1183         }
1184         if( InsertButtonImage( index, mSelectedBackgroundContent ) )
1185         {
1186           ++index;
1187         }
1188       }
1189
1190       if( InsertButtonImage( index, mDisabledSelectedContent ? mDisabledSelectedContent : mSelectedContent) )
1191       {
1192         ++index;
1193       }
1194       break;
1195     }
1196   }
1197 }
1198
1199 void Button::StartTransitionAnimation()
1200 {
1201   if( mTransitionAnimation )
1202   {
1203     mTransitionAnimation.Play();
1204   }
1205   else
1206   {
1207     ResetImageLayers();
1208   }
1209 }
1210
1211 void Button::StopTransitionAnimation()
1212 {
1213   if( mTransitionAnimation )
1214   {
1215     mTransitionAnimation.Clear();
1216     mTransitionAnimation.Reset();
1217   }
1218 }
1219
1220 Dali::Animation Button::GetTransitionAnimation()
1221 {
1222   if( !mTransitionAnimation )
1223   {
1224     mTransitionAnimation = Dali::Animation::New( GetAnimationTime() );
1225     mTransitionAnimation.FinishedSignal().Connect( this, &Button::TransitionAnimationFinished );
1226   }
1227
1228   return mTransitionAnimation;
1229 }
1230
1231 void Button::TransitionAnimationFinished( Dali::Animation& source )
1232 {
1233   StopTransitionAnimation();
1234   ResetImageLayers();
1235 }
1236
1237 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
1238 {
1239   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1240
1241   if ( button )
1242   {
1243     switch ( index )
1244     {
1245       case Toolkit::Button::Property::DISABLED:
1246       {
1247         GetImplementation( button ).SetDisabled( value.Get< bool >() );
1248         break;
1249       }
1250
1251       case Toolkit::Button::Property::AUTO_REPEATING:
1252       {
1253         GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
1254         break;
1255       }
1256
1257       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1258       {
1259         GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
1260         break;
1261       }
1262
1263       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1264       {
1265         GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
1266         break;
1267       }
1268
1269       case Toolkit::Button::Property::TOGGLABLE:
1270       {
1271         GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
1272         break;
1273       }
1274
1275       case Toolkit::Button::Property::SELECTED:
1276       {
1277         GetImplementation( button ).SetSelected( value.Get< bool >() );
1278         break;
1279       }
1280
1281       case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
1282       {
1283         GetImplementation( button ).SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1284         break;
1285       }
1286
1287       case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
1288       {
1289         GetImplementation( button ).SetSelectedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1290         break;
1291       }
1292
1293       case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
1294       {
1295         GetImplementation( button ).SetDisabledImage( Scripting::NewActor( value.Get< Property::Map >() ) );
1296         break;
1297       }
1298
1299       case Toolkit::Button::Property::LABEL_ACTOR:
1300       {
1301         GetImplementation( button ).SetLabel( Scripting::NewActor( value.Get< Property::Map >() ) );
1302         break;
1303       }
1304     }
1305   }
1306 }
1307
1308 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
1309 {
1310   Property::Value value;
1311
1312   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1313
1314   if ( button )
1315   {
1316     switch ( propertyIndex )
1317     {
1318       case Toolkit::Button::Property::DISABLED:
1319       {
1320         value = GetImplementation( button ).mDisabled;
1321         break;
1322       }
1323
1324       case Toolkit::Button::Property::AUTO_REPEATING:
1325       {
1326         value = GetImplementation( button ).mAutoRepeating;
1327         break;
1328       }
1329
1330       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1331       {
1332         value = GetImplementation( button ).mInitialAutoRepeatingDelay;
1333         break;
1334       }
1335
1336       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1337       {
1338         value = GetImplementation( button ).mNextAutoRepeatingDelay;
1339         break;
1340       }
1341
1342       case Toolkit::Button::Property::TOGGLABLE:
1343       {
1344         value = GetImplementation( button ).mTogglableButton;
1345         break;
1346       }
1347
1348       case Toolkit::Button::Property::SELECTED:
1349       {
1350         value = GetImplementation( button ).mSelected;
1351         break;
1352       }
1353
1354       case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
1355       {
1356         Property::Map map;
1357         Scripting::CreatePropertyMap( GetImplementation( button ).mUnselectedContent, map );
1358         value = map;
1359         break;
1360       }
1361
1362       case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
1363       {
1364         Property::Map map;
1365         Scripting::CreatePropertyMap( GetImplementation( button ).mSelectedContent, map );
1366         value = map;
1367         break;
1368       }
1369
1370       case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
1371       {
1372         Property::Map map;
1373         Scripting::CreatePropertyMap( GetImplementation( button ).mDisabledContent, map );
1374         value = map;
1375         break;
1376       }
1377
1378       case Toolkit::Button::Property::LABEL_ACTOR:
1379       {
1380         Property::Map map;
1381         Scripting::CreatePropertyMap( GetImplementation( button ).mLabel, map );
1382         value = map;
1383         break;
1384       }
1385     }
1386   }
1387
1388   return value;
1389 }
1390
1391 } // namespace Internal
1392
1393 } // namespace Toolkit
1394
1395 } // namespace Dali