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>
46 return Toolkit::PushButton::New();
49 TypeRegistration typeRegistration( typeid(Toolkit::PushButton), typeid(Toolkit::Button), Create );
51 SignalConnectorType signalConnector1( typeRegistration, Toolkit::PushButton::SIGNAL_PRESSED , &PushButton::DoConnectSignal );
52 SignalConnectorType signalConnector2( typeRegistration, Toolkit::PushButton::SIGNAL_RELEASED, &PushButton::DoConnectSignal );
54 TypeAction action1( typeRegistration, Toolkit::PushButton::ACTION_PUSH_BUTTON_CLICK, &PushButton::DoAction );
56 } // unnamed namespace
61 const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f );
62 const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f );
64 const float TEXT_PADDING = 12.0f;
66 // Helper function used to cast a ButtonPainter to PushButtonDefaultPainter
67 PushButtonDefaultPainterPtr GetPushButtonPainter( Dali::Toolkit::Internal::ButtonPainterPtr painter )
69 return static_cast<PushButtonDefaultPainter*>( painter.Get() );
73 * Find the first image actor in the actor hierarchy
75 ImageActor FindImageActor( Actor root )
77 ImageActor imageActor = ImageActor::DownCast( root );
78 if( !imageActor && root )
80 for( unsigned int i = 0, numChildren = root.GetChildCount(); i < numChildren; ++i )
82 ImageActor childImageActor = FindImageActor( root.GetChildAt( i ) );
85 return childImageActor;
94 } // unnamed namespace
96 Dali::Toolkit::PushButton PushButton::New()
98 // Create the implementation, temporarily owned on stack
99 IntrusivePtr< PushButton > internalPushButton = new PushButton();
101 // Pass ownership to CustomActor
102 Dali::Toolkit::PushButton pushButton( *internalPushButton );
104 // Second-phase init of the implementation
105 // This can only be done after the CustomActor connection has been made...
106 internalPushButton->Initialize();
111 void PushButton::SetAutoRepeating( bool autoRepeating )
113 mAutoRepeating = autoRepeating;
115 // An autorepeating button can't be a toggle button.
118 mToggleButton = false;
121 // Emit a signal is not wanted, only change the appearance.
122 Toolkit::PushButton handle( GetOwner() );
123 GetPushButtonPainter( mPainter )->Toggled( handle );
128 // Notifies the painter.
129 GetPushButtonPainter( mPainter )->SetAutoRepeating( mAutoRepeating );
132 bool PushButton::IsAutoRepeating() const
134 return mAutoRepeating;
137 void PushButton::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
139 DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
140 mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
143 float PushButton::GetInitialAutoRepeatingDelay() const
145 return mInitialAutoRepeatingDelay;
148 void PushButton::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
150 DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
151 mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
154 float PushButton::GetNextAutoRepeatingDelay() const
156 return mNextAutoRepeatingDelay;
159 void PushButton::SetToggleButton( bool toggle )
161 mToggleButton = toggle;
163 // A toggle button can't be an autorepeating button.
166 mAutoRepeating = false;
168 // Notifies the painter.
169 GetPushButtonPainter( mPainter )->SetAutoRepeating( mAutoRepeating );
173 bool PushButton::IsToggleButton() const
175 return mToggleButton;
178 void PushButton::SetToggled( bool toggle )
180 if( !mDisabled && mToggleButton && ( toggle != mToggled ) )
184 Toolkit::PushButton handle( GetOwner() );
186 // Notifies the painter the button has been toggled.
187 GetPushButtonPainter( mPainter )->Toggled( handle );
190 mStateChangedSignal.Emit( handle, mToggled );
194 bool PushButton::IsToggled() const
196 return mToggleButton && mToggled;
199 void PushButton::SetButtonImage( Image image )
201 SetButtonImage( ImageActor::New( image ) );
204 void PushButton::SetButtonImage( Actor image )
206 Toolkit::PushButton handle( GetOwner() );
207 GetPushButtonPainter( mPainter )->SetButtonImage( handle, image );
210 Actor& PushButton::GetButtonImage()
215 Actor PushButton::GetButtonImage() const
220 void PushButton::SetBackgroundImage( Image image )
222 SetBackgroundImage( ImageActor::New( image ) );
225 void PushButton::SetBackgroundImage( Actor image )
227 Toolkit::PushButton handle( GetOwner() );
228 GetPushButtonPainter( mPainter )->SetBackgroundImage( handle, image );
231 Actor& PushButton::GetBackgroundImage()
233 return mBackgroundImage;
236 Actor PushButton::GetBackgroundImage() const
238 return mBackgroundImage;
241 void PushButton::SetSelectedImage( Image image )
243 SetSelectedImage( ImageActor::New( image ) );
246 void PushButton::SetSelectedImage( Actor image )
248 Toolkit::PushButton handle( GetOwner() );
249 GetPushButtonPainter( mPainter )->SetSelectedImage( handle, image );
252 Actor& PushButton::GetSelectedImage()
254 return mSelectedImage;
257 Actor PushButton::GetSelectedImage() const
259 return mSelectedImage;
262 void PushButton::SetDisabledBackgroundImage( Image image )
264 SetDisabledBackgroundImage( ImageActor::New( image ) );
267 void PushButton::SetDisabledBackgroundImage( Actor image )
269 Toolkit::PushButton handle( GetOwner() );
270 GetPushButtonPainter( mPainter )->SetDisabledBackgroundImage( handle, image );
273 Actor& PushButton::GetDisabledBackgroundImage()
275 return mDisabledBackgroundImage;
278 Actor PushButton::GetDisabledBackgroundImage() const
280 return mDisabledBackgroundImage;
283 void PushButton::SetDisabledImage( Image image )
285 SetDisabledImage( ImageActor::New( image ) );
288 void PushButton::SetDisabledImage( Actor image )
290 Toolkit::PushButton handle( GetOwner() );
291 GetPushButtonPainter( mPainter )->SetDisabledImage( handle, image );
294 Actor& PushButton::GetDisabledImage()
296 return mDisabledImage;
299 Actor PushButton::GetDisabledImage() const
301 return mDisabledImage;
304 void PushButton::SetLabel( const std::string& label )
309 void PushButton::SetLabel( Actor label )
311 Toolkit::PushButton handle( GetOwner() );
312 GetPushButtonPainter( mPainter )->SetLabel( handle, label );
315 Actor PushButton::GetLabel() const
320 Actor& PushButton::GetLabel()
325 Actor& PushButton::GetFadeOutBackgroundImage()
327 return mFadeOutBackgroundImage;
330 Actor& PushButton::GetFadeOutButtonImage()
332 return mFadeOutButtonImage;
335 Toolkit::PushButton::PressedSignalType& PushButton::PressedSignal()
337 return mPressedSignal;
340 Toolkit::PushButton::ReleasedSignalType& PushButton::ReleasedSignal()
342 return mReleasedSignal;
345 bool PushButton::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
347 Dali::BaseHandle handle( object );
349 bool connected( true );
350 Toolkit::PushButton button = Toolkit::PushButton::DownCast(handle);
352 if( Toolkit::PushButton::SIGNAL_STATE_CHANGED == signalName )
354 button.StateChangedSignal().Connect( tracker, functor );
356 else if( Toolkit::PushButton::SIGNAL_PRESSED == signalName )
358 button.PressedSignal().Connect( tracker, functor );
360 else if( Toolkit::PushButton::SIGNAL_RELEASED == signalName )
362 button.ReleasedSignal().Connect( tracker, functor );
366 // signalName does not match any signal
373 void PushButton::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
375 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( Dali::BaseHandle( object ) );
379 PushButton& pushButtonImpl( GetImplementation( pushButton ) );
381 if ( propertyIndex == Toolkit::Button::PROPERTY_AUTO_REPEATING )
383 pushButtonImpl.SetAutoRepeating( value.Get< bool >() );
385 else if ( propertyIndex == Toolkit::Button::PROPERTY_INITIAL_AUTO_REPEATING_DELAY )
387 pushButtonImpl.SetInitialAutoRepeatingDelay( value.Get< float >() );
389 else if ( propertyIndex == Toolkit::Button::PROPERTY_NEXT_AUTO_REPEATING_DELAY )
391 pushButtonImpl.SetNextAutoRepeatingDelay( value.Get< float >() );
393 else if ( propertyIndex == Toolkit::Button::PROPERTY_TOGGLABLE )
395 pushButtonImpl.SetToggleButton( value.Get< bool >() );
397 else if ( propertyIndex == Toolkit::Button::PROPERTY_TOGGLED )
399 pushButtonImpl.SetToggled( value.Get< bool >() );
401 else if ( propertyIndex == Toolkit::Button::PROPERTY_NORMAL_STATE_ACTOR )
403 pushButtonImpl.SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
405 else if ( propertyIndex == Toolkit::Button::PROPERTY_SELECTED_STATE_ACTOR )
407 pushButtonImpl.SetSelectedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
409 else if ( propertyIndex == Toolkit::Button::PROPERTY_DISABLED_STATE_ACTOR )
411 pushButtonImpl.SetDisabledImage( Scripting::NewActor( value.Get< Property::Map >() ) );
413 else if ( propertyIndex == Toolkit::Button::PROPERTY_LABEL_ACTOR )
415 pushButtonImpl.SetLabel( Scripting::NewActor( value.Get< Property::Map >() ) );
420 Property::Value PushButton::GetProperty( BaseObject* object, Property::Index propertyIndex )
422 Property::Value value;
424 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( Dali::BaseHandle( object ) );
428 PushButton& pushButtonImpl( GetImplementation( pushButton ) );
430 if ( propertyIndex == Toolkit::Button::PROPERTY_AUTO_REPEATING )
432 value = pushButtonImpl.mAutoRepeating;
434 else if ( propertyIndex == Toolkit::Button::PROPERTY_INITIAL_AUTO_REPEATING_DELAY )
436 value = pushButtonImpl.mInitialAutoRepeatingDelay;
438 else if ( propertyIndex == Toolkit::Button::PROPERTY_NEXT_AUTO_REPEATING_DELAY )
440 value = pushButtonImpl.mNextAutoRepeatingDelay;
442 else if ( propertyIndex == Toolkit::Button::PROPERTY_TOGGLABLE )
444 value = pushButtonImpl.mToggleButton;
446 else if ( propertyIndex == Toolkit::Button::PROPERTY_TOGGLED )
448 value = pushButtonImpl.mToggled;
450 else if ( propertyIndex == Toolkit::Button::PROPERTY_NORMAL_STATE_ACTOR )
453 Scripting::CreatePropertyMap( pushButtonImpl.mButtonImage, map );
456 else if ( propertyIndex == Toolkit::Button::PROPERTY_SELECTED_STATE_ACTOR )
459 Scripting::CreatePropertyMap( pushButtonImpl.mSelectedImage, map );
462 else if ( propertyIndex == Toolkit::Button::PROPERTY_DISABLED_STATE_ACTOR )
465 Scripting::CreatePropertyMap( pushButtonImpl.mDisabledImage, map );
468 else if ( propertyIndex == Toolkit::Button::PROPERTY_LABEL_ACTOR )
471 Scripting::CreatePropertyMap( pushButtonImpl.mLabel, map );
479 void PushButton::OnButtonInitialize()
481 // Push button requires the Leave event.
483 root.SetLeaveRequired( true );
486 void PushButton::OnButtonDown()
490 Toolkit::PushButton handle( GetOwner() );
492 // Notifies the painter the button has been pressed.
493 GetPushButtonPainter( mPainter )->Pressed( handle );
497 SetUpTimer( mInitialAutoRepeatingDelay );
501 mPressedSignal.Emit( handle );
505 void PushButton::OnButtonUp()
507 if( ButtonDown == mState )
511 mToggled = !mToggled;
513 Toolkit::PushButton handle( GetOwner() );
515 // Notifies the painter the button has been toggled.
516 GetPushButtonPainter( mPainter )->Toggled( handle );
519 mStateChangedSignal.Emit( handle, mToggled );
523 Toolkit::PushButton handle( GetOwner() );
525 // Notifies the painter the button has been clicked.
526 GetPushButtonPainter( mPainter )->Released( handle );
527 GetPushButtonPainter( mPainter )->Clicked( handle );
531 mAutoRepeatingTimer.Reset();
535 mReleasedSignal.Emit( handle );
536 mClickedSignal.Emit( handle );
541 void PushButton::OnTouchPointLeave()
543 if( ButtonDown == mState )
547 Toolkit::PushButton handle( GetOwner() );
549 // Notifies the painter the button has been released.
550 GetPushButtonPainter( mPainter )->Released( handle );
554 mAutoRepeatingTimer.Reset();
558 mReleasedSignal.Emit( handle );
563 void PushButton::OnTouchPointInterrupted()
568 void PushButton::OnAnimationTimeSet( float animationTime )
570 GetPushButtonPainter( mPainter )->SetAnimationTime( animationTime );
573 float PushButton::OnAnimationTimeRequested() const
575 return GetPushButtonPainter( mPainter )->GetAnimationTime();
578 void PushButton::OnButtonStageDisconnection()
580 if( ButtonDown == mState )
584 Toolkit::PushButton handle( GetOwner() );
586 // Notifies the painter the button has been released.
587 GetPushButtonPainter( mPainter )->Released( handle );
591 mAutoRepeatingTimer.Reset();
597 PushButton::PushButton()
599 mAutoRepeating( false ),
600 mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ),
601 mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ),
602 mToggleButton( false ),
603 mAutoRepeatingTimer(),
605 mClickActionPerforming(false)
607 // Creates specific painter.
608 mPainter = PushButtonDefaultPainterPtr( new PushButtonDefaultPainter() );
611 PushButton::~PushButton()
613 if( mAutoRepeatingTimer )
615 mAutoRepeatingTimer.Reset();
621 void PushButton::SetUpTimer( float delay )
623 mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
624 mAutoRepeatingTimer.TickSignal().Connect( this, &PushButton::AutoRepeatingSlot );
625 mAutoRepeatingTimer.Start();
628 bool PushButton::AutoRepeatingSlot()
630 bool consumed = false;
633 // Restart the autorepeat timer.
634 SetUpTimer( mNextAutoRepeatingDelay );
636 Toolkit::PushButton handle( GetOwner() );
638 // Notifies the painter the button has been pressed.
639 GetPushButtonPainter( mPainter )->Pressed( handle );
642 consumed = mReleasedSignal.Emit( handle );
643 consumed |= mClickedSignal.Emit( handle );
644 consumed |= mPressedSignal.Emit( handle );
650 void PushButton::OnActivated()
652 // When the button is activated, it performs the click action
653 PropertyValueContainer attributes;
654 DoClickAction(attributes);
657 Vector3 PushButton::GetNaturalSize()
659 Vector3 size = Control::GetNaturalSize();
661 const bool widthIsZero = EqualsZero( size.width );
662 const bool heightIsZero = EqualsZero( size.height );
664 if( widthIsZero || heightIsZero )
666 // If background and background not scale9 try get size from that
667 ImageActor imageActor = FindImageActor( mButtonImage );
668 if( imageActor && imageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH )
670 Vector3 imageSize = RelayoutHelper::GetNaturalSize( imageActor );
674 size.width = imageSize.width;
679 size.height = imageSize.height;
683 ImageActor backgroundImageActor = FindImageActor( mBackgroundImage );
684 if( backgroundImageActor && backgroundImageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH )
686 Vector3 imageSize = RelayoutHelper::GetNaturalSize( backgroundImageActor );
690 size.width = std::max( size.width, imageSize.width );
695 size.height = std::max( size.height, imageSize.height );
703 void PushButton::DoClickAction(const PropertyValueContainer& attributes)
705 // Prevents the button signals from doing a recursive loop by sending an action
706 // and re-emitting the signals.
707 if(!mClickActionPerforming)
709 mClickActionPerforming = true;
713 mClickActionPerforming = false;
717 bool PushButton::DoAction(BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes)
721 Dali::BaseHandle handle(object);
723 Toolkit::PushButton button = Toolkit::PushButton::DownCast(handle);
725 DALI_ASSERT_ALWAYS(button);
727 if(Toolkit::PushButton::ACTION_PUSH_BUTTON_CLICK == actionName)
729 GetImplementation(button).DoClickAction(attributes);
736 } // namespace Internal
738 } // namespace Toolkit