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