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