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