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/public-api/controls/text-view/text-view.h>
31 #include <dali-toolkit/internal/controls/relayout-helper.h>
47 return Toolkit::PushButton::New();
50 TypeRegistration typeRegistration( typeid(Toolkit::PushButton), typeid(Toolkit::Button), Create );
52 SignalConnectorType signalConnector1( typeRegistration, Toolkit::PushButton::SIGNAL_PRESSED , &PushButton::DoConnectSignal );
53 SignalConnectorType signalConnector2( typeRegistration, Toolkit::PushButton::SIGNAL_RELEASED, &PushButton::DoConnectSignal );
55 TypeAction action1( typeRegistration, Toolkit::PushButton::ACTION_PUSH_BUTTON_CLICK, &PushButton::DoAction );
57 } // unnamed namespace
62 const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f );
63 const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f );
65 const float TEXT_PADDING = 12.0f;
67 // Helper function used to cast a ButtonPainter to PushButtonDefaultPainter
68 PushButtonDefaultPainterPtr GetPushButtonPainter( Dali::Toolkit::Internal::ButtonPainterPtr painter )
70 return static_cast<PushButtonDefaultPainter*>( painter.Get() );
74 * Find the first image actor in the actor hierarchy
76 ImageActor FindImageActor( Actor root )
78 ImageActor imageActor = ImageActor::DownCast( root );
79 if( !imageActor && root )
81 for( unsigned int i = 0, numChildren = root.GetChildCount(); i < numChildren; ++i )
83 ImageActor childImageActor = FindImageActor( root.GetChildAt( i ) );
86 return childImageActor;
95 } // unnamed namespace
97 Dali::Toolkit::PushButton PushButton::New()
99 // Create the implementation, temporarily owned on stack
100 IntrusivePtr< PushButton > internalPushButton = new PushButton();
102 // Pass ownership to CustomActor
103 Dali::Toolkit::PushButton pushButton( *internalPushButton );
105 // Second-phase init of the implementation
106 // This can only be done after the CustomActor connection has been made...
107 internalPushButton->Initialize();
112 void PushButton::SetAutoRepeating( bool autoRepeating )
114 mAutoRepeating = autoRepeating;
116 // An autorepeating button can't be a toggle button.
119 mToggleButton = false;
122 // Emit a signal is not wanted, only change the appearance.
123 Toolkit::PushButton handle( GetOwner() );
124 GetPushButtonPainter( mPainter )->Toggled( handle );
129 // Notifies the painter.
130 GetPushButtonPainter( mPainter )->SetAutoRepeating( mAutoRepeating );
133 bool PushButton::IsAutoRepeating() const
135 return mAutoRepeating;
138 void PushButton::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
140 DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
141 mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
144 float PushButton::GetInitialAutoRepeatingDelay() const
146 return mInitialAutoRepeatingDelay;
149 void PushButton::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
151 DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
152 mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
155 float PushButton::GetNextAutoRepeatingDelay() const
157 return mNextAutoRepeatingDelay;
160 void PushButton::SetToggleButton( bool toggle )
162 mToggleButton = toggle;
164 // A toggle button can't be an autorepeating button.
167 mAutoRepeating = false;
169 // Notifies the painter.
170 GetPushButtonPainter( mPainter )->SetAutoRepeating( mAutoRepeating );
174 bool PushButton::IsToggleButton() const
176 return mToggleButton;
179 void PushButton::SetToggled( bool toggle )
181 if( !mDisabled && mToggleButton && ( toggle != mToggled ) )
185 Toolkit::PushButton handle( GetOwner() );
187 // Notifies the painter the button has been toggled.
188 GetPushButtonPainter( mPainter )->Toggled( handle );
191 mStateChangedSignal.Emit( handle, mToggled );
195 bool PushButton::IsToggled() const
197 return mToggleButton && mToggled;
200 void PushButton::SetButtonImage( Image image )
202 SetButtonImage( ImageActor::New( image ) );
205 void PushButton::SetButtonImage( Actor image )
207 Toolkit::PushButton handle( GetOwner() );
208 GetPushButtonPainter( mPainter )->SetButtonImage( handle, image );
211 Actor& PushButton::GetButtonImage()
216 Actor PushButton::GetButtonImage() const
221 void PushButton::SetBackgroundImage( Image image )
223 SetBackgroundImage( ImageActor::New( image ) );
226 void PushButton::SetBackgroundImage( Actor image )
228 Toolkit::PushButton handle( GetOwner() );
229 GetPushButtonPainter( mPainter )->SetBackgroundImage( handle, image );
232 Actor& PushButton::GetBackgroundImage()
234 return mBackgroundImage;
237 Actor PushButton::GetBackgroundImage() const
239 return mBackgroundImage;
242 void PushButton::SetSelectedImage( Image image )
244 SetSelectedImage( ImageActor::New( image ) );
247 void PushButton::SetSelectedImage( Actor image )
249 Toolkit::PushButton handle( GetOwner() );
250 GetPushButtonPainter( mPainter )->SetSelectedImage( handle, image );
253 Actor& PushButton::GetSelectedImage()
255 return mSelectedImage;
258 Actor PushButton::GetSelectedImage() const
260 return mSelectedImage;
263 void PushButton::SetDisabledBackgroundImage( Image image )
265 SetDisabledBackgroundImage( ImageActor::New( image ) );
268 void PushButton::SetDisabledBackgroundImage( Actor image )
270 Toolkit::PushButton handle( GetOwner() );
271 GetPushButtonPainter( mPainter )->SetDisabledBackgroundImage( handle, image );
274 Actor& PushButton::GetDisabledBackgroundImage()
276 return mDisabledBackgroundImage;
279 Actor PushButton::GetDisabledBackgroundImage() const
281 return mDisabledBackgroundImage;
284 void PushButton::SetDisabledImage( Image image )
286 SetDisabledImage( ImageActor::New( image ) );
289 void PushButton::SetDisabledImage( Actor image )
291 Toolkit::PushButton handle( GetOwner() );
292 GetPushButtonPainter( mPainter )->SetDisabledImage( handle, image );
295 Actor& PushButton::GetDisabledImage()
297 return mDisabledImage;
300 Actor PushButton::GetDisabledImage() const
302 return mDisabledImage;
305 void PushButton::SetLabel( const std::string& label )
307 Toolkit::TextView textView ( Toolkit::TextView::New( label ) );
308 textView.SetWidthExceedPolicy( Toolkit::TextView::ShrinkToFit ); // Make sure our text always fits inside the button
309 SetLabel( textView );
312 void PushButton::SetLabel( Actor label )
314 Toolkit::PushButton handle( GetOwner() );
315 GetPushButtonPainter( mPainter )->SetLabel( handle, label );
318 Actor PushButton::GetLabel() const
323 Actor& PushButton::GetLabel()
328 Actor& PushButton::GetFadeOutBackgroundImage()
330 return mFadeOutBackgroundImage;
333 Actor& PushButton::GetFadeOutButtonImage()
335 return mFadeOutButtonImage;
338 Toolkit::PushButton::PressedSignalType& PushButton::PressedSignal()
340 return mPressedSignal;
343 Toolkit::PushButton::ReleasedSignalType& PushButton::ReleasedSignal()
345 return mReleasedSignal;
348 bool PushButton::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
350 Dali::BaseHandle handle( object );
352 bool connected( true );
353 Toolkit::PushButton button = Toolkit::PushButton::DownCast(handle);
355 if( Toolkit::PushButton::SIGNAL_STATE_CHANGED == signalName )
357 button.StateChangedSignal().Connect( tracker, functor );
359 else if( Toolkit::PushButton::SIGNAL_PRESSED == signalName )
361 button.PressedSignal().Connect( tracker, functor );
363 else if( Toolkit::PushButton::SIGNAL_RELEASED == signalName )
365 button.ReleasedSignal().Connect( tracker, functor );
369 // signalName does not match any signal
376 void PushButton::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
378 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( Dali::BaseHandle( object ) );
382 PushButton& pushButtonImpl( GetImplementation( pushButton ) );
384 if ( propertyIndex == Toolkit::Button::PROPERTY_AUTO_REPEATING )
386 pushButtonImpl.SetAutoRepeating( value.Get< bool >() );
388 else if ( propertyIndex == Toolkit::Button::PROPERTY_INITIAL_AUTO_REPEATING_DELAY )
390 pushButtonImpl.SetInitialAutoRepeatingDelay( value.Get< float >() );
392 else if ( propertyIndex == Toolkit::Button::PROPERTY_NEXT_AUTO_REPEATING_DELAY )
394 pushButtonImpl.SetNextAutoRepeatingDelay( value.Get< float >() );
396 else if ( propertyIndex == Toolkit::Button::PROPERTY_TOGGLABLE )
398 pushButtonImpl.SetToggleButton( value.Get< bool >() );
400 else if ( propertyIndex == Toolkit::Button::PROPERTY_TOGGLED )
402 pushButtonImpl.SetToggled( value.Get< bool >() );
404 else if ( propertyIndex == Toolkit::Button::PROPERTY_NORMAL_STATE_ACTOR )
406 pushButtonImpl.SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
408 else if ( propertyIndex == Toolkit::Button::PROPERTY_SELECTED_STATE_ACTOR )
410 pushButtonImpl.SetSelectedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
412 else if ( propertyIndex == Toolkit::Button::PROPERTY_DISABLED_STATE_ACTOR )
414 pushButtonImpl.SetDisabledImage( Scripting::NewActor( value.Get< Property::Map >() ) );
416 else if ( propertyIndex == Toolkit::Button::PROPERTY_LABEL_ACTOR )
418 pushButtonImpl.SetLabel( Scripting::NewActor( value.Get< Property::Map >() ) );
423 Property::Value PushButton::GetProperty( BaseObject* object, Property::Index propertyIndex )
425 Property::Value value;
427 Toolkit::PushButton pushButton = Toolkit::PushButton::DownCast( Dali::BaseHandle( object ) );
431 PushButton& pushButtonImpl( GetImplementation( pushButton ) );
433 if ( propertyIndex == Toolkit::Button::PROPERTY_AUTO_REPEATING )
435 value = pushButtonImpl.mAutoRepeating;
437 else if ( propertyIndex == Toolkit::Button::PROPERTY_INITIAL_AUTO_REPEATING_DELAY )
439 value = pushButtonImpl.mInitialAutoRepeatingDelay;
441 else if ( propertyIndex == Toolkit::Button::PROPERTY_NEXT_AUTO_REPEATING_DELAY )
443 value = pushButtonImpl.mNextAutoRepeatingDelay;
445 else if ( propertyIndex == Toolkit::Button::PROPERTY_TOGGLABLE )
447 value = pushButtonImpl.mToggleButton;
449 else if ( propertyIndex == Toolkit::Button::PROPERTY_TOGGLED )
451 value = pushButtonImpl.mToggled;
453 else if ( propertyIndex == Toolkit::Button::PROPERTY_NORMAL_STATE_ACTOR )
456 Scripting::CreatePropertyMap( pushButtonImpl.mButtonImage, map );
459 else if ( propertyIndex == Toolkit::Button::PROPERTY_SELECTED_STATE_ACTOR )
462 Scripting::CreatePropertyMap( pushButtonImpl.mSelectedImage, map );
465 else if ( propertyIndex == Toolkit::Button::PROPERTY_DISABLED_STATE_ACTOR )
468 Scripting::CreatePropertyMap( pushButtonImpl.mDisabledImage, map );
471 else if ( propertyIndex == Toolkit::Button::PROPERTY_LABEL_ACTOR )
474 Scripting::CreatePropertyMap( pushButtonImpl.mLabel, map );
482 void PushButton::OnButtonInitialize()
484 // Push button requires the Leave event.
486 root.SetLeaveRequired( true );
489 void PushButton::OnButtonDown()
493 Toolkit::PushButton handle( GetOwner() );
495 // Notifies the painter the button has been pressed.
496 GetPushButtonPainter( mPainter )->Pressed( handle );
500 SetUpTimer( mInitialAutoRepeatingDelay );
504 mPressedSignal.Emit( handle );
508 void PushButton::OnButtonUp()
510 if( ButtonDown == mState )
514 mToggled = !mToggled;
516 Toolkit::PushButton handle( GetOwner() );
518 // Notifies the painter the button has been toggled.
519 GetPushButtonPainter( mPainter )->Toggled( handle );
522 mStateChangedSignal.Emit( handle, mToggled );
526 Toolkit::PushButton handle( GetOwner() );
528 // Notifies the painter the button has been clicked.
529 GetPushButtonPainter( mPainter )->Released( handle );
530 GetPushButtonPainter( mPainter )->Clicked( handle );
534 mAutoRepeatingTimer.Reset();
538 mReleasedSignal.Emit( handle );
539 mClickedSignal.Emit( handle );
544 void PushButton::OnTouchPointLeave()
546 if( ButtonDown == mState )
550 Toolkit::PushButton handle( GetOwner() );
552 // Notifies the painter the button has been released.
553 GetPushButtonPainter( mPainter )->Released( handle );
557 mAutoRepeatingTimer.Reset();
561 mReleasedSignal.Emit( handle );
566 void PushButton::OnTouchPointInterrupted()
571 void PushButton::OnAnimationTimeSet( float animationTime )
573 GetPushButtonPainter( mPainter )->SetAnimationTime( animationTime );
576 float PushButton::OnAnimationTimeRequested() const
578 return GetPushButtonPainter( mPainter )->GetAnimationTime();
581 void PushButton::OnButtonStageDisconnection()
583 if( ButtonDown == mState )
587 Toolkit::PushButton handle( GetOwner() );
589 // Notifies the painter the button has been released.
590 GetPushButtonPainter( mPainter )->Released( handle );
594 mAutoRepeatingTimer.Reset();
600 PushButton::PushButton()
602 mAutoRepeating( false ),
603 mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ),
604 mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ),
605 mToggleButton( false ),
606 mAutoRepeatingTimer(),
608 mClickActionPerforming(false)
610 // Creates specific painter.
611 mPainter = PushButtonDefaultPainterPtr( new PushButtonDefaultPainter() );
614 PushButton::~PushButton()
616 if( mAutoRepeatingTimer )
618 mAutoRepeatingTimer.Reset();
624 void PushButton::SetUpTimer( float delay )
626 mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
627 mAutoRepeatingTimer.TickSignal().Connect( this, &PushButton::AutoRepeatingSlot );
628 mAutoRepeatingTimer.Start();
631 bool PushButton::AutoRepeatingSlot()
633 bool consumed = false;
636 // Restart the autorepeat timer.
637 SetUpTimer( mNextAutoRepeatingDelay );
639 Toolkit::PushButton handle( GetOwner() );
641 // Notifies the painter the button has been pressed.
642 GetPushButtonPainter( mPainter )->Pressed( handle );
645 consumed = mReleasedSignal.Emit( handle );
646 consumed |= mClickedSignal.Emit( handle );
647 consumed |= mPressedSignal.Emit( handle );
653 void PushButton::OnActivated()
655 // When the button is activated, it performs the click action
656 PropertyValueContainer attributes;
657 DoClickAction(attributes);
660 Vector3 PushButton::GetNaturalSize()
662 Vector3 size = Control::GetNaturalSize();
664 const bool widthIsZero = EqualsZero( size.width );
665 const bool heightIsZero = EqualsZero( size.height );
667 if( widthIsZero || heightIsZero )
669 // If background and background not scale9 try get size from that
670 ImageActor imageActor = FindImageActor( mButtonImage );
671 if( imageActor && imageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH )
673 Vector3 imageSize = RelayoutHelper::GetNaturalSize( imageActor );
677 size.width = imageSize.width;
682 size.height = imageSize.height;
686 ImageActor backgroundImageActor = FindImageActor( mBackgroundImage );
687 if( backgroundImageActor && backgroundImageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH )
689 Vector3 imageSize = RelayoutHelper::GetNaturalSize( backgroundImageActor );
693 size.width = std::max( size.width, imageSize.width );
698 size.height = std::max( size.height, imageSize.height );
702 // If label, test against it's size
703 Toolkit::TextView textView = Toolkit::TextView::DownCast( mLabel );
706 Vector3 textViewSize = textView.GetNaturalSize();
710 size.width = std::max( size.width, textViewSize.width + TEXT_PADDING * 2.0f );
715 size.height = std::max( size.height, textViewSize.height + TEXT_PADDING * 2.0f );
723 void PushButton::DoClickAction(const PropertyValueContainer& attributes)
725 // Prevents the button signals from doing a recursive loop by sending an action
726 // and re-emitting the signals.
727 if(!mClickActionPerforming)
729 mClickActionPerforming = true;
733 mClickActionPerforming = false;
737 bool PushButton::DoAction(BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes)
741 Dali::BaseHandle handle(object);
743 Toolkit::PushButton button = Toolkit::PushButton::DownCast(handle);
745 DALI_ASSERT_ALWAYS(button);
747 if(Toolkit::PushButton::ACTION_PUSH_BUTTON_CLICK == actionName)
749 GetImplementation(button).DoClickAction(attributes);
756 } // namespace Internal
758 } // namespace Toolkit