Button to use Color Renderer when setting (un)selected color
[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-data.h>
24 #include <dali/public-api/images/resource-image.h>
25 #include <dali/public-api/object/type-registry.h>
26 #include <dali/public-api/object/type-registry-helper.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 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
32 #include <dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h>
33
34 /**
35  * Button states and contents
36  *                                         (3) mSelectedContent
37  *  (2) mUnselectedContent                 (2) mSelectedBackgroundContent
38  *  (1) mBackgroundContent                 (1) mBackgroundContent
39  * < unselected > ----------------------- < selected >
40  *       |                OnSelect()            |
41  *       | OnDisabled()                         | OnDisabled()
42  *       |                                      |
43  * < disabled >                           < disabled-selected >
44  *  (2) mDisabledContent                   (2) mDisabledSelectedContent
45  *  (1) mDisabledBackgroundContent         (1) mDisabledBackgroundContent
46  *
47  * The drawing order of child actors is as follows.
48  *
49  *  Top      mLabel
50  *   |       mUnselectedContent / mSelectedContent / mDisabledContent / mDisabledSelectedContent
51  *   |       mSelectedBackgroundContent
52  * Bottom    mBackgroundContent / mDisabledBackgroundContent
53  *
54  * Some of contents may be missed.
55  * 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.
56  */
57
58 namespace Dali
59 {
60
61 namespace Toolkit
62 {
63
64 namespace Internal
65 {
66
67 namespace
68 {
69
70 BaseHandle Create()
71 {
72   // empty handle as we cannot create button (but type registered for clicked signal)
73   return BaseHandle();
74 }
75
76 // Setup properties, signals and actions using the type-registry.
77 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Button, Toolkit::Control, Create );
78
79 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabled",                     BOOLEAN, DISABLED                     )
80 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "autoRepeating",                BOOLEAN, AUTO_REPEATING               )
81 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "initialAutoRepeatingDelay",    FLOAT,   INITIAL_AUTO_REPEATING_DELAY )
82 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "nextAutoRepeatingDelay",       FLOAT,   NEXT_AUTO_REPEATING_DELAY    )
83 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "togglable",                    BOOLEAN, TOGGLABLE                    )
84 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selected",                     BOOLEAN, SELECTED                     )
85 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "unselectedStateImage",         STRING,  UNSELECTED_STATE_IMAGE       )
86 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selectedStateImage",           STRING,  SELECTED_STATE_IMAGE         )
87 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledStateImage",           STRING,  DISABLED_STATE_IMAGE         )
88 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "unselectedColor",              VECTOR4, UNSELECTED_COLOR             )
89 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selectedColor",                VECTOR4, SELECTED_COLOR               )
90 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "label",                        MAP,     LABEL                        )
91
92 // Deprecated properties:
93 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "labelText",                    STRING,  LABEL_TEXT                   )
94
95 // Signals:
96 DALI_SIGNAL_REGISTRATION(   Toolkit, Button, "pressed",                               SIGNAL_PRESSED               )
97 DALI_SIGNAL_REGISTRATION(   Toolkit, Button, "released",                              SIGNAL_RELEASED              )
98 DALI_SIGNAL_REGISTRATION(   Toolkit, Button, "clicked",                               SIGNAL_CLICKED               )
99 DALI_SIGNAL_REGISTRATION(   Toolkit, Button, "stateChanged",                          SIGNAL_STATE_CHANGED         )
100
101 // Actions:
102 DALI_ACTION_REGISTRATION(   Toolkit, Button, "buttonClick",                           ACTION_BUTTON_CLICK          )
103
104 DALI_TYPE_REGISTRATION_END()
105
106 const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f );
107 const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f );
108
109 } // unnamed namespace
110
111 Button::Button()
112 : Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
113   mAutoRepeatingTimer(),
114   mUnselectedColor( Color::WHITE ), // The natural colors of the specified images will be used by default.
115   mSelectedColor( Color::WHITE ),
116   mDisabled( false ),
117   mAutoRepeating( false ),
118   mTogglableButton( false ),
119   mSelected( false ),
120   mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ),
121   mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ),
122   mAnimationTime( 0.0f ),
123   mClickActionPerforming( false ),
124   mState( ButtonUp ),
125   mPaintState( UnselectedState )
126 {
127 }
128
129 Button::~Button()
130 {
131 }
132
133 void Button::SetDisabled( bool disabled )
134 {
135   if( disabled == mDisabled )
136   {
137     return;
138   }
139
140   StopTransitionAnimation();
141
142   mDisabled = disabled;
143
144   // Notifies the derived class the button has been disabled.
145   OnDisabled();
146
147   switch( mPaintState )
148   {
149     case UnselectedState:
150     {
151       //Layer Order
152       //(3) mDisabledContent (Inserted)
153       //(4) mUnselectedContent
154       //(2) mDisabledBackgroundContent (Inserted)
155       //(1) mBackgroundContent
156
157       AddButtonImage( mBackgroundContent );
158       TransitionButtonImage( mDisabledBackgroundContent );
159       AddButtonImage( mUnselectedContent );
160       TransitionButtonImage( mDisabledContent );
161
162       AddButtonImage( mDecoration[ UNSELECTED_DECORATION ] );
163       ReAddLabel();
164
165       TransitionOut( mDecoration[ SELECTED_DECORATION ] );
166       TransitionOut( mUnselectedContent );
167       TransitionOut( mSelectedContent );
168       TransitionOut( mBackgroundContent );
169       TransitionOut( mSelectedBackgroundContent );
170       TransitionOut( mDisabledSelectedContent );
171
172       mPaintState = DisabledUnselectedState;
173       break;
174     }
175     case SelectedState:
176     {
177       //Layer Order
178       //(5) mDisabledSelectedContent (Inserted)
179       //(4) mSelectedContent
180       //(3) mDisabledBackgroundContent (Inserted)
181       //(2) mSelectedBackgroundContent
182       //(1) mBackgroundContent
183
184       AddButtonImage( mBackgroundContent );
185       AddButtonImage( mSelectedBackgroundContent );
186       TransitionButtonImage( mDisabledBackgroundContent );
187       AddButtonImage( mSelectedContent );
188       TransitionButtonImage( mDisabledSelectedContent );
189
190       AddButtonImage( mDecoration[ SELECTED_DECORATION ] );
191       ReAddLabel();
192
193       TransitionOut( mDecoration[ UNSELECTED_DECORATION ] );
194       TransitionOut( mUnselectedContent );
195       TransitionOut( mSelectedContent );
196       TransitionOut( mBackgroundContent );
197       TransitionOut( mSelectedBackgroundContent );
198       TransitionOut( mDisabledContent );
199
200       mPaintState = DisabledSelectedState;
201       break;
202     }
203     case DisabledUnselectedState:
204     {
205       //Layer Order
206       //(3) mUnselectedContent (Inserted)
207       //(4) mDisabledContent
208       //(2) mBackgroundContent (Inserted)
209       //(1) mDisabledBackgroundContent
210
211       AddButtonImage( mDisabledBackgroundContent );
212       TransitionButtonImage( mBackgroundContent );
213       AddButtonImage( mDisabledContent );
214       TransitionButtonImage( mUnselectedContent );
215
216       AddButtonImage( mDecoration[ UNSELECTED_DECORATION ] );
217       ReAddLabel();
218
219       TransitionOut( mDecoration[ SELECTED_DECORATION ] );
220       TransitionOut( mSelectedContent );
221       TransitionOut( mSelectedBackgroundContent );
222       TransitionOut( mDisabledContent );
223       TransitionOut( mDisabledSelectedContent );
224       TransitionOut( mDisabledBackgroundContent );
225
226       mPaintState = UnselectedState;
227       break;
228     }
229     case DisabledSelectedState:
230     {
231       //Layer Order
232       //(4) mSelectedContent (Inserted)
233       //(5) mDisabledSelectedContent
234       //(3) mSelectedBackgroundContent (Inserted)
235       //(2) mBackgroundContent (Inserted)
236       //(1) mDisabledBackgroundContent
237
238       AddButtonImage( mDisabledBackgroundContent );
239       TransitionButtonImage( mBackgroundContent );
240       TransitionButtonImage( mSelectedBackgroundContent );
241       AddButtonImage( mDisabledSelectedContent );
242       TransitionButtonImage( mSelectedContent );
243
244       AddButtonImage( mDecoration[ SELECTED_DECORATION ] );
245       ReAddLabel();
246
247       TransitionOut( mDecoration[ UNSELECTED_DECORATION ] );
248       TransitionOut( mUnselectedContent );
249       TransitionOut( mDisabledContent );
250       TransitionOut( mDisabledSelectedContent );
251       TransitionOut( mDisabledBackgroundContent );
252
253       mPaintState = SelectedState;
254       break;
255     }
256   }
257
258   StartTransitionAnimation();
259 }
260
261 bool Button::IsDisabled() const
262 {
263   return mDisabled;
264 }
265
266 void Button::SetAutoRepeating( bool autoRepeating )
267 {
268   mAutoRepeating = autoRepeating;
269
270   // An autorepeating button can't be a togglable button.
271   if( autoRepeating )
272   {
273     mTogglableButton = false;
274
275     if( mSelected )
276     {
277       // Emit a signal is not wanted, only change the appearance.
278       SetSelected( false, false );
279     }
280   }
281 }
282
283 bool Button::IsAutoRepeating() const
284 {
285   return mAutoRepeating;
286 }
287
288 void Button::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
289 {
290   DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
291   mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
292 }
293
294 float Button::GetInitialAutoRepeatingDelay() const
295 {
296   return mInitialAutoRepeatingDelay;
297 }
298
299 void Button::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
300 {
301   DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
302   mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
303 }
304
305 float Button::GetNextAutoRepeatingDelay() const
306 {
307   return mNextAutoRepeatingDelay;
308 }
309
310 void Button::SetTogglableButton( bool togglable )
311 {
312   mTogglableButton = togglable;
313
314   // A togglable button can't be an autorepeating button.
315   if( togglable )
316   {
317     mAutoRepeating = false;
318   }
319 }
320
321 bool Button::IsTogglableButton() const
322 {
323   return mTogglableButton;
324 }
325
326 void Button::SetSelected( bool selected )
327 {
328   if( !mDisabled && mTogglableButton && ( selected != mSelected ) )
329   {
330     SetSelected( selected, true );
331   }
332 }
333
334 void Button::SetSelected( bool selected, bool emitSignal )
335 {
336   StopTransitionAnimation();
337
338   mSelected = selected;
339
340   // Notifies the derived class the button has been selected.
341   OnSelected();
342
343   switch( mPaintState )
344   {
345     case UnselectedState:
346     {
347       //Layer Order
348       //(3) mSelectedContent (Inserted)
349       //(4) mUnselectedContent
350       //(2) mSelectedBackgroundContent (Inserted)
351       //(1) mBackgroundContent
352
353       AddButtonImage( mBackgroundContent );
354       TransitionButtonImage( mSelectedBackgroundContent );
355       AddButtonImage( mUnselectedContent );
356       TransitionButtonImage( mSelectedContent );
357
358       AddButtonImage( mDecoration[ UNSELECTED_DECORATION ] );
359       TransitionButtonImage( mDecoration[ SELECTED_DECORATION ] );
360       ReAddLabel();
361
362       TransitionOut( mDecoration[ UNSELECTED_DECORATION ] );
363       TransitionOut( mUnselectedContent );
364       TransitionOut( mDisabledContent );
365       TransitionOut( mDisabledSelectedContent );
366       TransitionOut( mDisabledBackgroundContent );
367
368       mPaintState = SelectedState;
369       break;
370     }
371     case SelectedState:
372     {
373       //Layer Order
374       //(3) mUnselectedContent (Inserted)
375       //(2) mSelectedContent
376       //(1) mBackgroundContent
377
378       AddButtonImage( mBackgroundContent );
379       AddButtonImage( mSelectedContent );
380       TransitionButtonImage( mUnselectedContent );
381
382       AddButtonImage( mDecoration[ SELECTED_DECORATION ] );
383       TransitionButtonImage( mDecoration[ UNSELECTED_DECORATION ] );
384       ReAddLabel();
385
386       TransitionOut( mDecoration[ SELECTED_DECORATION ] );
387       TransitionOut( mSelectedContent );
388       TransitionOut( mSelectedBackgroundContent );
389       TransitionOut( mDisabledContent );
390       TransitionOut( mDisabledSelectedContent );
391       TransitionOut( mDisabledBackgroundContent );
392
393       mPaintState = UnselectedState;
394       break;
395     }
396     case DisabledUnselectedState:
397     case DisabledSelectedState:
398     {
399       DALI_ASSERT_DEBUG( 0 && "Shouldn't be able to change paint state if the button is disabled." );
400       break;
401     }
402   }
403
404   StartTransitionAnimation();
405
406   if( emitSignal )
407   {
408     Toolkit::Button handle( GetOwner() );
409
410     // Emit signal.
411     mStateChangedSignal.Emit( handle );
412   }
413
414   RelayoutRequest();
415 }
416
417 bool Button::IsSelected() const
418 {
419   return mTogglableButton && mSelected;
420 }
421
422 void Button::SetAnimationTime( float animationTime )
423 {
424   mAnimationTime = animationTime;
425 }
426
427 float Button::GetAnimationTime() const
428 {
429   return mAnimationTime;
430 }
431
432 void Button::SetLabelText( const std::string& label )
433 {
434   Property::Map labelProperty;
435   labelProperty.Insert( "text", label );
436   ModifyLabel( labelProperty );
437 }
438
439 std::string Button::GetLabelText() const
440 {
441   Toolkit::TextLabel label = Dali::Toolkit::TextLabel::DownCast( mLabel );
442   if( label )
443   {
444     return label.GetProperty<std::string>( Dali::Toolkit::TextLabel::Property::TEXT );
445   }
446   return std::string();
447 }
448
449 void Button::ModifyLabel( const Property::Map& properties )
450 {
451   // If we don't have a label yet, create one.
452   if( !mLabel )
453   {
454     // If we don't have a label, create one and set it up.
455     // Note: The label text is set from the passed in property map after creation.
456     mLabel = Toolkit::TextLabel::New();
457     mLabel.SetPosition( 0.0f, 0.0f );
458     // label should be the top of the button
459     Self().Add( mLabel );
460   }
461
462   // Set any properties specified for the label by iterating through all property key-value pairs.
463   for( unsigned int i = 0, mapCount = properties.Count(); i < mapCount; ++i )
464   {
465     const StringValuePair& propertyPair( properties.GetPair( i ) );
466
467     // Convert the property string to a property index.
468     Property::Index setPropertyIndex = mLabel.GetPropertyIndex( propertyPair.first );
469     if( setPropertyIndex != Property::INVALID_INDEX )
470     {
471       // If the conversion worked, we have a valid property index,
472       // Set the property to the new value.
473       mLabel.SetProperty( setPropertyIndex, propertyPair.second );
474     }
475   }
476
477   // Notify derived button classes of the change.
478   OnLabelSet( false );
479
480   RelayoutRequest();
481 }
482
483 Actor& Button::GetLabelActor()
484 {
485   return mLabel;
486 }
487
488 void Button::SetDecoration( DecorationState state, Actor actor )
489 {
490   if( mDecoration[ state ] && mDecoration[ state ].GetParent() )
491   {
492     mDecoration[ state ].Unparent();
493   }
494
495   mDecoration[ state ] = actor;
496   mDecoration[ state ].SetColorMode( USE_OWN_COLOR );
497
498   ResetImageLayers();
499   RelayoutRequest();
500 }
501
502 Actor& Button::GetDecoration( DecorationState state )
503 {
504   return mDecoration[ state ];
505 }
506
507 void Button::SetupContent( Actor& actorToModify, Actor newActor )
508 {
509   if( newActor )
510   {
511     StopTransitionAnimation();
512
513     if( actorToModify && actorToModify.GetParent() )
514     {
515       actorToModify.Unparent();
516     }
517
518     actorToModify = newActor;
519
520     if( actorToModify )
521     {
522       actorToModify.SetAnchorPoint( AnchorPoint::TOP_LEFT );
523       actorToModify.SetParentOrigin( ParentOrigin::TOP_LEFT );
524       actorToModify.SetPosition( 0.f, 0.f );
525     }
526
527     ResetImageLayers();
528   }
529 }
530
531 const Vector4 Button::GetUnselectedColor() const
532 {
533   return mUnselectedColor;
534 }
535
536 void Button::SetColor( const Vector4& color, Button::PaintState selectedState )
537 {
538   Actor& contentActor = mSelectedContent;
539   bool imageFileExists = false;
540
541   if ( selectedState == SelectedState || selectedState == DisabledSelectedState )
542   {
543     mSelectedColor = color;
544     imageFileExists = !GetSelectedImageFilename().empty();
545   }
546   else
547   {
548     mUnselectedColor = color;
549     contentActor = mUnselectedContent;
550     imageFileExists = !GetUnselectedImageFilename().empty();
551   }
552
553   if( contentActor &&  imageFileExists )
554   {
555     // If there is existing unselected content, change the color on it directly.
556     contentActor.SetColor( color );
557   }
558   else
559   {
560     // If there is no existing content, create a new actor to use for flat color.
561     Actor placementActor = Actor::New();
562     Toolkit::RendererFactory rendererFactory = Toolkit::RendererFactory::Get();
563     Toolkit::ControlRenderer colorRenderer;
564
565     Property::Map map;
566     map["rendererType"] = "color";
567     map["mixColor"] = color;
568
569     colorRenderer = rendererFactory.CreateControlRenderer( map );
570     colorRenderer.SetOnStage( placementActor );
571     SetupContent( contentActor, placementActor );
572     contentActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
573   }
574 }
575
576 const Vector4 Button::GetSelectedColor() const
577 {
578   return mSelectedColor;
579 }
580
581 void Button::SetUnselectedImage( const std::string& filename )
582 {
583   Toolkit::ImageView newContent;
584   if( !filename.empty() )
585   {
586     newContent = Toolkit::ImageView::New( filename );
587   }
588   else
589   {
590     newContent = Toolkit::ImageView::New();
591   }
592
593   if( newContent )
594   {
595     SetupContent( mUnselectedContent, newContent );
596
597     mUnselectedContent.SetColor( mUnselectedColor );
598
599     OnUnselectedImageSet();
600     RelayoutRequest();
601   }
602 }
603
604 Actor& Button::GetUnselectedImage()
605 {
606   return mUnselectedContent;
607 }
608
609 void Button::SetSelectedImage( const std::string& filename )
610 {
611   Toolkit::ImageView newContent;
612   if( !filename.empty() )
613   {
614    newContent = Toolkit::ImageView::New( filename );
615   }
616   else
617   {
618     newContent = Toolkit::ImageView::New();
619   }
620
621   if( newContent )
622   {
623     SetupContent( mSelectedContent, newContent );
624
625     mSelectedContent.SetColor( mSelectedColor );
626
627     OnSelectedImageSet();
628     RelayoutRequest();
629   }
630 }
631
632 Actor& Button::GetSelectedImage()
633 {
634   return mSelectedContent;
635 }
636
637 void Button::SetBackgroundImage( const std::string& filename )
638 {
639   SetupContent( mBackgroundContent, Toolkit::ImageView::New( filename ) );
640
641   OnBackgroundImageSet();
642   RelayoutRequest();
643 }
644
645 Actor& Button::GetBackgroundImage()
646 {
647   return mBackgroundContent;
648 }
649
650 void Button::SetSelectedBackgroundImage( const std::string& filename )
651 {
652   SetupContent( mSelectedBackgroundContent, Toolkit::ImageView::New( filename ) );
653
654   OnSelectedBackgroundImageSet();
655   RelayoutRequest();
656 }
657
658 Actor& Button::GetSelectedBackgroundImage()
659 {
660   return mSelectedBackgroundContent;
661 }
662
663 void Button::SetDisabledImage( const std::string& filename )
664 {
665   SetupContent( mDisabledContent, Toolkit::ImageView::New( filename ) );
666
667   OnDisabledImageSet();
668   RelayoutRequest();
669 }
670
671 Actor& Button::GetDisabledImage()
672 {
673   return mDisabledContent;
674 }
675
676 void Button::SetDisabledSelectedImage( const std::string& filename )
677 {
678   SetupContent( mDisabledSelectedContent, Toolkit::ImageView::New( filename ) );
679
680   OnDisabledSelectedImageSet();
681   RelayoutRequest();
682 }
683
684 Actor& Button::GetDisabledSelectedImage()
685 {
686   return mDisabledSelectedContent;
687 }
688
689 void Button::SetDisabledBackgroundImage( const std::string& filename )
690 {
691   SetupContent( mDisabledBackgroundContent, Toolkit::ImageView::New( filename ) );
692
693   OnDisabledBackgroundImageSet();
694   RelayoutRequest();
695 }
696
697 Actor& Button::GetDisabledBackgroundImage()
698 {
699   return mDisabledBackgroundContent;
700 }
701
702 std::string Button::GetUnselectedImageFilename() const
703 {
704   if( mUnselectedContent )
705   {
706     ResourceImage image = ResourceImage::DownCast( mUnselectedContent );
707     if( image )
708     {
709       return image.GetUrl();
710     }
711   }
712   return std::string();
713 }
714
715 std::string Button::GetSelectedImageFilename() const
716 {
717   if( mSelectedContent )
718   {
719     ResourceImage image = ResourceImage::DownCast( mSelectedContent );
720     if( image )
721     {
722       return image.GetUrl();
723     }
724   }
725   return std::string();
726 }
727
728 std::string Button::GetDisabledImageFilename() const
729 {
730   if( mDisabledContent )
731   {
732     ResourceImage image = ResourceImage::DownCast( mDisabledContent );
733     if( image )
734     {
735       return image.GetUrl();
736     }
737   }
738   return std::string();
739 }
740
741 bool Button::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
742 {
743   bool ret = false;
744
745   Dali::BaseHandle handle( object );
746
747   Toolkit::Button button = Toolkit::Button::DownCast( handle );
748
749   DALI_ASSERT_ALWAYS( button );
750
751   if( 0 == strcmp( actionName.c_str(), ACTION_BUTTON_CLICK ) )
752   {
753     ret = GetImplementation( button ).DoClickAction( attributes );
754   }
755
756   return ret;
757 }
758
759 bool Button::DoClickAction( const Property::Map& attributes )
760 {
761   // Prevents the button signals from doing a recursive loop by sending an action
762   // and re-emitting the signals.
763   if( !mClickActionPerforming )
764   {
765     mClickActionPerforming = true;
766     OnButtonDown();
767     mState = ButtonDown;
768     OnButtonUp();
769     mClickActionPerforming = false;
770
771     return true;
772   }
773
774   return false;
775 }
776
777 void Button::OnButtonDown()
778 {
779   if( !mTogglableButton )
780   {
781     Pressed();
782
783     if( mAutoRepeating )
784     {
785       SetUpTimer( mInitialAutoRepeatingDelay );
786     }
787   }
788
789   // The pressed signal should be emitted regardless of toggle mode.
790   Toolkit::Button handle( GetOwner() );
791   mPressedSignal.Emit( handle );
792 }
793
794 void Button::OnButtonUp()
795 {
796   if( ButtonDown == mState )
797   {
798     if( mTogglableButton )
799     {
800       SetSelected( !mSelected );
801     }
802     else
803     {
804       Released();
805
806       if( mAutoRepeating )
807       {
808         mAutoRepeatingTimer.Reset();
809       }
810     }
811
812     // The clicked and released signals should be emitted regardless of toggle mode.
813     Toolkit::Button handle( GetOwner() );
814     mReleasedSignal.Emit( handle );
815     mClickedSignal.Emit( handle );
816   }
817 }
818
819 void Button::OnTouchPointLeave()
820 {
821   if( ButtonDown == mState )
822   {
823     if( !mTogglableButton )
824     {
825       Released();
826
827       if( mAutoRepeating )
828       {
829         mAutoRepeatingTimer.Reset();
830       }
831     }
832
833     // The released signal should be emitted regardless of toggle mode.
834     Toolkit::Button handle( GetOwner() );
835     mReleasedSignal.Emit( handle );
836   }
837 }
838
839 void Button::OnTouchPointInterrupted()
840 {
841   OnTouchPointLeave();
842 }
843
844 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
845 {
846   return mPressedSignal;
847 }
848
849 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
850 {
851   return mReleasedSignal;
852 }
853
854 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
855 {
856   return mClickedSignal;
857 }
858
859 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
860 {
861   return mStateChangedSignal;
862 }
863
864 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
865 {
866   Dali::BaseHandle handle( object );
867
868   bool connected( true );
869   Toolkit::Button button = Toolkit::Button::DownCast( handle );
870
871   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
872   {
873     button.PressedSignal().Connect( tracker, functor );
874   }
875   else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
876   {
877     button.ReleasedSignal().Connect( tracker, functor );
878   }
879   else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
880   {
881     button.ClickedSignal().Connect( tracker, functor );
882   }
883   else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
884   {
885     button.StateChangedSignal().Connect( tracker, functor );
886   }
887   else
888   {
889     // signalName does not match any signal
890     connected = false;
891   }
892
893   return connected;
894 }
895
896 void Button::OnInitialize()
897 {
898   Actor self = Self();
899
900   mTapDetector = TapGestureDetector::New();
901   mTapDetector.Attach( self );
902   mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
903
904   self.SetKeyboardFocusable( true );
905
906   self.TouchSignal().Connect( this, &Button::OnTouch );
907 }
908
909 bool Button::OnAccessibilityActivated()
910 {
911   return OnKeyboardEnter();
912 }
913
914 bool Button::OnKeyboardEnter()
915 {
916   // When the enter key is pressed, or button is activated, the click action is performed.
917   Property::Map attributes;
918   bool ret = DoClickAction( attributes );
919
920   return ret;
921 }
922
923 void Button::OnStageDisconnection()
924 {
925   if( ButtonDown == mState )
926   {
927     if( !mTogglableButton )
928     {
929       Released();
930
931       if( mAutoRepeating )
932       {
933         mAutoRepeatingTimer.Reset();
934       }
935     }
936   }
937
938   mState = ButtonUp;
939
940   Control::OnStageDisconnection();
941 }
942
943 bool Button::OnTouch( Actor actor, const TouchData& touch )
944 {
945   // Only events are processed when the button is not disabled and the touch event has only
946   // one touch point.
947   if( ( !mDisabled ) && ( 1 == touch.GetPointCount() ) )
948   {
949     switch( touch.GetState( 0 ) )
950     {
951       case PointState::DOWN:
952       {
953         OnButtonDown(); // Notification for derived classes.
954
955         // Sets the button state to ButtonDown.
956         mState = ButtonDown;
957         break;
958       }
959       case PointState::UP:
960       {
961         OnButtonUp(); // Notification for derived classes.
962
963         // Sets the button state to ButtonUp.
964         mState = ButtonUp;
965         break;
966       }
967       case PointState::INTERRUPTED:
968       {
969         OnTouchPointInterrupted(); // Notification for derived classes.
970
971         // Sets the button state to the default (ButtonUp).
972         mState = ButtonUp;
973         break;
974       }
975       case PointState::LEAVE:
976       {
977         OnTouchPointLeave(); // Notification for derived classes.
978
979         // Sets the button state to the default (ButtonUp).
980         mState = ButtonUp;
981         break;
982       }
983       case PointState::MOTION:
984       case PointState::STATIONARY: // FALLTHROUGH
985       {
986         // Nothing to do
987         break;
988       }
989     }
990   }
991   else if( 1 < touch.GetPointCount() )
992   {
993     OnTouchPointLeave(); // Notification for derived classes.
994
995     // Sets the button state to the default (ButtonUp).
996     mState = ButtonUp;
997   }
998
999   return false;
1000 }
1001
1002 void Button::OnTap(Actor actor, const TapGesture& tap)
1003 {
1004   // Do nothing.
1005 }
1006
1007 void Button::SetUpTimer( float delay )
1008 {
1009   mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
1010   mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
1011   mAutoRepeatingTimer.Start();
1012 }
1013
1014 bool Button::AutoRepeatingSlot()
1015 {
1016   bool consumed = false;
1017   if( !mDisabled )
1018   {
1019     // Restart the autorepeat timer.
1020     SetUpTimer( mNextAutoRepeatingDelay );
1021
1022     Pressed();
1023
1024     Toolkit::Button handle( GetOwner() );
1025
1026     //Emit signal.
1027     consumed = mReleasedSignal.Emit( handle );
1028     consumed |= mClickedSignal.Emit( handle );
1029     consumed |= mPressedSignal.Emit( handle );
1030  }
1031
1032   return consumed;
1033 }
1034
1035 void Button::Pressed()
1036 {
1037   if( mPaintState == UnselectedState )
1038   {
1039     StopTransitionAnimation();
1040
1041     // Notifies the derived class the button has been pressed.
1042     OnPressed();
1043
1044     //Layer Order
1045     //(4) mSelectedContent (Inserted)
1046     //(3) mUnselectedContent
1047     //(2) mSelectedBackgroundContent (Inserted)
1048     //(1) mBackgroundContent
1049
1050     AddButtonImage( mBackgroundContent );
1051     TransitionButtonImage( mSelectedBackgroundContent );
1052     AddButtonImage( mUnselectedContent );
1053     TransitionButtonImage( mSelectedContent );
1054
1055     AddButtonImage( mDecoration[ UNSELECTED_DECORATION ] );
1056     TransitionButtonImage( mDecoration[ SELECTED_DECORATION ] );
1057     ReAddLabel();
1058
1059     TransitionOut( mDecoration[ UNSELECTED_DECORATION ] );
1060     TransitionOut( mUnselectedContent );
1061     TransitionOut( mDisabledContent );
1062     TransitionOut( mDisabledSelectedContent );
1063     TransitionOut( mDisabledBackgroundContent );
1064
1065     mPaintState = SelectedState;
1066
1067     StartTransitionAnimation();
1068   }
1069 }
1070
1071 void Button::Released()
1072 {
1073   if( mPaintState == SelectedState )
1074   {
1075     StopTransitionAnimation();
1076
1077     // Notifies the derived class the button has been released.
1078     OnReleased();
1079
1080     //Layer Order
1081     //(3) mUnselectedContent (Inserted)
1082     //(2) mSelectedContent
1083     //(1) mBackgroundContent
1084
1085     AddButtonImage( mBackgroundContent );
1086     AddButtonImage( mSelectedContent );
1087     TransitionButtonImage( mUnselectedContent );
1088
1089     AddButtonImage( mDecoration[ SELECTED_DECORATION ] );
1090     TransitionButtonImage( mDecoration[ UNSELECTED_DECORATION ] );
1091     ReAddLabel();
1092
1093     TransitionOut( mDecoration[ SELECTED_DECORATION ] );
1094     TransitionOut( mSelectedContent );
1095     TransitionOut( mSelectedBackgroundContent );
1096     TransitionOut( mDisabledContent );
1097     TransitionOut( mDisabledSelectedContent );
1098     TransitionOut( mDisabledBackgroundContent );
1099
1100     mPaintState = UnselectedState;
1101
1102     StartTransitionAnimation();
1103   }
1104 }
1105
1106 Button::ButtonState Button::GetState()
1107 {
1108   return mState;
1109 }
1110
1111 Button::PaintState Button::GetPaintState()
1112 {
1113   return mPaintState;
1114 }
1115
1116 void Button::PrepareAddButtonImage( Actor& actor )
1117 {
1118   if( actor )
1119   {
1120     Self().Add( actor );
1121     PrepareForTranstionOut( actor );
1122   }
1123 }
1124
1125 void Button::TransitionButtonImage( Actor& actor )
1126 {
1127   if( actor )
1128   {
1129     if( !actor.GetParent() )
1130     {
1131       Self().Add( actor );
1132     }
1133
1134     OnTransitionIn( actor );
1135   }
1136 }
1137
1138 void Button::AddButtonImage( Actor& actor )
1139 {
1140   if( actor )
1141   {
1142     Self().Add( actor );
1143   }
1144 }
1145
1146 void Button::ReAddLabel()
1147 {
1148   if( mLabel )
1149   {
1150     mLabel.Unparent();
1151     Self().Add( mLabel );
1152   }
1153 }
1154
1155 void Button::RemoveButtonImage( Actor& actor )
1156 {
1157   if( actor )
1158   {
1159     if( actor.GetParent() )
1160     {
1161       Self().Remove( actor );
1162     }
1163     PrepareForTranstionIn( actor );
1164   }
1165 }
1166
1167 unsigned int Button::FindChildIndex( Actor& actor )
1168 {
1169   Actor self = Self();
1170   unsigned int childrenNum = self.GetChildCount();
1171
1172   for( unsigned int i = 0; i < childrenNum; i++ )
1173   {
1174     Actor child = self.GetChildAt( i );
1175     if( child == actor )
1176     {
1177       return i;
1178     }
1179   }
1180
1181   return childrenNum;
1182 }
1183
1184 void Button::TransitionOut( Actor actor )
1185 {
1186   OnTransitionOut( actor );
1187 }
1188
1189 void Button::ResetImageLayers()
1190 {
1191   // Ensure that all layers are in the correct order and state according to the paint state
1192
1193   switch( mPaintState )
1194   {
1195     case UnselectedState:
1196     {
1197       //Layer Order
1198       //(2) mUnselectedContent
1199       //(1) mBackgroundContent
1200
1201       RemoveButtonImage( mDecoration[ SELECTED_DECORATION ] );
1202       RemoveButtonImage( mSelectedContent );
1203       RemoveButtonImage( mSelectedBackgroundContent );
1204       RemoveButtonImage( mDisabledContent );
1205       RemoveButtonImage( mDisabledSelectedContent );
1206       RemoveButtonImage( mDisabledBackgroundContent );
1207
1208       PrepareAddButtonImage( mBackgroundContent );
1209       PrepareAddButtonImage( mUnselectedContent );
1210
1211       PrepareAddButtonImage( mDecoration[ UNSELECTED_DECORATION ] );
1212       ReAddLabel();
1213       break;
1214     }
1215     case SelectedState:
1216     {
1217       //Layer Order
1218       //(3) mSelectedContent
1219       //(2) mSelectedBackgroundContent
1220       //(1) mBackgroundContent
1221
1222       RemoveButtonImage( mDecoration[ UNSELECTED_DECORATION ] );
1223       RemoveButtonImage( mUnselectedContent );
1224       RemoveButtonImage( mDisabledContent );
1225       RemoveButtonImage( mDisabledSelectedContent );
1226       RemoveButtonImage( mDisabledBackgroundContent );
1227
1228       PrepareAddButtonImage( mBackgroundContent );
1229       PrepareAddButtonImage( mSelectedBackgroundContent );
1230       PrepareAddButtonImage( mSelectedContent );
1231
1232       PrepareAddButtonImage( mDecoration[ SELECTED_DECORATION ] );
1233       ReAddLabel();
1234       break;
1235     }
1236     case DisabledUnselectedState:
1237     {
1238       //Layer Order
1239       //(2) mDisabledContent
1240       //(1) mDisabledBackgroundContent
1241
1242       RemoveButtonImage( mDecoration[ UNSELECTED_DECORATION ] );
1243       RemoveButtonImage( mUnselectedContent );
1244       RemoveButtonImage( mBackgroundContent );
1245       RemoveButtonImage( mDecoration[ SELECTED_DECORATION ] );
1246       RemoveButtonImage( mSelectedContent );
1247       RemoveButtonImage( mDisabledSelectedContent );
1248       RemoveButtonImage( mSelectedBackgroundContent );
1249
1250       PrepareAddButtonImage( mDisabledBackgroundContent ? mDisabledBackgroundContent : mBackgroundContent );
1251       PrepareAddButtonImage( mDisabledContent ? mDisabledContent : mUnselectedContent );
1252
1253       PrepareAddButtonImage( mDecoration[ UNSELECTED_DECORATION ] );
1254       ReAddLabel();
1255       break;
1256     }
1257     case DisabledSelectedState:
1258     {
1259       //Layer Order
1260       // (2) mDisabledSelectedContent
1261       // (1) mDisabledBackgroundContent
1262
1263       RemoveButtonImage( mDecoration[ UNSELECTED_DECORATION ] );
1264       RemoveButtonImage( mUnselectedContent );
1265       RemoveButtonImage( mDecoration[ SELECTED_DECORATION ] );
1266       RemoveButtonImage( mSelectedContent );
1267       RemoveButtonImage( mBackgroundContent );
1268       RemoveButtonImage( mSelectedBackgroundContent );
1269       RemoveButtonImage( mDisabledContent );
1270
1271       if( mDisabledBackgroundContent )
1272       {
1273         PrepareAddButtonImage( mDisabledBackgroundContent );
1274       }
1275       else
1276       {
1277         PrepareAddButtonImage( mBackgroundContent );
1278         PrepareAddButtonImage( mSelectedBackgroundContent );
1279       }
1280
1281       PrepareAddButtonImage( mDisabledSelectedContent ? mDisabledSelectedContent : mSelectedContent );
1282
1283       PrepareAddButtonImage( mDecoration[ SELECTED_DECORATION ] );
1284       ReAddLabel();
1285       break;
1286     }
1287   }
1288 }
1289
1290 void Button::StartTransitionAnimation()
1291 {
1292   if( mTransitionAnimation )
1293   {
1294     mTransitionAnimation.Play();
1295   }
1296   else
1297   {
1298     ResetImageLayers();
1299   }
1300 }
1301
1302 void Button::StopTransitionAnimation()
1303 {
1304   if( mTransitionAnimation )
1305   {
1306     mTransitionAnimation.Clear();
1307     mTransitionAnimation.Reset();
1308   }
1309 }
1310
1311 Dali::Animation Button::GetTransitionAnimation()
1312 {
1313   if( !mTransitionAnimation )
1314   {
1315     mTransitionAnimation = Dali::Animation::New( GetAnimationTime() );
1316     mTransitionAnimation.FinishedSignal().Connect( this, &Button::TransitionAnimationFinished );
1317   }
1318
1319   return mTransitionAnimation;
1320 }
1321
1322 void Button::TransitionAnimationFinished( Dali::Animation& source )
1323 {
1324   StopTransitionAnimation();
1325   ResetImageLayers();
1326 }
1327
1328 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
1329 {
1330   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1331
1332   if ( button )
1333   {
1334     switch ( index )
1335     {
1336       case Toolkit::Button::Property::DISABLED:
1337       {
1338         GetImplementation( button ).SetDisabled( value.Get< bool >() );
1339         break;
1340       }
1341
1342       case Toolkit::Button::Property::AUTO_REPEATING:
1343       {
1344         GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
1345         break;
1346       }
1347
1348       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1349       {
1350         GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
1351         break;
1352       }
1353
1354       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1355       {
1356         GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
1357         break;
1358       }
1359
1360       case Toolkit::Button::Property::TOGGLABLE:
1361       {
1362         GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
1363         break;
1364       }
1365
1366       case Toolkit::Button::Property::SELECTED:
1367       {
1368         GetImplementation( button ).SetSelected( value.Get< bool >() );
1369         break;
1370       }
1371
1372       case Toolkit::Button::Property::UNSELECTED_STATE_IMAGE:
1373       {
1374         GetImplementation( button ).SetUnselectedImage( value.Get< std::string >() );
1375         break;
1376       }
1377
1378       case Toolkit::Button::Property::SELECTED_STATE_IMAGE:
1379       {
1380         GetImplementation( button ).SetSelectedImage( value.Get< std::string >() );
1381         break;
1382       }
1383
1384       case Toolkit::Button::Property::DISABLED_STATE_IMAGE:
1385       {
1386         GetImplementation( button ).SetDisabledImage( value.Get< std::string >() );
1387         break;
1388       }
1389
1390       case Toolkit::Button::Property::UNSELECTED_COLOR:
1391       {
1392         GetImplementation( button ).SetColor( value.Get< Vector4 >(), UnselectedState );
1393         break;
1394       }
1395
1396       case Toolkit::Button::Property::SELECTED_COLOR:
1397       {
1398         GetImplementation( button ).SetColor( value.Get< Vector4 >(), SelectedState );
1399         break;
1400       }
1401
1402       case Toolkit::Button::Property::LABEL_TEXT:
1403       {
1404         GetImplementation( button ).SetLabelText( value.Get< std::string >() );
1405         break;
1406       }
1407
1408       case Toolkit::Button::Property::LABEL:
1409       {
1410         // Get a Property::Map from the property if possible.
1411         Property::Map setPropertyMap;
1412         if( value.Get( setPropertyMap ) )
1413         {
1414           GetImplementation( button ).ModifyLabel( setPropertyMap );
1415         }
1416       }
1417       break;
1418     }
1419   }
1420 }
1421
1422 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
1423 {
1424   Property::Value value;
1425
1426   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1427
1428   if ( button )
1429   {
1430     switch ( propertyIndex )
1431     {
1432       case Toolkit::Button::Property::DISABLED:
1433       {
1434         value = GetImplementation( button ).mDisabled;
1435         break;
1436       }
1437
1438       case Toolkit::Button::Property::AUTO_REPEATING:
1439       {
1440         value = GetImplementation( button ).mAutoRepeating;
1441         break;
1442       }
1443
1444       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1445       {
1446         value = GetImplementation( button ).mInitialAutoRepeatingDelay;
1447         break;
1448       }
1449
1450       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1451       {
1452         value = GetImplementation( button ).mNextAutoRepeatingDelay;
1453         break;
1454       }
1455
1456       case Toolkit::Button::Property::TOGGLABLE:
1457       {
1458         value = GetImplementation( button ).mTogglableButton;
1459         break;
1460       }
1461
1462       case Toolkit::Button::Property::SELECTED:
1463       {
1464         value = GetImplementation( button ).mSelected;
1465         break;
1466       }
1467
1468       case Toolkit::Button::Property::UNSELECTED_STATE_IMAGE:
1469       {
1470         value = GetImplementation( button ).GetUnselectedImageFilename();
1471         break;
1472       }
1473
1474       case Toolkit::Button::Property::SELECTED_STATE_IMAGE:
1475       {
1476         value = GetImplementation( button ).GetSelectedImageFilename();
1477         break;
1478       }
1479
1480       case Toolkit::Button::Property::DISABLED_STATE_IMAGE:
1481       {
1482         value = GetImplementation( button ).GetDisabledImageFilename();
1483         break;
1484       }
1485
1486       case Toolkit::Button::Property::UNSELECTED_COLOR:
1487       {
1488         value = GetImplementation( button ).GetUnselectedColor();
1489         break;
1490       }
1491
1492       case Toolkit::Button::Property::SELECTED_COLOR:
1493       {
1494         value = GetImplementation( button ).GetSelectedColor();
1495         break;
1496       }
1497
1498       case Toolkit::Button::Property::LABEL_TEXT:
1499       {
1500         value = GetImplementation( button ).GetLabelText();
1501         break;
1502       }
1503
1504       case Toolkit::Button::Property::LABEL:
1505       {
1506         Property::Map emptyMap;
1507         value = emptyMap;
1508         break;
1509       }
1510     }
1511   }
1512
1513   return value;
1514 }
1515
1516 // Deprecated API
1517
1518 void Button::SetLabel( Actor label )
1519 {
1520   if( mLabel != label )
1521   {
1522     if( mLabel && mLabel.GetParent() )
1523     {
1524       mLabel.GetParent().Remove( mLabel );
1525     }
1526
1527     mLabel = label;
1528     mLabel.SetPosition( 0.0f, 0.0f );
1529
1530     // label should be the top of the button
1531     Self().Add( mLabel );
1532
1533     ResetImageLayers();
1534     OnLabelSet( true );
1535
1536     RelayoutRequest();
1537   }
1538 }
1539
1540 void Button::SetButtonImage( Actor image )
1541 {
1542   if( image )
1543   {
1544     StopTransitionAnimation();
1545
1546     SetupContent( mUnselectedContent, image );
1547
1548     OnUnselectedImageSet();
1549     RelayoutRequest();
1550   }
1551 }
1552
1553 void Button::SetSelectedImage( Actor image )
1554 {
1555   if( image )
1556   {
1557     StopTransitionAnimation();
1558
1559     SetupContent( mSelectedContent, image );
1560
1561     OnSelectedImageSet();
1562     RelayoutRequest();
1563   }
1564 }
1565
1566 void Button::SetBackgroundImage( Actor image )
1567 {
1568   if( image )
1569   {
1570     StopTransitionAnimation();
1571
1572     SetupContent( mBackgroundContent, image );
1573
1574     OnBackgroundImageSet();
1575     RelayoutRequest();
1576   }
1577 }
1578
1579 void Button::SetSelectedBackgroundImage( Actor image )
1580 {
1581   if( image )
1582   {
1583     StopTransitionAnimation();
1584
1585     SetupContent( mSelectedBackgroundContent, image );
1586
1587     OnSelectedBackgroundImageSet();
1588     RelayoutRequest();
1589   }
1590 }
1591
1592 void Button::SetDisabledImage( Actor image )
1593 {
1594   if( image )
1595   {
1596     StopTransitionAnimation();
1597
1598     SetupContent( mDisabledContent, image );
1599
1600     OnDisabledImageSet();
1601     RelayoutRequest();
1602   }
1603 }
1604
1605 void Button::SetDisabledSelectedImage( Actor image )
1606 {
1607   if( image )
1608   {
1609     StopTransitionAnimation();
1610
1611     SetupContent( mDisabledSelectedContent, image );
1612
1613     OnDisabledSelectedImageSet();
1614     RelayoutRequest();
1615   }
1616 }
1617
1618 void Button::SetDisabledBackgroundImage( Actor image )
1619 {
1620   if( image )
1621   {
1622     StopTransitionAnimation();
1623
1624     SetupContent( mDisabledBackgroundContent, image );
1625
1626     OnDisabledBackgroundImageSet();
1627     RelayoutRequest();
1628   }
1629 }
1630
1631 Actor Button::GetButtonImage() const
1632 {
1633   return mUnselectedContent;
1634 }
1635
1636 Actor Button::GetSelectedImage() const
1637 {
1638   return mSelectedContent;
1639 }
1640
1641
1642 } // namespace Internal
1643
1644 } // namespace Toolkit
1645
1646 } // namespace Dali