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>
44 // empty handle as we cannot create button (but type registered for clicked signal)
48 // Setup properties, signals and actions using the type-registry.
49 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Button, Toolkit::Control, Create );
51 DALI_PROPERTY_REGISTRATION( Button, "disabled", BOOLEAN, DISABLED )
52 DALI_PROPERTY_REGISTRATION( Button, "auto-repeating", BOOLEAN, AUTO_REPEATING )
53 DALI_PROPERTY_REGISTRATION( Button, "initial-auto-repeating-delay", FLOAT, INITIAL_AUTO_REPEATING_DELAY )
54 DALI_PROPERTY_REGISTRATION( Button, "next-auto-repeating-delay", FLOAT, NEXT_AUTO_REPEATING_DELAY )
55 DALI_PROPERTY_REGISTRATION( Button, "togglable", BOOLEAN, TOGGLABLE )
56 DALI_PROPERTY_REGISTRATION( Button, "selected", BOOLEAN, SELECTED )
57 DALI_PROPERTY_REGISTRATION( Button, "normal-state-actor", MAP, NORMAL_STATE_ACTOR )
58 DALI_PROPERTY_REGISTRATION( Button, "selected-state-actor", MAP, SELECTED_STATE_ACTOR )
59 DALI_PROPERTY_REGISTRATION( Button, "disabled-state-actor", MAP, DISABLED_STATE_ACTOR )
60 DALI_PROPERTY_REGISTRATION( Button, "label-actor", MAP, LABEL_ACTOR )
62 DALI_SIGNAL_REGISTRATION( Button, "pressed", SIGNAL_PRESSED )
63 DALI_SIGNAL_REGISTRATION( Button, "released", SIGNAL_RELEASED )
64 DALI_SIGNAL_REGISTRATION( Button, "clicked", SIGNAL_CLICKED )
65 DALI_SIGNAL_REGISTRATION( Button, "state-changed", SIGNAL_STATE_CHANGED )
67 DALI_ACTION_REGISTRATION( Button, "button-click", ACTION_BUTTON_CLICK )
69 DALI_TYPE_REGISTRATION_END()
71 const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f );
72 const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f );
74 } // unnamed namespace
77 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
78 mAutoRepeatingTimer(),
80 mAutoRepeating( false ),
81 mTogglableButton( false ),
83 mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ),
84 mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ),
85 mAnimationTime( 0.0f ),
86 mClickActionPerforming( false ),
93 if( mAutoRepeatingTimer )
95 mAutoRepeatingTimer.Reset();
99 void Button::SetDisabled( bool disabled )
101 if( disabled != mDisabled )
103 mDisabled = disabled;
105 OnDisabled( mDisabled );
109 bool Button::IsDisabled() const
114 void Button::SetAutoRepeating( bool autoRepeating )
116 mAutoRepeating = autoRepeating;
118 // An autorepeating button can't be a togglable button.
121 mTogglableButton = false;
125 // Emit a signal is not wanted, only change the appearance.
135 bool Button::IsAutoRepeating() const
137 return mAutoRepeating;
140 void Button::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
142 DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
143 mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
146 float Button::GetInitialAutoRepeatingDelay() const
148 return mInitialAutoRepeatingDelay;
151 void Button::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
153 DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
154 mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
157 float Button::GetNextAutoRepeatingDelay() const
159 return mNextAutoRepeatingDelay;
162 void Button::SetTogglableButton( bool togglable )
164 mTogglableButton = togglable;
166 // A togglable button can't be an autorepeating button.
169 mAutoRepeating = false;
173 bool Button::IsTogglableButton() const
175 return mTogglableButton;
178 void Button::SetSelected( bool selected )
180 if( !mDisabled && mTogglableButton && ( selected != mSelected ) )
182 // Notifies the derived class the button has been selected.
183 OnSelected( selected );
185 mSelected = selected;
187 Toolkit::Button handle( GetOwner() );
190 mStateChangedSignal.Emit( handle );
196 bool Button::IsSelected() const
198 return mTogglableButton && mSelected;
201 void Button::SetAnimationTime( float animationTime )
203 mAnimationTime = animationTime;
206 float Button::GetAnimationTime() const
208 return mAnimationTime;
211 void Button::SetLabel( const std::string& label )
215 void Button::SetLabel( Actor label )
217 if( mLabel != label )
219 if( mLabel && mLabel.GetParent() )
221 mLabel.GetParent().Remove( mLabel );
232 Actor Button::GetLabel() const
237 Actor& Button::GetLabel()
242 Actor Button::GetButtonImage() const
244 return mButtonContent;
247 Actor& Button::GetButtonImage()
249 return mButtonContent;
252 Actor Button::GetSelectedImage() const
254 return mSelectedContent;
257 Actor& Button::GetSelectedImage()
259 return mSelectedContent;
262 Actor Button::GetBackgroundImage() const
264 return mBackgroundContent;
267 Actor& Button::GetBackgroundImage()
269 return mBackgroundContent;
272 Actor Button::GetDisabledImage() const
274 return mDisabledContent;
277 Actor& Button::GetDisabledImage()
279 return mDisabledContent;
282 Actor Button::GetDisabledSelectedImage() const
284 return mDisabledSelectedContent;
287 Actor& Button::GetDisabledSelectedImage()
289 return mDisabledSelectedContent;
292 Actor Button::GetDisabledBackgroundImage() const
294 return mDisabledBackgroundContent;
297 Actor& Button::GetDisabledBackgroundImage()
299 return mDisabledBackgroundContent;
302 bool Button::DoAction( BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes )
306 Dali::BaseHandle handle( object );
308 Toolkit::Button button = Toolkit::Button::DownCast( handle );
310 DALI_ASSERT_ALWAYS( button );
312 if( 0 == strcmp( actionName.c_str(), ACTION_BUTTON_CLICK ) )
314 GetImplementation( button ).DoClickAction( attributes );
321 void Button::DoClickAction( const PropertyValueContainer& attributes )
323 // Prevents the button signals from doing a recursive loop by sending an action
324 // and re-emitting the signals.
325 if( !mClickActionPerforming )
327 mClickActionPerforming = true;
331 mClickActionPerforming = false;
335 void Button::OnButtonStageDisconnection()
337 if( ButtonDown == mState )
339 if( !mTogglableButton )
341 Toolkit::Button handle( GetOwner() );
343 // Notifies the derived class the button has been released.
348 mAutoRepeatingTimer.Reset();
354 void Button::OnButtonDown()
356 if( !mTogglableButton )
358 Toolkit::Button handle( GetOwner() );
360 // Notifies the derived class the button has been pressed.
365 SetUpTimer( mInitialAutoRepeatingDelay );
369 mPressedSignal.Emit( handle );
373 void Button::OnButtonUp()
375 if( ButtonDown == mState )
377 if( mTogglableButton )
379 SetSelected( !mSelected );
383 // Notifies the derived class the button has been clicked.
389 mAutoRepeatingTimer.Reset();
392 Toolkit::Button handle( GetOwner() );
395 mReleasedSignal.Emit( handle );
396 mClickedSignal.Emit( handle );
401 void Button::OnTouchPointLeave()
403 if( ButtonDown == mState )
405 if( !mTogglableButton )
407 Toolkit::Button handle( GetOwner() );
409 // Notifies the derived class the button has been released.
414 mAutoRepeatingTimer.Reset();
418 mReleasedSignal.Emit( handle );
423 void Button::OnTouchPointInterrupted()
428 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
430 return mPressedSignal;
433 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
435 return mReleasedSignal;
438 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
440 return mClickedSignal;
443 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
445 return mStateChangedSignal;
448 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
450 Dali::BaseHandle handle( object );
452 bool connected( true );
453 Toolkit::Button button = Toolkit::Button::DownCast( handle );
455 if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
457 button.PressedSignal().Connect( tracker, functor );
459 else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
461 button.ReleasedSignal().Connect( tracker, functor );
463 else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
465 button.ClickedSignal().Connect( tracker, functor );
467 else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
469 button.StateChangedSignal().Connect( tracker, functor );
473 // signalName does not match any signal
480 bool Button::OnTouchEvent(const TouchEvent& event)
482 // Only events are processed when the button is not disabled and the touch event has only
484 if( ( !mDisabled ) && ( 1 == event.GetPointCount() ) )
486 switch( event.GetPoint(0).state )
488 case TouchPoint::Down:
490 OnButtonDown(); // Notification for derived classes.
492 // Sets the button state to ButtonDown.
498 OnButtonUp(); // Notification for derived classes.
500 // Sets the button state to ButtonUp.
504 case TouchPoint::Interrupted:
506 OnTouchPointInterrupted(); // Notification for derived classes.
508 // Sets the button state to the default (ButtonUp).
512 case TouchPoint::Leave:
514 OnTouchPointLeave(); // Notification for derived classes.
516 // Sets the button state to the default (ButtonUp).
520 case TouchPoint::Motion:
521 case TouchPoint::Stationary: // FALLTHROUGH
528 DALI_ASSERT_ALWAYS( !"Point status unhandled." );
533 else if( 1 < event.GetPointCount() )
535 OnTouchPointLeave(); // Notification for derived classes.
537 // Sets the button state to the default (ButtonUp).
544 void Button::OnInitialize()
548 mTapDetector = TapGestureDetector::New();
549 mTapDetector.Attach( self );
550 mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
552 OnButtonInitialize();
554 self.SetKeyboardFocusable( true );
557 void Button::OnActivated()
559 // When the button is activated, it performs the click action
560 PropertyValueContainer attributes;
561 DoClickAction( attributes );
564 void Button::OnTap(Actor actor, const TapGesture& tap)
569 void Button::SetUpTimer( float delay )
571 mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
572 mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
573 mAutoRepeatingTimer.Start();
576 bool Button::AutoRepeatingSlot()
578 bool consumed = false;
581 // Restart the autorepeat timer.
582 SetUpTimer( mNextAutoRepeatingDelay );
584 Toolkit::Button handle( GetOwner() );
586 // Notifies the derived class the button has been pressed.
590 consumed = mReleasedSignal.Emit( handle );
591 consumed |= mClickedSignal.Emit( handle );
592 consumed |= mPressedSignal.Emit( handle );
598 void Button::OnControlStageDisconnection()
600 OnButtonStageDisconnection(); // Notification for derived classes.
604 Button::ButtonState Button::GetState()
609 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
611 Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
617 case Toolkit::Button::Property::DISABLED:
619 GetImplementation( button ).SetDisabled( value.Get<bool>() );
623 case Toolkit::Button::Property::AUTO_REPEATING:
625 GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
629 case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
631 GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
635 case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
637 GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
641 case Toolkit::Button::Property::TOGGLABLE:
643 GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
647 case Toolkit::Button::Property::SELECTED:
649 GetImplementation( button ).SetSelected( value.Get< bool >() );
653 case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
655 GetImplementation( button ).SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
659 case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
661 GetImplementation( button ).SetSelectedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
665 case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
667 GetImplementation( button ).SetDisabledImage( Scripting::NewActor( value.Get< Property::Map >() ) );
671 case Toolkit::Button::Property::LABEL_ACTOR:
673 GetImplementation( button ).SetLabel( Scripting::NewActor( value.Get< Property::Map >() ) );
680 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
682 Property::Value value;
684 Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
688 switch ( propertyIndex )
690 case Toolkit::Button::Property::DISABLED:
692 value = GetImplementation( button ).mDisabled;
696 case Toolkit::Button::Property::AUTO_REPEATING:
698 value = GetImplementation( button ).mAutoRepeating;
702 case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
704 value = GetImplementation( button ).mInitialAutoRepeatingDelay;
708 case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
710 value = GetImplementation( button ).mNextAutoRepeatingDelay;
714 case Toolkit::Button::Property::TOGGLABLE:
716 value = GetImplementation( button ).mTogglableButton;
720 case Toolkit::Button::Property::SELECTED:
722 value = GetImplementation( button ).mSelected;
726 case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
729 Scripting::CreatePropertyMap( GetImplementation( button ).mButtonContent, map );
734 case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
737 Scripting::CreatePropertyMap( GetImplementation( button ).mSelectedContent, map );
742 case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
745 Scripting::CreatePropertyMap( GetImplementation( button ).mDisabledContent, map );
750 case Toolkit::Button::Property::LABEL_ACTOR:
753 Scripting::CreatePropertyMap( GetImplementation( button ).mLabel, map );
763 } // namespace Internal
765 } // namespace Toolkit