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/actors/image-actor.h>
25 #include <dali/public-api/scripting/scripting.h>
28 #include <dali-toolkit/public-api/controls/text-view/text-view.h>
36 const Property::Index Button::PROPERTY_DISABLED = Internal::Button::BUTTON_PROPERTY_START_INDEX;
37 const Property::Index Button::PROPERTY_AUTO_REPEATING = Internal::Button::BUTTON_PROPERTY_START_INDEX + 1;
38 const Property::Index Button::PROPERTY_INITIAL_AUTO_REPEATING_DELAY = Internal::Button::BUTTON_PROPERTY_START_INDEX + 2;
39 const Property::Index Button::PROPERTY_NEXT_AUTO_REPEATING_DELAY = Internal::Button::BUTTON_PROPERTY_START_INDEX + 3;
40 const Property::Index Button::PROPERTY_TOGGLABLE = Internal::Button::BUTTON_PROPERTY_START_INDEX + 4;
41 const Property::Index Button::PROPERTY_SELECTED = Internal::Button::BUTTON_PROPERTY_START_INDEX + 5;
42 const Property::Index Button::PROPERTY_NORMAL_STATE_ACTOR = Internal::Button::BUTTON_PROPERTY_START_INDEX + 6;
43 const Property::Index Button::PROPERTY_SELECTED_STATE_ACTOR = Internal::Button::BUTTON_PROPERTY_START_INDEX + 7;
44 const Property::Index Button::PROPERTY_DISABLED_STATE_ACTOR = Internal::Button::BUTTON_PROPERTY_START_INDEX + 8;
45 const Property::Index Button::PROPERTY_LABEL_ACTOR = Internal::Button::BUTTON_PROPERTY_START_INDEX + 9;
53 const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f );
54 const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f );
58 const char* const SIGNAL_PRESSED = "pressed";
59 const char* const SIGNAL_RELEASED = "released";
60 const char* const SIGNAL_CLICKED = "clicked";
61 const char* const SIGNAL_STATE_CHANGED = "state-changed";
65 const char* const ACTION_BUTTON_CLICK = "button-click";
69 // empty handle as we cannot create button (but type registered for clicked signal)
73 TypeRegistration typeRegistration( typeid( Toolkit::Button ), typeid( Toolkit::Control ), Create );
75 SignalConnectorType signalConnector1( typeRegistration, SIGNAL_PRESSED , &Button::DoConnectSignal );
76 SignalConnectorType signalConnector2( typeRegistration, SIGNAL_RELEASED, &Button::DoConnectSignal );
77 SignalConnectorType signalConnector3( typeRegistration, SIGNAL_CLICKED, &Button::DoConnectSignal );
78 SignalConnectorType signalConnector4( typeRegistration, SIGNAL_STATE_CHANGED, &Button::DoConnectSignal );
80 TypeAction action1( typeRegistration, ACTION_BUTTON_CLICK, &Button::DoAction );
82 PropertyRegistration property1( typeRegistration, "disabled", Toolkit::Button::PROPERTY_DISABLED, Property::BOOLEAN, &Button::SetProperty, &Button::GetProperty );
83 PropertyRegistration property2( typeRegistration, "auto-repeating", Toolkit::Button::PROPERTY_AUTO_REPEATING, Property::BOOLEAN, &Button::SetProperty, &Button::GetProperty );
84 PropertyRegistration property3( typeRegistration, "initial-auto-repeating-delay", Toolkit::Button::PROPERTY_INITIAL_AUTO_REPEATING_DELAY, Property::FLOAT, &Button::SetProperty, &Button::GetProperty );
85 PropertyRegistration property4( typeRegistration, "next-auto-repeating-delay", Toolkit::Button::PROPERTY_NEXT_AUTO_REPEATING_DELAY, Property::FLOAT, &Button::SetProperty, &Button::GetProperty );
86 PropertyRegistration property5( typeRegistration, "togglable", Toolkit::Button::PROPERTY_TOGGLABLE, Property::BOOLEAN, &Button::SetProperty, &Button::GetProperty );
87 PropertyRegistration property6( typeRegistration, "selected", Toolkit::Button::PROPERTY_SELECTED, Property::BOOLEAN, &Button::SetProperty, &Button::GetProperty );
88 PropertyRegistration property7( typeRegistration, "normal-state-actor", Toolkit::Button::PROPERTY_NORMAL_STATE_ACTOR, Property::MAP, &Button::SetProperty, &Button::GetProperty );
89 PropertyRegistration property8( typeRegistration, "selected-state-actor", Toolkit::Button::PROPERTY_SELECTED_STATE_ACTOR, Property::MAP, &Button::SetProperty, &Button::GetProperty );
90 PropertyRegistration property9( typeRegistration, "disabled-state-actor", Toolkit::Button::PROPERTY_DISABLED_STATE_ACTOR, Property::MAP, &Button::SetProperty, &Button::GetProperty );
91 PropertyRegistration property10( typeRegistration, "label-actor", Toolkit::Button::PROPERTY_LABEL_ACTOR, Property::MAP, &Button::SetProperty, &Button::GetProperty );
93 } // unnamed namespace
96 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
97 mAutoRepeatingTimer(),
99 mAutoRepeating( false ),
100 mTogglableButton( false ),
102 mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ),
103 mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ),
104 mAnimationTime( 0.0f ),
105 mClickActionPerforming( false ),
112 if( mAutoRepeatingTimer )
114 mAutoRepeatingTimer.Reset();
118 void Button::SetDisabled( bool disabled )
120 if( disabled != mDisabled )
122 mDisabled = disabled;
124 OnDisabled( mDisabled );
128 bool Button::IsDisabled() const
133 void Button::SetAutoRepeating( bool autoRepeating )
135 mAutoRepeating = autoRepeating;
137 // An autorepeating button can't be a togglable button.
140 mTogglableButton = false;
144 // Emit a signal is not wanted, only change the appearance.
154 bool Button::IsAutoRepeating() const
156 return mAutoRepeating;
159 void Button::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
161 DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
162 mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
165 float Button::GetInitialAutoRepeatingDelay() const
167 return mInitialAutoRepeatingDelay;
170 void Button::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
172 DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
173 mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
176 float Button::GetNextAutoRepeatingDelay() const
178 return mNextAutoRepeatingDelay;
181 void Button::SetTogglableButton( bool togglable )
183 mTogglableButton = togglable;
185 // A togglable button can't be an autorepeating button.
188 mAutoRepeating = false;
192 bool Button::IsTogglableButton() const
194 return mTogglableButton;
197 void Button::SetSelected( bool selected )
199 if( !mDisabled && mTogglableButton && ( selected != mSelected ) )
201 // Notifies the derived class the button has been selected.
202 OnSelected( selected );
204 mSelected = selected;
206 Toolkit::Button handle( GetOwner() );
209 mStateChangedSignal.Emit( handle );
215 bool Button::IsSelected() const
217 return mTogglableButton && mSelected;
220 void Button::SetAnimationTime( float animationTime )
222 mAnimationTime = animationTime;
225 float Button::GetAnimationTime() const
227 return mAnimationTime;
230 void Button::SetLabel( const std::string& label )
232 Toolkit::TextView textView = Toolkit::TextView::New( label );
233 textView.SetWidthExceedPolicy( Toolkit::TextView::ShrinkToFit ); // Make sure our text always fits inside the button
234 SetLabel( textView );
237 void Button::SetLabel( Actor label )
239 if( mLabel != label )
241 if( mLabel && mLabel.GetParent() )
243 mLabel.GetParent().Remove( mLabel );
254 Actor Button::GetLabel() const
259 Actor& Button::GetLabel()
264 Actor Button::GetButtonImage() const
266 return mButtonContent;
269 Actor& Button::GetButtonImage()
271 return mButtonContent;
274 Actor Button::GetSelectedImage() const
276 return mSelectedContent;
279 Actor& Button::GetSelectedImage()
281 return mSelectedContent;
284 Actor Button::GetBackgroundImage() const
286 return mBackgroundContent;
289 Actor& Button::GetBackgroundImage()
291 return mBackgroundContent;
294 Actor Button::GetDisabledImage() const
296 return mDisabledContent;
299 Actor& Button::GetDisabledImage()
301 return mDisabledContent;
304 Actor Button::GetDisabledSelectedImage() const
306 return mDisabledSelectedContent;
309 Actor& Button::GetDisabledSelectedImage()
311 return mDisabledSelectedContent;
314 Actor Button::GetDisabledBackgroundImage() const
316 return mDisabledBackgroundContent;
319 Actor& Button::GetDisabledBackgroundImage()
321 return mDisabledBackgroundContent;
324 bool Button::DoAction( BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes )
328 Dali::BaseHandle handle( object );
330 Toolkit::Button button = Toolkit::Button::DownCast( handle );
332 DALI_ASSERT_ALWAYS( button );
334 if( 0 == strcmp( actionName.c_str(), ACTION_BUTTON_CLICK ) )
336 GetImplementation( button ).DoClickAction( attributes );
343 void Button::DoClickAction( const PropertyValueContainer& attributes )
345 // Prevents the button signals from doing a recursive loop by sending an action
346 // and re-emitting the signals.
347 if( !mClickActionPerforming )
349 mClickActionPerforming = true;
353 mClickActionPerforming = false;
357 void Button::OnButtonStageDisconnection()
359 if( ButtonDown == mState )
361 if( !mTogglableButton )
363 Toolkit::Button handle( GetOwner() );
365 // Notifies the derived class the button has been released.
370 mAutoRepeatingTimer.Reset();
376 void Button::OnButtonDown()
378 if( !mTogglableButton )
380 Toolkit::Button handle( GetOwner() );
382 // Notifies the derived class the button has been pressed.
387 SetUpTimer( mInitialAutoRepeatingDelay );
391 mPressedSignal.Emit( handle );
395 void Button::OnButtonUp()
397 if( ButtonDown == mState )
399 if( mTogglableButton )
401 SetSelected( !mSelected );
405 // Notifies the derived class the button has been clicked.
411 mAutoRepeatingTimer.Reset();
414 Toolkit::Button handle( GetOwner() );
417 mReleasedSignal.Emit( handle );
418 mClickedSignal.Emit( handle );
423 void Button::OnTouchPointLeave()
425 if( ButtonDown == mState )
427 if( !mTogglableButton )
429 Toolkit::Button handle( GetOwner() );
431 // Notifies the derived class the button has been released.
436 mAutoRepeatingTimer.Reset();
440 mReleasedSignal.Emit( handle );
445 void Button::OnTouchPointInterrupted()
450 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
452 return mPressedSignal;
455 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
457 return mReleasedSignal;
460 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
462 return mClickedSignal;
465 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
467 return mStateChangedSignal;
470 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
472 Dali::BaseHandle handle( object );
474 bool connected( true );
475 Toolkit::Button button = Toolkit::Button::DownCast( handle );
477 if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
479 button.PressedSignal().Connect( tracker, functor );
481 else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
483 button.ReleasedSignal().Connect( tracker, functor );
485 else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
487 button.ClickedSignal().Connect( tracker, functor );
489 else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
491 button.StateChangedSignal().Connect( tracker, functor );
495 // signalName does not match any signal
502 bool Button::OnTouchEvent(const TouchEvent& event)
504 // Only events are processed when the button is not disabled and the touch event has only
506 if( ( !mDisabled ) && ( 1 == event.GetPointCount() ) )
508 switch( event.GetPoint(0).state )
510 case TouchPoint::Down:
512 OnButtonDown(); // Notification for derived classes.
514 // Sets the button state to ButtonDown.
520 OnButtonUp(); // Notification for derived classes.
522 // Sets the button state to ButtonUp.
526 case TouchPoint::Interrupted:
528 OnTouchPointInterrupted(); // Notification for derived classes.
530 // Sets the button state to the default (ButtonUp).
534 case TouchPoint::Leave:
536 OnTouchPointLeave(); // Notification for derived classes.
538 // Sets the button state to the default (ButtonUp).
542 case TouchPoint::Motion:
543 case TouchPoint::Stationary: // FALLTHROUGH
550 DALI_ASSERT_ALWAYS( !"Point status unhandled." );
555 else if( 1 < event.GetPointCount() )
557 OnTouchPointLeave(); // Notification for derived classes.
559 // Sets the button state to the default (ButtonUp).
566 void Button::OnInitialize()
570 mTapDetector = TapGestureDetector::New();
571 mTapDetector.Attach( self );
572 mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
574 OnButtonInitialize();
576 self.SetKeyboardFocusable( true );
579 void Button::OnActivated()
581 // When the button is activated, it performs the click action
582 PropertyValueContainer attributes;
583 DoClickAction( attributes );
586 void Button::OnTap(Actor actor, const TapGesture& tap)
591 void Button::SetUpTimer( float delay )
593 mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
594 mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
595 mAutoRepeatingTimer.Start();
598 bool Button::AutoRepeatingSlot()
600 bool consumed = false;
603 // Restart the autorepeat timer.
604 SetUpTimer( mNextAutoRepeatingDelay );
606 Toolkit::Button handle( GetOwner() );
608 // Notifies the derived class the button has been pressed.
612 consumed = mReleasedSignal.Emit( handle );
613 consumed |= mClickedSignal.Emit( handle );
614 consumed |= mPressedSignal.Emit( handle );
620 void Button::OnControlStageDisconnection()
622 OnButtonStageDisconnection(); // Notification for derived classes.
626 Button::ButtonState Button::GetState()
631 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
633 Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
639 case Toolkit::Button::PROPERTY_DISABLED:
641 GetImplementation( button ).SetDisabled( value.Get<bool>() );
645 case Toolkit::Button::PROPERTY_AUTO_REPEATING:
647 GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
651 case Toolkit::Button::PROPERTY_INITIAL_AUTO_REPEATING_DELAY:
653 GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
657 case Toolkit::Button::PROPERTY_NEXT_AUTO_REPEATING_DELAY:
659 GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
663 case Toolkit::Button::PROPERTY_TOGGLABLE:
665 GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
669 case Toolkit::Button::PROPERTY_SELECTED:
671 GetImplementation( button ).SetSelected( value.Get< bool >() );
675 case Toolkit::Button::PROPERTY_NORMAL_STATE_ACTOR:
677 GetImplementation( button ).SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
681 case Toolkit::Button::PROPERTY_SELECTED_STATE_ACTOR:
683 GetImplementation( button ).SetSelectedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
687 case Toolkit::Button::PROPERTY_DISABLED_STATE_ACTOR:
689 GetImplementation( button ).SetDisabledImage( Scripting::NewActor( value.Get< Property::Map >() ) );
693 case Toolkit::Button::PROPERTY_LABEL_ACTOR:
695 GetImplementation( button ).SetLabel( Scripting::NewActor( value.Get< Property::Map >() ) );
702 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
704 Property::Value value;
706 Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
710 switch ( propertyIndex )
712 case Toolkit::Button::PROPERTY_DISABLED:
714 value = GetImplementation( button ).mDisabled;
718 case Toolkit::Button::PROPERTY_AUTO_REPEATING:
720 value = GetImplementation( button ).mAutoRepeating;
724 case Toolkit::Button::PROPERTY_INITIAL_AUTO_REPEATING_DELAY:
726 value = GetImplementation( button ).mInitialAutoRepeatingDelay;
730 case Toolkit::Button::PROPERTY_NEXT_AUTO_REPEATING_DELAY:
732 value = GetImplementation( button ).mNextAutoRepeatingDelay;
736 case Toolkit::Button::PROPERTY_TOGGLABLE:
738 value = GetImplementation( button ).mTogglableButton;
742 case Toolkit::Button::PROPERTY_SELECTED:
744 value = GetImplementation( button ).mSelected;
748 case Toolkit::Button::PROPERTY_NORMAL_STATE_ACTOR:
751 Scripting::CreatePropertyMap( GetImplementation( button ).mButtonContent, map );
756 case Toolkit::Button::PROPERTY_SELECTED_STATE_ACTOR:
759 Scripting::CreatePropertyMap( GetImplementation( button ).mSelectedContent, map );
764 case Toolkit::Button::PROPERTY_DISABLED_STATE_ACTOR:
767 Scripting::CreatePropertyMap( GetImplementation( button ).mDisabledContent, map );
772 case Toolkit::Button::PROPERTY_LABEL_ACTOR:
775 Scripting::CreatePropertyMap( GetImplementation( button ).mLabel, map );
785 } // namespace Internal
787 } // namespace Toolkit