46159edcf86272bce1c15a00f3e9795b7cc9142f
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / buttons / push-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
20 #include "push-button-impl.h"
21
22 // EXTERNAL INCLUDES
23
24 #include <algorithm>
25
26 // INTERNAL INCLUDES
27
28 #include "push-button-default-painter-impl.h"
29
30 #include <dali-toolkit/public-api/controls/text-view/text-view.h>
31 #include <dali-toolkit/internal/controls/relayout-helper.h>
32
33 namespace Dali
34 {
35
36 namespace Toolkit
37 {
38
39 const Property::Index PushButton::PROPERTY_AUTO_REPEATING               = Internal::Button::BUTTON_PROPERTY_END_INDEX + 1;
40 const Property::Index PushButton::PROPERTY_INITIAL_AUTO_REPEATING_DELAY = Internal::Button::BUTTON_PROPERTY_END_INDEX + 2;
41 const Property::Index PushButton::PROPERTY_NEXT_AUTO_REPEATING_DELAY    = Internal::Button::BUTTON_PROPERTY_END_INDEX + 3;
42 const Property::Index PushButton::PROPERTY_TOGGLABLE                    = Internal::Button::BUTTON_PROPERTY_END_INDEX + 4;
43 const Property::Index PushButton::PROPERTY_TOGGLE                       = Internal::Button::BUTTON_PROPERTY_END_INDEX + 5;
44 const Property::Index PushButton::PROPERTY_NORMAL_STATE_ACTOR           = Internal::Button::BUTTON_PROPERTY_END_INDEX + 6;
45 const Property::Index PushButton::PROPERTY_PRESSED_STATE_ACTOR          = Internal::Button::BUTTON_PROPERTY_END_INDEX + 7;
46 const Property::Index PushButton::PROPERTY_DIMMED_STATE_ACTOR           = Internal::Button::BUTTON_PROPERTY_END_INDEX + 8;
47 const Property::Index PushButton::PROPERTY_LABEL_ACTOR                  = Internal::Button::BUTTON_PROPERTY_END_INDEX + 9;
48
49 namespace Internal
50 {
51
52 namespace
53 {
54
55 BaseHandle Create()
56 {
57   return Toolkit::PushButton::New();
58 }
59
60 TypeRegistration typeRegistration( typeid(Toolkit::PushButton), typeid(Toolkit::Button), Create );
61
62 SignalConnectorType signalConnector1( typeRegistration, Toolkit::PushButton::SIGNAL_TOGGLED , &PushButton::DoConnectSignal );
63 SignalConnectorType signalConnector2( typeRegistration, Toolkit::PushButton::SIGNAL_PRESSED , &PushButton::DoConnectSignal );
64 SignalConnectorType signalConnector3( typeRegistration, Toolkit::PushButton::SIGNAL_RELEASED, &PushButton::DoConnectSignal );
65
66 TypeAction action1( typeRegistration, Toolkit::PushButton::ACTION_PUSH_BUTTON_CLICK, &PushButton::DoAction );
67
68 PropertyRegistration property1( typeRegistration, "auto-repeating",               Toolkit::PushButton::PROPERTY_AUTO_REPEATING,               Property::BOOLEAN, &PushButton::SetProperty, &PushButton::GetProperty );
69 PropertyRegistration property2( typeRegistration, "initial-auto-repeating-delay", Toolkit::PushButton::PROPERTY_INITIAL_AUTO_REPEATING_DELAY, Property::FLOAT,   &PushButton::SetProperty, &PushButton::GetProperty );
70 PropertyRegistration property3( typeRegistration, "next-auto-repeating-delay",    Toolkit::PushButton::PROPERTY_NEXT_AUTO_REPEATING_DELAY,    Property::FLOAT,   &PushButton::SetProperty, &PushButton::GetProperty );
71 PropertyRegistration property4( typeRegistration, "togglable",                    Toolkit::PushButton::PROPERTY_TOGGLABLE,                    Property::BOOLEAN, &PushButton::SetProperty, &PushButton::GetProperty );
72 PropertyRegistration property5( typeRegistration, "toggle",                       Toolkit::PushButton::PROPERTY_TOGGLE,                       Property::BOOLEAN, &PushButton::SetProperty, &PushButton::GetProperty );
73 PropertyRegistration property6( typeRegistration, "normal-state-actor",           Toolkit::PushButton::PROPERTY_NORMAL_STATE_ACTOR,           Property::MAP,     &PushButton::SetProperty, &PushButton::GetProperty );
74 PropertyRegistration property7( typeRegistration, "pressed-state-actor",          Toolkit::PushButton::PROPERTY_PRESSED_STATE_ACTOR,          Property::MAP,     &PushButton::SetProperty, &PushButton::GetProperty );
75 PropertyRegistration property8( typeRegistration, "dimmed-state-actor",           Toolkit::PushButton::PROPERTY_DIMMED_STATE_ACTOR,           Property::MAP,     &PushButton::SetProperty, &PushButton::GetProperty );
76 PropertyRegistration property9( typeRegistration, "label-actor",                  Toolkit::PushButton::PROPERTY_LABEL_ACTOR,                  Property::MAP,     &PushButton::SetProperty, &PushButton::GetProperty );
77
78 } // unnamed namespace
79
80 namespace
81 {
82
83 const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f );
84 const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f );
85
86 const float TEXT_PADDING = 12.0f;
87
88 // Helper function used to cast a ButtonPainter to PushButtonDefaultPainter
89 PushButtonDefaultPainterPtr GetPushButtonPainter( Dali::Toolkit::Internal::ButtonPainterPtr painter )
90 {
91   return static_cast<PushButtonDefaultPainter*>( painter.Get() );
92 }
93
94 /**
95  * Find the first image actor in the actor hierarchy
96  */
97 ImageActor FindImageActor( Actor root )
98 {
99   ImageActor imageActor = ImageActor::DownCast( root );
100   if( !imageActor && root )
101   {
102     for( unsigned int i = 0, numChildren = root.GetChildCount(); i < numChildren; ++i )
103     {
104       ImageActor childImageActor = FindImageActor( root.GetChildAt( i ) );
105       if( childImageActor )
106       {
107         return childImageActor;
108       }
109     }
110   }
111
112   return imageActor;
113 }
114
115
116 } // unnamed namespace
117
118 Dali::Toolkit::PushButton PushButton::New()
119 {
120   // Create the implementation, temporarily owned on stack
121   IntrusivePtr< PushButton > internalPushButton = new PushButton();
122
123   // Pass ownership to CustomActor
124   Dali::Toolkit::PushButton pushButton( *internalPushButton );
125
126   // Second-phase init of the implementation
127   // This can only be done after the CustomActor connection has been made...
128   internalPushButton->Initialize();
129
130   return pushButton;
131 }
132
133 void PushButton::SetAutoRepeating( bool autoRepeating )
134 {
135   mAutoRepeating = autoRepeating;
136
137   // An autorepeating button can't be a toggle button.
138   if( autoRepeating )
139   {
140     mToggleButton = false;
141     if( mToggled )
142     {
143       // Emit a signal is not wanted, only change the appearance.
144       Toolkit::PushButton handle( GetOwner() );
145       GetPushButtonPainter( mPainter )->Toggled( handle );
146       mToggled = false;
147     }
148   }
149
150   // Notifies the painter.
151   GetPushButtonPainter( mPainter )->SetAutoRepeating( mAutoRepeating );
152 }
153
154 bool PushButton::IsAutoRepeating() const
155 {
156   return mAutoRepeating;
157 }
158
159 void PushButton::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
160 {
161   DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
162   mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
163 }
164
165 float PushButton::GetInitialAutoRepeatingDelay() const
166 {
167   return mInitialAutoRepeatingDelay;
168 }
169
170 void PushButton::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
171 {
172   DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
173   mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
174 }
175
176 float PushButton::GetNextAutoRepeatingDelay() const
177 {
178   return mNextAutoRepeatingDelay;
179 }
180
181 void PushButton::SetToggleButton( bool toggle )
182 {
183   mToggleButton = toggle;
184
185   // A toggle button can't be an autorepeating button.
186   if( toggle )
187   {
188     mAutoRepeating = false;
189
190     // Notifies the painter.
191     GetPushButtonPainter( mPainter )->SetAutoRepeating( mAutoRepeating );
192   }
193 }
194
195 bool PushButton::IsToggleButton() const
196 {
197   return mToggleButton;
198 }
199
200 void PushButton::SetToggled( bool toggle )
201 {
202   if( !mDimmed && mToggleButton && ( toggle != mToggled ) )
203   {
204     mToggled = toggle;
205
206     Toolkit::PushButton handle( GetOwner() );
207
208     // Notifies the painter the button has been toggled.
209     GetPushButtonPainter( mPainter )->Toggled( handle );
210
211     // Emit signal.
212     mToggledSignalV2.Emit( handle, mToggled );
213   }
214 }
215
216 bool PushButton::IsToggled() const
217 {
218   return mToggleButton && mToggled;
219 }
220
221 void PushButton::SetButtonImage( Image image )
222 {
223   SetButtonImage( ImageActor::New( image ) );
224 }
225
226 void PushButton::SetButtonImage( Actor image )
227 {
228   Toolkit::PushButton handle( GetOwner() );
229   GetPushButtonPainter( mPainter )->SetButtonImage( handle, image );
230 }
231
232 Actor& PushButton::GetButtonImage()
233 {
234   return mButtonImage;
235 }
236
237 Actor PushButton::GetButtonImage() const
238 {
239   return mButtonImage;
240 }
241
242 void PushButton::SetBackgroundImage( Image image )
243 {
244   SetBackgroundImage( ImageActor::New( image ) );
245 }
246
247 void PushButton::SetBackgroundImage( Actor image )
248 {
249   Toolkit::PushButton handle( GetOwner() );
250   GetPushButtonPainter( mPainter )->SetBackgroundImage( handle, image );
251 }
252
253 Actor& PushButton::GetBackgroundImage()
254 {
255   return mBackgroundImage;
256 }
257
258 Actor PushButton::GetBackgroundImage() const
259 {
260   return mBackgroundImage;
261 }
262
263 void PushButton::SetPressedImage( Image image )
264 {
265   SetPressedImage( ImageActor::New( image ) );
266 }
267
268 void PushButton::SetPressedImage( Actor image )
269 {
270   Toolkit::PushButton handle( GetOwner() );
271   GetPushButtonPainter( mPainter )->SetPressedImage( handle, image );
272 }
273
274 Actor& PushButton::GetPressedImage()
275 {
276   return mPressedImage;
277 }
278
279 Actor PushButton::GetPressedImage() const
280 {
281   return mPressedImage;
282 }
283
284 void PushButton::SetDimmedBackgroundImage( Image image )
285 {
286   SetDimmedBackgroundImage( ImageActor::New( image ) );
287 }
288
289 void PushButton::SetDimmedBackgroundImage( Actor image )
290 {
291   Toolkit::PushButton handle( GetOwner() );
292   GetPushButtonPainter( mPainter )->SetDimmedBackgroundImage( handle, image );
293 }
294
295 Actor& PushButton::GetDimmedBackgroundImage()
296 {
297   return mDimmedBackgroundImage;
298 }
299
300 Actor PushButton::GetDimmedBackgroundImage() const
301 {
302   return mDimmedBackgroundImage;
303 }
304
305 void PushButton::SetDimmedImage( Image image )
306 {
307   SetDimmedImage( ImageActor::New( image ) );
308 }
309
310 void PushButton::SetDimmedImage( Actor image )
311 {
312   Toolkit::PushButton handle( GetOwner() );
313   GetPushButtonPainter( mPainter )->SetDimmedImage( handle, image );
314 }
315
316 Actor& PushButton::GetDimmedImage()
317 {
318   return mDimmedImage;
319 }
320
321 Actor PushButton::GetDimmedImage() const
322 {
323   return mDimmedImage;
324 }
325
326 void PushButton::SetLabelText( const std::string& text )
327 {
328   Toolkit::TextView textView ( Toolkit::TextView::New( text ) );
329   textView.SetWidthExceedPolicy( Toolkit::TextView::ShrinkToFit ); // Make sure our text always fits inside the button
330   SetLabelText( textView );
331 }
332
333 void PushButton::SetLabelText( Actor text )
334 {
335   Toolkit::PushButton handle( GetOwner() );
336   GetPushButtonPainter( mPainter )->SetLabelText( handle, text );
337 }
338
339 Actor& PushButton::GetLabel()
340 {
341   return mLabel;
342 }
343
344 Actor PushButton::GetLabelText() const
345 {
346   return mLabel;
347 }
348
349 Actor& PushButton::GetFadeOutBackgroundImage()
350 {
351   return mFadeOutBackgroundImage;
352 }
353
354 Actor& PushButton::GetFadeOutButtonImage()
355 {
356   return mFadeOutButtonImage;
357 }
358
359 Toolkit::PushButton::ToggledSignalV2& PushButton::ToggledSignal()
360 {
361   return mToggledSignalV2;
362 }
363
364 Toolkit::PushButton::PressedSignalV2& PushButton::PressedSignal()
365 {
366   return mPressedSignalV2;
367 }
368
369 Toolkit::PushButton::ReleasedSignalV2& PushButton::ReleasedSignal()
370 {
371   return mReleasedSignalV2;
372 }
373
374 bool PushButton::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
375 {
376   Dali::BaseHandle handle( object );
377
378   bool connected( true );
379   Toolkit::PushButton button = Toolkit::PushButton::DownCast(handle);
380
381   if( Toolkit::PushButton::SIGNAL_TOGGLED == signalName )
382   {
383     button.ToggledSignal().Connect( tracker, functor );
384   }
385   else if( Toolkit::PushButton::SIGNAL_PRESSED == signalName )
386   {
387     button.PressedSignal().Connect( tracker, functor );
388   }
389   else if( Toolkit::PushButton::SIGNAL_RELEASED == signalName )
390   {
391     button.ReleasedSignal().Connect( tracker, functor );
392   }
393   else
394   {
395     // signalName does not match any signal
396     connected = false;
397   }
398
399   return connected;
400 }
401
402 void PushButton::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
403 {
404   Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( Dali::BaseHandle( object ) );
405
406   if ( pushButton )
407   {
408     PushButton& pushButtonImpl( GetImplementation( pushButton ) );
409
410     switch ( propertyIndex )
411     {
412       case Toolkit::PushButton::PROPERTY_AUTO_REPEATING:
413       {
414         pushButtonImpl.SetAutoRepeating( value.Get< bool >() );
415         break;
416       }
417
418       case Toolkit::PushButton::PROPERTY_INITIAL_AUTO_REPEATING_DELAY:
419       {
420         pushButtonImpl.SetInitialAutoRepeatingDelay( value.Get< float >() );
421         break;
422       }
423
424       case Toolkit::PushButton::PROPERTY_NEXT_AUTO_REPEATING_DELAY:
425       {
426         pushButtonImpl.SetNextAutoRepeatingDelay( value.Get< float >() );
427         break;
428       }
429
430       case Toolkit::PushButton::PROPERTY_TOGGLABLE:
431       {
432         pushButtonImpl.SetToggleButton( value.Get< bool >() );
433         break;
434       }
435
436       case Toolkit::PushButton::PROPERTY_TOGGLE:
437       {
438         pushButtonImpl.SetToggled( value.Get< bool >() );
439         break;
440       }
441
442       case Toolkit::PushButton::PROPERTY_NORMAL_STATE_ACTOR:
443       {
444         pushButtonImpl.SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
445         break;
446       }
447
448       case Toolkit::PushButton::PROPERTY_PRESSED_STATE_ACTOR:
449       {
450         pushButtonImpl.SetPressedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
451         break;
452       }
453
454       case Toolkit::PushButton::PROPERTY_DIMMED_STATE_ACTOR:
455       {
456         pushButtonImpl.SetDimmedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
457         break;
458       }
459
460       case Toolkit::PushButton::PROPERTY_LABEL_ACTOR:
461       {
462         pushButtonImpl.SetLabelText( Scripting::NewActor( value.Get< Property::Map >() ) );
463         break;
464       }
465     }
466   }
467 }
468
469 Property::Value PushButton::GetProperty( BaseObject* object, Property::Index propertyIndex )
470 {
471   Property::Value value;
472
473   Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( Dali::BaseHandle( object ) );
474
475   if ( pushButton )
476   {
477     PushButton& pushButtonImpl( GetImplementation( pushButton ) );
478
479     switch ( propertyIndex )
480     {
481       case Toolkit::PushButton::PROPERTY_AUTO_REPEATING:
482       {
483         value = pushButtonImpl.mAutoRepeating;
484         break;
485       }
486
487       case Toolkit::PushButton::PROPERTY_INITIAL_AUTO_REPEATING_DELAY:
488       {
489         value = pushButtonImpl.mInitialAutoRepeatingDelay;
490         break;
491       }
492
493       case Toolkit::PushButton::PROPERTY_NEXT_AUTO_REPEATING_DELAY:
494       {
495         value = pushButtonImpl.mNextAutoRepeatingDelay;
496         break;
497       }
498
499       case Toolkit::PushButton::PROPERTY_TOGGLABLE:
500       {
501         value = pushButtonImpl.mToggleButton;
502         break;
503       }
504
505       case Toolkit::PushButton::PROPERTY_TOGGLE:
506       {
507         value = pushButtonImpl.mToggled;
508         break;
509       }
510
511       case Toolkit::PushButton::PROPERTY_NORMAL_STATE_ACTOR:
512       {
513         Property::Map map;
514         Scripting::CreatePropertyMap( pushButtonImpl.mButtonImage, map );
515         value = map;
516         break;
517       }
518
519       case Toolkit::PushButton::PROPERTY_PRESSED_STATE_ACTOR:
520       {
521         Property::Map map;
522         Scripting::CreatePropertyMap( pushButtonImpl.mPressedImage, map );
523         value = map;
524         break;
525       }
526
527       case Toolkit::PushButton::PROPERTY_DIMMED_STATE_ACTOR:
528       {
529         Property::Map map;
530         Scripting::CreatePropertyMap( pushButtonImpl.mDimmedImage, map );
531         value = map;
532         break;
533       }
534
535       case Toolkit::PushButton::PROPERTY_LABEL_ACTOR:
536       {
537         Property::Map map;
538         Scripting::CreatePropertyMap( pushButtonImpl.mLabel, map );
539         value = map;
540         break;
541       }
542     }
543   }
544
545   return value;
546 }
547
548 void PushButton::OnButtonInitialize()
549 {
550   // Push button requires the Leave event.
551   Actor root = Self();
552   root.SetLeaveRequired( true );
553 }
554
555 void PushButton::OnButtonDown()
556 {
557   if( !mToggleButton )
558   {
559     Toolkit::PushButton handle( GetOwner() );
560
561     // Notifies the painter the button has been pressed.
562     GetPushButtonPainter( mPainter )->Pressed( handle );
563
564     if( mAutoRepeating )
565     {
566       SetUpTimer( mInitialAutoRepeatingDelay );
567     }
568
569     //Emit signal.
570     mPressedSignalV2.Emit( handle );
571   }
572 }
573
574 void PushButton::OnButtonUp()
575 {
576   if( ButtonDown == mState )
577   {
578     if( mToggleButton )
579     {
580       mToggled = !mToggled;
581
582       Toolkit::PushButton handle( GetOwner() );
583
584       // Notifies the painter the button has been toggled.
585       GetPushButtonPainter( mPainter )->Toggled( handle );
586
587       //Emit signal.
588       mToggledSignalV2.Emit( handle, mToggled );
589     }
590     else
591     {
592       Toolkit::PushButton handle( GetOwner() );
593
594       // Notifies the painter the button has been clicked.
595       GetPushButtonPainter( mPainter )->Released( handle );
596       GetPushButtonPainter( mPainter )->Clicked( handle );
597
598       if( mAutoRepeating )
599       {
600         mAutoRepeatingTimer.Reset();
601       }
602
603       //Emit signal.
604       mReleasedSignalV2.Emit( handle );
605       mClickedSignalV2.Emit( handle );
606     }
607   }
608 }
609
610 void PushButton::OnTouchPointLeave()
611 {
612   if( ButtonDown == mState )
613   {
614     if( !mToggleButton )
615     {
616       Toolkit::PushButton handle( GetOwner() );
617
618       // Notifies the painter the button has been released.
619       GetPushButtonPainter( mPainter )->Released( handle );
620
621       if( mAutoRepeating )
622       {
623         mAutoRepeatingTimer.Reset();
624       }
625
626       //Emit signal.
627       mReleasedSignalV2.Emit( handle );
628     }
629   }
630 }
631
632 void PushButton::OnTouchPointInterrupted()
633 {
634   OnTouchPointLeave();
635 }
636
637 void PushButton::OnAnimationTimeSet( float animationTime )
638 {
639   GetPushButtonPainter( mPainter )->SetAnimationTime( animationTime );
640 }
641
642 float PushButton::OnAnimationTimeRequested() const
643 {
644   return GetPushButtonPainter( mPainter )->GetAnimationTime();
645 }
646
647 PushButton::PushButton()
648 : Button(),
649   mAutoRepeating( false ),
650   mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ),
651   mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ),
652   mToggleButton( false ),
653   mAutoRepeatingTimer(),
654   mToggled( false ),
655   mClickActionPerforming(false)
656 {
657   // Creates specific painter.
658   mPainter = PushButtonDefaultPainterPtr( new PushButtonDefaultPainter() );
659 }
660
661 PushButton::~PushButton()
662 {
663   if( mAutoRepeatingTimer )
664   {
665     mAutoRepeatingTimer.Reset();
666   }
667
668   mPainter = NULL;
669 }
670
671 void PushButton::SetUpTimer( float delay )
672 {
673   mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
674   mAutoRepeatingTimer.TickSignal().Connect( this, &PushButton::AutoRepeatingSlot );
675   mAutoRepeatingTimer.Start();
676 }
677
678 bool PushButton::AutoRepeatingSlot()
679 {
680   bool consumed = false;
681   if( !mDimmed )
682   {
683     // Restart the autorepeat timer.
684     SetUpTimer( mNextAutoRepeatingDelay );
685
686     Toolkit::PushButton handle( GetOwner() );
687
688     // Notifies the painter the button has been pressed.
689     GetPushButtonPainter( mPainter )->Pressed( handle );
690
691     //Emit signal.
692     consumed = mReleasedSignalV2.Emit( handle );
693     consumed |= mClickedSignalV2.Emit( handle );
694     consumed |= mPressedSignalV2.Emit( handle );
695  }
696
697   return consumed;
698 }
699
700 void PushButton::OnActivated()
701 {
702   // When the button is activated, it performs the click action
703   std::vector<Property::Value> attributes;
704   DoClickAction(attributes);
705 }
706
707 Vector3 PushButton::GetNaturalSize()
708 {
709   Vector3 size = Control::GetNaturalSize();
710
711   const bool widthIsZero = EqualsZero( size.width );
712   const bool heightIsZero = EqualsZero( size.height );
713
714   if( widthIsZero || heightIsZero )
715   {
716     // If background and background not scale9 try get size from that
717     ImageActor imageActor = FindImageActor( mButtonImage );
718     if( imageActor && imageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH )
719     {
720       Vector3 imageSize = RelayoutHelper::GetNaturalSize( imageActor );
721
722       if( widthIsZero )
723       {
724         size.width = imageSize.width;
725       }
726
727       if( heightIsZero )
728       {
729         size.height = imageSize.height;
730       }
731     }
732
733     ImageActor backgroundImageActor = FindImageActor( mBackgroundImage );
734     if( backgroundImageActor && backgroundImageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH )
735     {
736       Vector3 imageSize = RelayoutHelper::GetNaturalSize( backgroundImageActor );
737
738       if( widthIsZero )
739       {
740         size.width = std::max( size.width, imageSize.width );
741       }
742
743       if( heightIsZero )
744       {
745         size.height = std::max( size.height, imageSize.height );
746       }
747     }
748
749     // If label, test against it's size
750     Toolkit::TextView textView = Toolkit::TextView::DownCast( mLabel );
751     if( textView )
752     {
753       Vector3 textViewSize = textView.GetNaturalSize();
754
755       if( widthIsZero )
756       {
757         size.width = std::max( size.width, textViewSize.width + TEXT_PADDING * 2.0f );
758       }
759
760       if( heightIsZero )
761       {
762         size.height = std::max( size.height, textViewSize.height + TEXT_PADDING * 2.0f );
763       }
764     }
765   }
766
767   return size;
768 }
769
770 void PushButton::DoClickAction(const PropertyValueContainer& attributes)
771 {
772   // Prevents the button signals from doing a recursive loop by sending an action
773   // and re-emitting the signals.
774   if(!mClickActionPerforming)
775   {
776     mClickActionPerforming = true;
777     OnButtonDown();
778     mState = ButtonDown;
779     OnButtonUp();
780     mClickActionPerforming = false;
781   }
782 }
783
784 bool PushButton::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
785 {
786   bool ret = false;
787
788   Dali::BaseHandle handle(object);
789
790   Toolkit::PushButton button = Toolkit::PushButton::DownCast(handle);
791
792   DALI_ASSERT_ALWAYS(button);
793
794   if(Toolkit::PushButton::ACTION_PUSH_BUTTON_CLICK == actionName)
795   {
796     GetImplementation(button).DoClickAction(attributes);
797     ret = true;
798   }
799
800   return ret;
801 }
802
803 } // namespace Internal
804
805 } // namespace Toolkit
806
807 } // namespace Dali