2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "push-button-impl.h"
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>
28 #include "push-button-default-painter-impl.h"
30 #include <dali-toolkit/internal/controls/relayout-helper.h>
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;
56 return Toolkit::PushButton::New();
59 TypeRegistration typeRegistration( typeid(Toolkit::PushButton), typeid(Toolkit::Button), Create );
61 SignalConnectorType signalConnector1( typeRegistration, Toolkit::PushButton::SIGNAL_PRESSED , &PushButton::DoConnectSignal );
62 SignalConnectorType signalConnector2( typeRegistration, Toolkit::PushButton::SIGNAL_RELEASED, &PushButton::DoConnectSignal );
64 TypeAction action1( typeRegistration, Toolkit::PushButton::ACTION_PUSH_BUTTON_CLICK, &PushButton::DoAction );
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 );
76 } // unnamed namespace
81 const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f );
82 const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f );
84 const float TEXT_PADDING = 12.0f;
86 // Helper function used to cast a ButtonPainter to PushButtonDefaultPainter
87 PushButtonDefaultPainterPtr GetPushButtonPainter( Dali::Toolkit::Internal::ButtonPainterPtr painter )
89 return static_cast<PushButtonDefaultPainter*>( painter.Get() );
93 * Find the first image actor in the actor hierarchy
95 ImageActor FindImageActor( Actor root )
97 ImageActor imageActor = ImageActor::DownCast( root );
98 if( !imageActor && root )
100 for( unsigned int i = 0, numChildren = root.GetChildCount(); i < numChildren; ++i )
102 ImageActor childImageActor = FindImageActor( root.GetChildAt( i ) );
103 if( childImageActor )
105 return childImageActor;
114 } // unnamed namespace
116 Dali::Toolkit::PushButton PushButton::New()
118 // Create the implementation, temporarily owned on stack
119 IntrusivePtr< PushButton > internalPushButton = new PushButton();
121 // Pass ownership to CustomActor
122 Dali::Toolkit::PushButton pushButton( *internalPushButton );
124 // Second-phase init of the implementation
125 // This can only be done after the CustomActor connection has been made...
126 internalPushButton->Initialize();
131 void PushButton::SetAutoRepeating( bool autoRepeating )
133 mAutoRepeating = autoRepeating;
135 // An autorepeating button can't be a toggle button.
138 mToggleButton = false;
141 // Emit a signal is not wanted, only change the appearance.
142 Toolkit::PushButton handle( GetOwner() );
143 GetPushButtonPainter( mPainter )->Toggled( handle );
148 // Notifies the painter.
149 GetPushButtonPainter( mPainter )->SetAutoRepeating( mAutoRepeating );
152 bool PushButton::IsAutoRepeating() const
154 return mAutoRepeating;
157 void PushButton::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
159 DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
160 mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
163 float PushButton::GetInitialAutoRepeatingDelay() const
165 return mInitialAutoRepeatingDelay;
168 void PushButton::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
170 DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
171 mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
174 float PushButton::GetNextAutoRepeatingDelay() const
176 return mNextAutoRepeatingDelay;
179 void PushButton::SetToggleButton( bool toggle )
181 mToggleButton = toggle;
183 // A toggle button can't be an autorepeating button.
186 mAutoRepeating = false;
188 // Notifies the painter.
189 GetPushButtonPainter( mPainter )->SetAutoRepeating( mAutoRepeating );
193 bool PushButton::IsToggleButton() const
195 return mToggleButton;
198 void PushButton::SetToggled( bool toggle )
200 if( !mDimmed && mToggleButton && ( toggle != mToggled ) )
204 Toolkit::PushButton handle( GetOwner() );
206 // Notifies the painter the button has been toggled.
207 GetPushButtonPainter( mPainter )->Toggled( handle );
210 mToggledSignalV2.Emit( handle, mToggled );
214 bool PushButton::IsToggled() const
216 return mToggleButton && mToggled;
219 void PushButton::SetButtonImage( Image image )
221 SetButtonImage( ImageActor::New( image ) );
224 void PushButton::SetButtonImage( Actor image )
226 Toolkit::PushButton handle( GetOwner() );
227 GetPushButtonPainter( mPainter )->SetButtonImage( handle, image );
230 Actor& PushButton::GetButtonImage()
235 Actor PushButton::GetButtonImage() const
240 void PushButton::SetBackgroundImage( Image image )
242 SetBackgroundImage( ImageActor::New( image ) );
245 void PushButton::SetBackgroundImage( Actor image )
247 Toolkit::PushButton handle( GetOwner() );
248 GetPushButtonPainter( mPainter )->SetBackgroundImage( handle, image );
251 Actor& PushButton::GetBackgroundImage()
253 return mBackgroundImage;
256 Actor PushButton::GetBackgroundImage() const
258 return mBackgroundImage;
261 void PushButton::SetPressedImage( Image image )
263 SetPressedImage( ImageActor::New( image ) );
266 void PushButton::SetPressedImage( Actor image )
268 Toolkit::PushButton handle( GetOwner() );
269 GetPushButtonPainter( mPainter )->SetPressedImage( handle, image );
272 Actor& PushButton::GetPressedImage()
274 return mPressedImage;
277 Actor PushButton::GetPressedImage() const
279 return mPressedImage;
282 void PushButton::SetDimmedBackgroundImage( Image image )
284 SetDimmedBackgroundImage( ImageActor::New( image ) );
287 void PushButton::SetDimmedBackgroundImage( Actor image )
289 Toolkit::PushButton handle( GetOwner() );
290 GetPushButtonPainter( mPainter )->SetDimmedBackgroundImage( handle, image );
293 Actor& PushButton::GetDimmedBackgroundImage()
295 return mDimmedBackgroundImage;
298 Actor PushButton::GetDimmedBackgroundImage() const
300 return mDimmedBackgroundImage;
303 void PushButton::SetDimmedImage( Image image )
305 SetDimmedImage( ImageActor::New( image ) );
308 void PushButton::SetDimmedImage( Actor image )
310 Toolkit::PushButton handle( GetOwner() );
311 GetPushButtonPainter( mPainter )->SetDimmedImage( handle, image );
314 Actor& PushButton::GetDimmedImage()
319 Actor PushButton::GetDimmedImage() const
324 void PushButton::SetLabelText( const std::string& text )
329 void PushButton::SetLabelText( Actor text )
331 Toolkit::PushButton handle( GetOwner() );
332 GetPushButtonPainter( mPainter )->SetLabelText( handle, text );
335 Actor& PushButton::GetLabel()
340 Actor PushButton::GetLabelText() const
345 Actor& PushButton::GetFadeOutBackgroundImage()
347 return mFadeOutBackgroundImage;
350 Actor& PushButton::GetFadeOutButtonImage()
352 return mFadeOutButtonImage;
355 Toolkit::PushButton::PressedSignalV2& PushButton::PressedSignal()
357 return mPressedSignalV2;
360 Toolkit::PushButton::ReleasedSignalV2& PushButton::ReleasedSignal()
362 return mReleasedSignalV2;
365 bool PushButton::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
367 Dali::BaseHandle handle( object );
369 bool connected( true );
370 Toolkit::PushButton button = Toolkit::PushButton::DownCast(handle);
372 if( Toolkit::PushButton::SIGNAL_TOGGLED == signalName )
374 button.ToggledSignal().Connect( tracker, functor );
376 else if( Toolkit::PushButton::SIGNAL_PRESSED == signalName )
378 button.PressedSignal().Connect( tracker, functor );
380 else if( Toolkit::PushButton::SIGNAL_RELEASED == signalName )
382 button.ReleasedSignal().Connect( tracker, functor );
386 // signalName does not match any signal
393 void PushButton::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
395 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( Dali::BaseHandle( object ) );
399 PushButton& pushButtonImpl( GetImplementation( pushButton ) );
401 switch ( propertyIndex )
403 case Toolkit::PushButton::PROPERTY_AUTO_REPEATING:
405 pushButtonImpl.SetAutoRepeating( value.Get< bool >() );
409 case Toolkit::PushButton::PROPERTY_INITIAL_AUTO_REPEATING_DELAY:
411 pushButtonImpl.SetInitialAutoRepeatingDelay( value.Get< float >() );
415 case Toolkit::PushButton::PROPERTY_NEXT_AUTO_REPEATING_DELAY:
417 pushButtonImpl.SetNextAutoRepeatingDelay( value.Get< float >() );
421 case Toolkit::PushButton::PROPERTY_TOGGLABLE:
423 pushButtonImpl.SetToggleButton( value.Get< bool >() );
427 case Toolkit::PushButton::PROPERTY_TOGGLE:
429 pushButtonImpl.SetToggled( value.Get< bool >() );
433 case Toolkit::PushButton::PROPERTY_NORMAL_STATE_ACTOR:
435 pushButtonImpl.SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
439 case Toolkit::PushButton::PROPERTY_PRESSED_STATE_ACTOR:
441 pushButtonImpl.SetPressedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
445 case Toolkit::PushButton::PROPERTY_DIMMED_STATE_ACTOR:
447 pushButtonImpl.SetDimmedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
451 case Toolkit::PushButton::PROPERTY_LABEL_ACTOR:
453 pushButtonImpl.SetLabelText( Scripting::NewActor( value.Get< Property::Map >() ) );
460 Property::Value PushButton::GetProperty( BaseObject* object, Property::Index propertyIndex )
462 Property::Value value;
464 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( Dali::BaseHandle( object ) );
468 PushButton& pushButtonImpl( GetImplementation( pushButton ) );
470 switch ( propertyIndex )
472 case Toolkit::PushButton::PROPERTY_AUTO_REPEATING:
474 value = pushButtonImpl.mAutoRepeating;
478 case Toolkit::PushButton::PROPERTY_INITIAL_AUTO_REPEATING_DELAY:
480 value = pushButtonImpl.mInitialAutoRepeatingDelay;
484 case Toolkit::PushButton::PROPERTY_NEXT_AUTO_REPEATING_DELAY:
486 value = pushButtonImpl.mNextAutoRepeatingDelay;
490 case Toolkit::PushButton::PROPERTY_TOGGLABLE:
492 value = pushButtonImpl.mToggleButton;
496 case Toolkit::PushButton::PROPERTY_TOGGLE:
498 value = pushButtonImpl.mToggled;
502 case Toolkit::PushButton::PROPERTY_NORMAL_STATE_ACTOR:
505 Scripting::CreatePropertyMap( pushButtonImpl.mButtonImage, map );
510 case Toolkit::PushButton::PROPERTY_PRESSED_STATE_ACTOR:
513 Scripting::CreatePropertyMap( pushButtonImpl.mPressedImage, map );
518 case Toolkit::PushButton::PROPERTY_DIMMED_STATE_ACTOR:
521 Scripting::CreatePropertyMap( pushButtonImpl.mDimmedImage, map );
526 case Toolkit::PushButton::PROPERTY_LABEL_ACTOR:
529 Scripting::CreatePropertyMap( pushButtonImpl.mLabel, map );
539 void PushButton::OnButtonInitialize()
541 // Push button requires the Leave event.
543 root.SetLeaveRequired( true );
546 void PushButton::OnButtonDown()
550 Toolkit::PushButton handle( GetOwner() );
552 // Notifies the painter the button has been pressed.
553 GetPushButtonPainter( mPainter )->Pressed( handle );
557 SetUpTimer( mInitialAutoRepeatingDelay );
561 mPressedSignalV2.Emit( handle );
565 void PushButton::OnButtonUp()
567 if( ButtonDown == mState )
571 mToggled = !mToggled;
573 Toolkit::PushButton handle( GetOwner() );
575 // Notifies the painter the button has been toggled.
576 GetPushButtonPainter( mPainter )->Toggled( handle );
579 mToggledSignalV2.Emit( handle, mToggled );
583 Toolkit::PushButton handle( GetOwner() );
585 // Notifies the painter the button has been clicked.
586 GetPushButtonPainter( mPainter )->Released( handle );
587 GetPushButtonPainter( mPainter )->Clicked( handle );
591 mAutoRepeatingTimer.Reset();
595 mReleasedSignalV2.Emit( handle );
596 mClickedSignalV2.Emit( handle );
601 void PushButton::OnTouchPointLeave()
603 if( ButtonDown == mState )
607 Toolkit::PushButton handle( GetOwner() );
609 // Notifies the painter the button has been released.
610 GetPushButtonPainter( mPainter )->Released( handle );
614 mAutoRepeatingTimer.Reset();
618 mReleasedSignalV2.Emit( handle );
623 void PushButton::OnTouchPointInterrupted()
628 void PushButton::OnAnimationTimeSet( float animationTime )
630 GetPushButtonPainter( mPainter )->SetAnimationTime( animationTime );
633 float PushButton::OnAnimationTimeRequested() const
635 return GetPushButtonPainter( mPainter )->GetAnimationTime();
638 void PushButton::OnButtonStageDisconnection()
640 if( ButtonDown == mState )
644 Toolkit::PushButton handle( GetOwner() );
646 // Notifies the painter the button has been released.
647 GetPushButtonPainter( mPainter )->Released( handle );
651 mAutoRepeatingTimer.Reset();
657 PushButton::PushButton()
659 mAutoRepeating( false ),
660 mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ),
661 mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ),
662 mToggleButton( false ),
663 mAutoRepeatingTimer(),
665 mClickActionPerforming(false)
667 // Creates specific painter.
668 mPainter = PushButtonDefaultPainterPtr( new PushButtonDefaultPainter() );
671 PushButton::~PushButton()
673 if( mAutoRepeatingTimer )
675 mAutoRepeatingTimer.Reset();
681 void PushButton::SetUpTimer( float delay )
683 mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
684 mAutoRepeatingTimer.TickSignal().Connect( this, &PushButton::AutoRepeatingSlot );
685 mAutoRepeatingTimer.Start();
688 bool PushButton::AutoRepeatingSlot()
690 bool consumed = false;
693 // Restart the autorepeat timer.
694 SetUpTimer( mNextAutoRepeatingDelay );
696 Toolkit::PushButton handle( GetOwner() );
698 // Notifies the painter the button has been pressed.
699 GetPushButtonPainter( mPainter )->Pressed( handle );
702 consumed = mReleasedSignalV2.Emit( handle );
703 consumed |= mClickedSignalV2.Emit( handle );
704 consumed |= mPressedSignalV2.Emit( handle );
710 void PushButton::OnActivated()
712 // When the button is activated, it performs the click action
713 PropertyValueContainer attributes;
714 DoClickAction(attributes);
717 Vector3 PushButton::GetNaturalSize()
719 Vector3 size = Control::GetNaturalSize();
721 const bool widthIsZero = EqualsZero( size.width );
722 const bool heightIsZero = EqualsZero( size.height );
724 if( widthIsZero || heightIsZero )
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 )
730 Vector3 imageSize = RelayoutHelper::GetNaturalSize( imageActor );
734 size.width = imageSize.width;
739 size.height = imageSize.height;
743 ImageActor backgroundImageActor = FindImageActor( mBackgroundImage );
744 if( backgroundImageActor && backgroundImageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH )
746 Vector3 imageSize = RelayoutHelper::GetNaturalSize( backgroundImageActor );
750 size.width = std::max( size.width, imageSize.width );
755 size.height = std::max( size.height, imageSize.height );
763 void PushButton::DoClickAction(const PropertyValueContainer& attributes)
765 // Prevents the button signals from doing a recursive loop by sending an action
766 // and re-emitting the signals.
767 if(!mClickActionPerforming)
769 mClickActionPerforming = true;
773 mClickActionPerforming = false;
777 bool PushButton::DoAction(BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes)
781 Dali::BaseHandle handle(object);
783 Toolkit::PushButton button = Toolkit::PushButton::DownCast(handle);
785 DALI_ASSERT_ALWAYS(button);
787 if(Toolkit::PushButton::ACTION_PUSH_BUTTON_CLICK == actionName)
789 GetImplementation(button).DoClickAction(attributes);
796 } // namespace Internal
798 } // namespace Toolkit