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 "button-impl.h"
22 #include <dali/public-api/events/touch-event.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/public-api/object/type-registry-helper.h>
25 #include <dali/public-api/actors/image-actor.h>
26 #include <dali/public-api/scripting/scripting.h>
29 #include <dali-toolkit/public-api/controls/text-view/text-view.h>
45 // empty handle as we cannot create button (but type registered for clicked signal)
49 // Setup properties, signals and actions using the type-registry.
50 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Button, Toolkit::Control, Create );
52 DALI_PROPERTY_REGISTRATION( Button, "disabled", BOOLEAN, DISABLED )
53 DALI_PROPERTY_REGISTRATION( Button, "auto-repeating", BOOLEAN, AUTO_REPEATING )
54 DALI_PROPERTY_REGISTRATION( Button, "initial-auto-repeating-delay", FLOAT, INITIAL_AUTO_REPEATING_DELAY )
55 DALI_PROPERTY_REGISTRATION( Button, "next-auto-repeating-delay", FLOAT, NEXT_AUTO_REPEATING_DELAY )
56 DALI_PROPERTY_REGISTRATION( Button, "togglable", BOOLEAN, TOGGLABLE )
57 DALI_PROPERTY_REGISTRATION( Button, "selected", BOOLEAN, SELECTED )
58 DALI_PROPERTY_REGISTRATION( Button, "normal-state-actor", MAP, NORMAL_STATE_ACTOR )
59 DALI_PROPERTY_REGISTRATION( Button, "selected-state-actor", MAP, SELECTED_STATE_ACTOR )
60 DALI_PROPERTY_REGISTRATION( Button, "disabled-state-actor", MAP, DISABLED_STATE_ACTOR )
61 DALI_PROPERTY_REGISTRATION( Button, "label-actor", MAP, LABEL_ACTOR )
63 DALI_SIGNAL_REGISTRATION( Button, "pressed", SIGNAL_PRESSED )
64 DALI_SIGNAL_REGISTRATION( Button, "released", SIGNAL_RELEASED )
65 DALI_SIGNAL_REGISTRATION( Button, "clicked", SIGNAL_CLICKED )
66 DALI_SIGNAL_REGISTRATION( Button, "state-changed", SIGNAL_STATE_CHANGED )
68 DALI_ACTION_REGISTRATION( Button, "button-click", ACTION_BUTTON_CLICK )
70 DALI_TYPE_REGISTRATION_END()
72 const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f );
73 const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f );
75 } // unnamed namespace
78 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
79 mAutoRepeatingTimer(),
81 mAutoRepeating( false ),
82 mTogglableButton( false ),
84 mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ),
85 mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ),
86 mAnimationTime( 0.0f ),
87 mClickActionPerforming( false ),
94 if( mAutoRepeatingTimer )
96 mAutoRepeatingTimer.Reset();
100 void Button::SetDisabled( bool disabled )
102 if( disabled != mDisabled )
104 mDisabled = disabled;
106 OnDisabled( mDisabled );
110 bool Button::IsDisabled() const
115 void Button::SetAutoRepeating( bool autoRepeating )
117 mAutoRepeating = autoRepeating;
119 // An autorepeating button can't be a togglable button.
122 mTogglableButton = false;
126 // Emit a signal is not wanted, only change the appearance.
136 bool Button::IsAutoRepeating() const
138 return mAutoRepeating;
141 void Button::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
143 DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
144 mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
147 float Button::GetInitialAutoRepeatingDelay() const
149 return mInitialAutoRepeatingDelay;
152 void Button::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
154 DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
155 mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
158 float Button::GetNextAutoRepeatingDelay() const
160 return mNextAutoRepeatingDelay;
163 void Button::SetTogglableButton( bool togglable )
165 mTogglableButton = togglable;
167 // A togglable button can't be an autorepeating button.
170 mAutoRepeating = false;
174 bool Button::IsTogglableButton() const
176 return mTogglableButton;
179 void Button::SetSelected( bool selected )
181 if( !mDisabled && mTogglableButton && ( selected != mSelected ) )
183 // Notifies the derived class the button has been selected.
184 OnSelected( selected );
186 mSelected = selected;
188 Toolkit::Button handle( GetOwner() );
191 mStateChangedSignal.Emit( handle );
197 bool Button::IsSelected() const
199 return mTogglableButton && mSelected;
202 void Button::SetAnimationTime( float animationTime )
204 mAnimationTime = animationTime;
207 float Button::GetAnimationTime() const
209 return mAnimationTime;
212 void Button::SetLabel( const std::string& label )
214 Toolkit::TextView textView = Toolkit::TextView::New( label );
215 textView.SetWidthExceedPolicy( Toolkit::TextView::ShrinkToFit ); // Make sure our text always fits inside the button
216 SetLabel( textView );
219 void Button::SetLabel( Actor label )
221 if( mLabel != label )
223 if( mLabel && mLabel.GetParent() )
225 mLabel.GetParent().Remove( mLabel );
236 Actor Button::GetLabel() const
241 Actor& Button::GetLabel()
246 Actor Button::GetButtonImage() const
248 return mButtonContent;
251 Actor& Button::GetButtonImage()
253 return mButtonContent;
256 Actor Button::GetSelectedImage() const
258 return mSelectedContent;
261 Actor& Button::GetSelectedImage()
263 return mSelectedContent;
266 Actor Button::GetBackgroundImage() const
268 return mBackgroundContent;
271 Actor& Button::GetBackgroundImage()
273 return mBackgroundContent;
276 Actor Button::GetDisabledImage() const
278 return mDisabledContent;
281 Actor& Button::GetDisabledImage()
283 return mDisabledContent;
286 Actor Button::GetDisabledSelectedImage() const
288 return mDisabledSelectedContent;
291 Actor& Button::GetDisabledSelectedImage()
293 return mDisabledSelectedContent;
296 Actor Button::GetDisabledBackgroundImage() const
298 return mDisabledBackgroundContent;
301 Actor& Button::GetDisabledBackgroundImage()
303 return mDisabledBackgroundContent;
306 bool Button::DoAction( BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes )
310 Dali::BaseHandle handle( object );
312 Toolkit::Button button = Toolkit::Button::DownCast( handle );
314 DALI_ASSERT_ALWAYS( button );
316 if( 0 == strcmp( actionName.c_str(), ACTION_BUTTON_CLICK ) )
318 GetImplementation( button ).DoClickAction( attributes );
325 void Button::DoClickAction( const PropertyValueContainer& attributes )
327 // Prevents the button signals from doing a recursive loop by sending an action
328 // and re-emitting the signals.
329 if( !mClickActionPerforming )
331 mClickActionPerforming = true;
335 mClickActionPerforming = false;
339 void Button::OnButtonStageDisconnection()
341 if( ButtonDown == mState )
343 if( !mTogglableButton )
345 Toolkit::Button handle( GetOwner() );
347 // Notifies the derived class the button has been released.
352 mAutoRepeatingTimer.Reset();
358 void Button::OnButtonDown()
360 if( !mTogglableButton )
362 Toolkit::Button handle( GetOwner() );
364 // Notifies the derived class the button has been pressed.
369 SetUpTimer( mInitialAutoRepeatingDelay );
373 mPressedSignal.Emit( handle );
377 void Button::OnButtonUp()
379 if( ButtonDown == mState )
381 if( mTogglableButton )
383 SetSelected( !mSelected );
387 // Notifies the derived class the button has been clicked.
393 mAutoRepeatingTimer.Reset();
396 Toolkit::Button handle( GetOwner() );
399 mReleasedSignal.Emit( handle );
400 mClickedSignal.Emit( handle );
405 void Button::OnTouchPointLeave()
407 if( ButtonDown == mState )
409 if( !mTogglableButton )
411 Toolkit::Button handle( GetOwner() );
413 // Notifies the derived class the button has been released.
418 mAutoRepeatingTimer.Reset();
422 mReleasedSignal.Emit( handle );
427 void Button::OnTouchPointInterrupted()
432 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
434 return mPressedSignal;
437 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
439 return mReleasedSignal;
442 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
444 return mClickedSignal;
447 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
449 return mStateChangedSignal;
452 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
454 Dali::BaseHandle handle( object );
456 bool connected( true );
457 Toolkit::Button button = Toolkit::Button::DownCast( handle );
459 if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
461 button.PressedSignal().Connect( tracker, functor );
463 else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
465 button.ReleasedSignal().Connect( tracker, functor );
467 else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
469 button.ClickedSignal().Connect( tracker, functor );
471 else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
473 button.StateChangedSignal().Connect( tracker, functor );
477 // signalName does not match any signal
484 bool Button::OnTouchEvent(const TouchEvent& event)
486 // Only events are processed when the button is not disabled and the touch event has only
488 if( ( !mDisabled ) && ( 1 == event.GetPointCount() ) )
490 switch( event.GetPoint(0).state )
492 case TouchPoint::Down:
494 OnButtonDown(); // Notification for derived classes.
496 // Sets the button state to ButtonDown.
502 OnButtonUp(); // Notification for derived classes.
504 // Sets the button state to ButtonUp.
508 case TouchPoint::Interrupted:
510 OnTouchPointInterrupted(); // Notification for derived classes.
512 // Sets the button state to the default (ButtonUp).
516 case TouchPoint::Leave:
518 OnTouchPointLeave(); // Notification for derived classes.
520 // Sets the button state to the default (ButtonUp).
524 case TouchPoint::Motion:
525 case TouchPoint::Stationary: // FALLTHROUGH
532 DALI_ASSERT_ALWAYS( !"Point status unhandled." );
537 else if( 1 < event.GetPointCount() )
539 OnTouchPointLeave(); // Notification for derived classes.
541 // Sets the button state to the default (ButtonUp).
548 void Button::OnInitialize()
552 mTapDetector = TapGestureDetector::New();
553 mTapDetector.Attach( self );
554 mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
556 OnButtonInitialize();
558 self.SetKeyboardFocusable( true );
561 void Button::OnActivated()
563 // When the button is activated, it performs the click action
564 PropertyValueContainer attributes;
565 DoClickAction( attributes );
568 void Button::OnTap(Actor actor, const TapGesture& tap)
573 void Button::SetUpTimer( float delay )
575 mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
576 mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
577 mAutoRepeatingTimer.Start();
580 bool Button::AutoRepeatingSlot()
582 bool consumed = false;
585 // Restart the autorepeat timer.
586 SetUpTimer( mNextAutoRepeatingDelay );
588 Toolkit::Button handle( GetOwner() );
590 // Notifies the derived class the button has been pressed.
594 consumed = mReleasedSignal.Emit( handle );
595 consumed |= mClickedSignal.Emit( handle );
596 consumed |= mPressedSignal.Emit( handle );
602 void Button::OnControlStageDisconnection()
604 OnButtonStageDisconnection(); // Notification for derived classes.
608 Button::ButtonState Button::GetState()
613 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
615 Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
621 case Toolkit::Button::Property::DISABLED:
623 GetImplementation( button ).SetDisabled( value.Get<bool>() );
627 case Toolkit::Button::Property::AUTO_REPEATING:
629 GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
633 case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
635 GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
639 case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
641 GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
645 case Toolkit::Button::Property::TOGGLABLE:
647 GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
651 case Toolkit::Button::Property::SELECTED:
653 GetImplementation( button ).SetSelected( value.Get< bool >() );
657 case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
659 GetImplementation( button ).SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
663 case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
665 GetImplementation( button ).SetSelectedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
669 case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
671 GetImplementation( button ).SetDisabledImage( Scripting::NewActor( value.Get< Property::Map >() ) );
675 case Toolkit::Button::Property::LABEL_ACTOR:
677 GetImplementation( button ).SetLabel( Scripting::NewActor( value.Get< Property::Map >() ) );
684 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
686 Property::Value value;
688 Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
692 switch ( propertyIndex )
694 case Toolkit::Button::Property::DISABLED:
696 value = GetImplementation( button ).mDisabled;
700 case Toolkit::Button::Property::AUTO_REPEATING:
702 value = GetImplementation( button ).mAutoRepeating;
706 case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
708 value = GetImplementation( button ).mInitialAutoRepeatingDelay;
712 case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
714 value = GetImplementation( button ).mNextAutoRepeatingDelay;
718 case Toolkit::Button::Property::TOGGLABLE:
720 value = GetImplementation( button ).mTogglableButton;
724 case Toolkit::Button::Property::SELECTED:
726 value = GetImplementation( button ).mSelected;
730 case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
733 Scripting::CreatePropertyMap( GetImplementation( button ).mButtonContent, map );
738 case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
741 Scripting::CreatePropertyMap( GetImplementation( button ).mSelectedContent, map );
746 case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
749 Scripting::CreatePropertyMap( GetImplementation( button ).mDisabledContent, map );
754 case Toolkit::Button::Property::LABEL_ACTOR:
757 Scripting::CreatePropertyMap( GetImplementation( button ).mLabel, map );
767 } // namespace Internal
769 } // namespace Toolkit