2 * Copyright (c) 2020 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 <cstring> // for strcmp
23 #include <dali/devel-api/scripting/enum-helper.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/public-api/events/touch-event.h>
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/public-api/object/type-registry-helper.h>
28 #include <dali/public-api/size-negotiation/relayout-container.h>
29 #include <dali/devel-api/object/property-helper-devel.h>
30 #include <dali/devel-api/scripting/scripting.h>
33 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
34 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
35 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
36 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
37 #include <dali-toolkit/public-api/align-enumerations.h>
38 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
39 #include <dali-toolkit/devel-api/controls/control-devel.h>
40 #include <dali-toolkit/devel-api/controls/buttons/button-devel.h>
41 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
42 #include <dali-toolkit/internal/visuals/text/text-visual.h>
43 #include <dali-toolkit/public-api/visuals/text-visual-properties.h>
44 #include <dali-toolkit/public-api/visuals/visual-properties.h>
46 #if defined(DEBUG_ENABLED)
47 Debug::Filter* gLogButtonFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_BUTTON_CONTROL");
64 // empty handle as we cannot create button (but type registered for clicked signal)
68 // Setup properties, signals and actions using the type-registry.
69 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Button, Toolkit::Control, Create )
71 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabled", BOOLEAN, DISABLED )
72 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "autoRepeating", BOOLEAN, AUTO_REPEATING )
73 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "initialAutoRepeatingDelay", FLOAT, INITIAL_AUTO_REPEATING_DELAY )
74 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "nextAutoRepeatingDelay", FLOAT, NEXT_AUTO_REPEATING_DELAY )
75 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "togglable", BOOLEAN, TOGGLABLE )
76 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selected", BOOLEAN, SELECTED )
77 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "unselectedVisual", MAP, UNSELECTED_VISUAL )
78 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selectedVisual", MAP, SELECTED_VISUAL )
79 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledSelectedVisual", MAP, DISABLED_SELECTED_VISUAL )
80 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledUnselectedVisual", MAP, DISABLED_UNSELECTED_VISUAL )
81 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "unselectedBackgroundVisual", MAP, UNSELECTED_BACKGROUND_VISUAL )
82 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "label", MAP, LABEL )
83 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selectedBackgroundVisual", MAP, SELECTED_BACKGROUND_VISUAL )
84 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledUnselectedBackgroundVisual", MAP, DISABLED_UNSELECTED_BACKGROUND_VISUAL )
85 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledSelectedBackgroundVisual", MAP, DISABLED_SELECTED_BACKGROUND_VISUAL )
86 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, Button, "labelRelativeAlignment", STRING, LABEL_RELATIVE_ALIGNMENT )
87 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, Button, "labelPadding", VECTOR4, LABEL_PADDING )
88 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, Button, "visualPadding", VECTOR4, VISUAL_PADDING )
91 DALI_SIGNAL_REGISTRATION( Toolkit, Button, "pressed", SIGNAL_PRESSED )
92 DALI_SIGNAL_REGISTRATION( Toolkit, Button, "released", SIGNAL_RELEASED )
93 DALI_SIGNAL_REGISTRATION( Toolkit, Button, "clicked", SIGNAL_CLICKED )
94 DALI_SIGNAL_REGISTRATION( Toolkit, Button, "stateChanged", SIGNAL_STATE_CHANGED )
97 DALI_ACTION_REGISTRATION( Toolkit, Button, "buttonClick", ACTION_BUTTON_CLICK )
99 DALI_TYPE_REGISTRATION_END()
101 DALI_ENUM_TO_STRING_TABLE_BEGIN( ALIGNMENT )
102 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::Internal::Button, BEGIN )
103 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::Internal::Button, END )
104 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::Internal::Button, TOP )
105 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::Internal::Button, BOTTOM )
106 DALI_ENUM_TO_STRING_TABLE_END( ALIGNMENT )
108 const Scripting::StringEnum ALIGNMENT_STRING_TABLE[] =
110 { "BEGIN", Button::BEGIN },
111 { "END", Button::END },
112 { "TOP", Button::TOP },
113 { "BOTTOM", Button::BOTTOM },
116 const unsigned int ALIGNMENT_STRING_TABLE_COUNT = sizeof( ALIGNMENT_STRING_TABLE ) / sizeof( ALIGNMENT_STRING_TABLE[0] );
118 const Property::Index VISUAL_INDEX_FOR_STATE[][Button::STATE_COUNT] =
120 { Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::UNSELECTED_VISUAL },
121 { Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::SELECTED_VISUAL },
122 { Toolkit::Button::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::DISABLED_UNSELECTED_VISUAL },
123 { Toolkit::Button::Property::DISABLED_SELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::DISABLED_SELECTED_VISUAL }
127 * Checks if given map contains a text string
129 bool MapContainsTextString( Property::Map& map )
132 Property::Value* value = map.Find( Toolkit::TextVisual::Property::TEXT );
135 std::string textString;
136 value->Get( textString );
137 if ( !textString.empty() )
145 } // unnamed namespace
148 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
149 mAutoRepeatingTimer(),
150 mTextLabelAlignment( END ),
151 mAutoRepeating( false ),
152 mTogglableButton( false ),
153 mTextStringSetFlag( false ),
154 mInitialAutoRepeatingDelay( 0.0f ),
155 mNextAutoRepeatingDelay( 0.0f ),
156 mAnimationTime( 0.0f ),
157 mButtonPressedState( UNPRESSED ),
158 mButtonState( UNSELECTED_STATE ),
159 mPreviousButtonState( mButtonState ),
160 mClickActionPerforming( false )
168 void Button::SetAutoRepeating( bool autoRepeating )
170 mAutoRepeating = autoRepeating;
172 // An autorepeating button can't be a toggle button.
177 SetSelected( false ); // UnSelect before switching off Toggle feature.
179 mTogglableButton = false;
183 void Button::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
185 DALI_ASSERT_DEBUG( initialAutoRepeatingDelay > 0.f );
186 mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
189 void Button::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
191 DALI_ASSERT_DEBUG( nextAutoRepeatingDelay > 0.f );
192 mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
195 void Button::SetTogglableButton( bool togglable )
197 mTogglableButton = togglable;
199 // A toggle button can't be an autorepeating button.
202 mAutoRepeating = false;
206 void Button::SetSelected( bool selected )
208 if( mTogglableButton )
210 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetSelected (%s)\n", (selected?"true":"false") );
212 if ( selected && ( mButtonState != SELECTED_STATE ) )
214 ChangeState( SELECTED_STATE );
216 else if ( !selected && ( mButtonState != UNSELECTED_STATE ) )
218 ChangeState( UNSELECTED_STATE );
223 void Button::SetDisabled( bool disabled )
225 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetDisabled(%s) state(%d)\n", (disabled)?"disabled":"active", mButtonState );
229 if ( mButtonState == SELECTED_STATE )
231 ChangeState( DISABLED_SELECTED_STATE );
233 else if ( mButtonState == UNSELECTED_STATE )
235 ChangeState( DISABLED_UNSELECTED_STATE );
240 if ( mButtonState == DISABLED_SELECTED_STATE )
242 ChangeState( SELECTED_STATE );
244 else if ( mButtonState == DISABLED_UNSELECTED_STATE )
246 ChangeState( UNSELECTED_STATE );
251 bool Button::IsDisabled() const
253 return ( mButtonState == DISABLED_SELECTED_STATE || mButtonState == DISABLED_UNSELECTED_STATE ) ;
256 bool Button::ValidateState( State requestedState )
258 /* Below tables shows allowed state transitions
259 * Match rows in first column to following columns, if true then transition allowed.
260 * eg UNSELECTED_STATE to DISABLED_UNSELECTED_STATE is true so state transition allowed.
262 to| UNSELECTED_STATE | SELECTED_STATE | DISABLED_UNSELECTED_STATE | DISABLED_SELECTED_STATE |*/
264 bool transitionTable[4][4] = { /* UNSELECTED_STATE*/ { false, true, true, false },
265 /* SELECTED_STATE*/ { true, false, false, true },
266 /* DISABLED_UNSELECTED_STATE*/{ true, true, false, false },
267 /* DISABLED_SELECTED_STATE*/ { false, true, false, false }
270 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::ValidateState ReuestedState:%d, CurrentState:%d, result:%s\n",
271 requestedState, mButtonState, (transitionTable[mButtonState][requestedState])?"change-accepted":"change-denied");
273 return transitionTable[mButtonState][requestedState];
276 void Button::ChangeState( State requestedState )
278 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::ChangeState ReuestedState(%d)\n", requestedState );
280 // Validate State before changing
281 if ( !ValidateState( requestedState ))
283 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::ChangeState ReuestedState(%d) not validated\n", requestedState );
287 // If not on stage the button could have still been set to selected so update state
288 mPreviousButtonState = mButtonState; // Store previous state for visual removal (used when animations ended)
289 mButtonState = requestedState; // Update current state
291 if ( Self().GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
293 OnStateChange( mButtonState ); // Notify derived buttons
294 SelectRequiredVisual( VISUAL_INDEX_FOR_STATE[ mButtonState ][ BACKGROUND ] );
295 SelectRequiredVisual( VISUAL_INDEX_FOR_STATE[ mButtonState ][ FOREGROUND ] );
296 // If animation supported then visual removal should be performed after any transition animation has completed.
297 // If Required Visual is not loaded before current visual is removed then a flickering will be evident.
298 // Derived button can override OnButtonVisualRemoval
299 OnButtonVisualRemoval( VISUAL_INDEX_FOR_STATE[ mPreviousButtonState ][ BACKGROUND ] );
300 OnButtonVisualRemoval( VISUAL_INDEX_FOR_STATE[ mPreviousButtonState ][ FOREGROUND ] );
304 Toolkit::Button handle( GetOwner() );
306 mStateChangedSignal.Emit( handle );
309 bool Button::IsSelected() const
311 bool selected = ( mButtonState == SELECTED_STATE ) || ( mButtonState == DISABLED_SELECTED_STATE );
312 return mTogglableButton && selected;
315 void Button::MergeWithExistingLabelProperties( const Property::Map& inMap, Property::Map& outMap )
317 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties with %d properties\n", inMap.Count() );
320 * Properties for the Label visual could be from a style sheet but after being set the "TEXT" property could be set.
321 * Hence would need to create the Text Visual with the complete merged set of properties.
323 * 1) Find Label Visual
324 * 2) Retrieve current properties ( settings )
325 * 3) Merge with new properties ( settings )
326 * 4) Return new merged map
328 Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, Toolkit::Button::Property::LABEL );
331 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties Visual already exists, retrieving existing map\n");
332 visual.CreatePropertyMap( outMap );
333 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties retrieved %d properties\n", outMap.Count() );
336 outMap.Merge( inMap );
338 // Store if a text string has been supplied.
340 mTextStringSetFlag = MapContainsTextString( outMap );
342 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties now has %d properties\n", outMap.Count() );
345 void Button::SetLabelAlignment( Button::Align labelAlignment)
347 mTextLabelAlignment = labelAlignment;
351 Button::Align Button::GetLabelAlignment()
353 return mTextLabelAlignment;
357 * Create Visual for given index from a property map or url.
358 * 1) Check if value passed in is a url and create visual
359 * 2) Create visual from map if step (1) is false
360 * 3) Register visual with control with false for enable flag. Button will later enable visual when needed ( Button::SelectRequiredVisual )
361 * 4) Unregister visual if empty map was provided. This is the method to remove a visual
363 void Button::CreateVisualsForComponent( Property::Index index, const Property::Value& value, const int visualDepth )
365 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent index(%d)\n", index );
366 Toolkit::VisualFactory visualFactory = Toolkit::VisualFactory::Get();
367 Toolkit::Visual::Base buttonVisual;
369 std::string imageUrl;
370 if( value.Get( imageUrl ) )
372 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent Using image URL(%d)\n", index );
373 if ( !imageUrl.empty() )
375 DALI_ASSERT_DEBUG( index != Toolkit::Button::Property::LABEL && "Creating a Image Visual instead of Text Visual " );
376 buttonVisual = visualFactory.CreateVisual( imageUrl, ImageDimensions() );
381 // if its not a string then get a Property::Map from the property if possible.
382 const Property::Map *map = value.GetMap();
383 if( map && !map->Empty() ) // Empty map results in current visual removal.
385 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent Using Map(%d)\n", index );
386 buttonVisual = visualFactory.CreateVisual( *map );
392 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent RegisterVisual index(%d) enabled(%s)\n",
393 index, DevelControl::IsVisualEnabled( *this, index )?"true":"false" );
394 // enable the visual if needed for current state
395 const bool enabled = ( ( index == VISUAL_INDEX_FOR_STATE[ mButtonState ][ BACKGROUND ] )||
396 ( index == VISUAL_INDEX_FOR_STATE[ mButtonState ][ FOREGROUND ] )||
397 ( index == Toolkit::Button::Property::LABEL ) );
398 DevelControl::RegisterVisual( *this, index, buttonVisual, enabled, visualDepth );
402 DevelControl::UnregisterVisual( *this, index );
403 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "CreateVisualsForComponent Visual not created or empty map (clearing visual).(%d)\n", index);
408 bool Button::GetPropertyMapForVisual( Property::Index visualIndex, Property::Map& retreivedMap ) const
410 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetPropertyMapForVisual visual(%d)\n", visualIndex);
411 bool success = false;
412 Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, visualIndex );
415 visual.CreatePropertyMap( retreivedMap );
418 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetPropertyMapForVisual %s\n", success?"Success":"Failure");
422 bool Button::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
426 Dali::BaseHandle handle( object );
428 Toolkit::Button button = Toolkit::Button::DownCast( handle );
430 DALI_ASSERT_DEBUG( button );
432 if( 0 == strcmp( actionName.c_str(), ACTION_BUTTON_CLICK ) )
434 ret = GetImplementation( button ).DoClickAction( attributes );
440 bool Button::DoClickAction( const Property::Map& attributes )
442 // Prevents the button signals from doing a recursive loop by sending an action
443 // and re-emitting the signals.
444 if( !mClickActionPerforming )
446 mClickActionPerforming = true;
448 if ( !mTogglableButton )
450 mButtonPressedState = DEPRESSED;
453 mClickActionPerforming = false;
461 void Button::ButtonDown()
463 if( mTogglableButton )
465 if ( mButtonState != SELECTED_STATE )
468 mButtonPressedState = TOGGLE_DEPRESSED;
472 mButtonPressedState = DEPRESSED;
478 mButtonPressedState = DEPRESSED;
481 SetUpTimer( mInitialAutoRepeatingDelay );
485 // The pressed signal should be emitted regardless of toggle mode.
486 Toolkit::Button handle( GetOwner() );
487 mPressedSignal.Emit( handle );
490 void Button::ButtonUp()
492 bool emitSignalsForPressAndReleaseAction = false;
494 if( DEPRESSED == mButtonPressedState )
496 if( mTogglableButton ) // Button up will change state
498 emitSignalsForPressAndReleaseAction = OnToggleReleased(); // Derived toggle buttons can override this to provide custom behaviour
502 Released(); // Button up will result in unselected state
505 mAutoRepeatingTimer.Reset();
507 emitSignalsForPressAndReleaseAction = true;
510 else if ( TOGGLE_DEPRESSED == mButtonPressedState )
512 emitSignalsForPressAndReleaseAction = true; // toggle released after being pressed, a click
515 if ( emitSignalsForPressAndReleaseAction )
517 // The clicked and released signals should be emitted regardless of toggle mode.
518 Toolkit::Button handle( GetOwner() );
519 mReleasedSignal.Emit( handle );
520 mClickedSignal.Emit( handle );
524 bool Button::OnToggleReleased()
526 SetSelected( !IsSelected() );
527 mButtonPressedState = UNPRESSED;
532 void Button::OnTouchPointLeave()
534 if( DEPRESSED == mButtonPressedState )
536 if( !mTogglableButton )
542 mAutoRepeatingTimer.Reset();
546 mButtonPressedState = UNPRESSED;
548 // The released signal should be emitted regardless of toggle mode.
549 Toolkit::Button handle( GetOwner() );
550 mReleasedSignal.Emit( handle );
554 void Button::OnTouchPointInterrupted()
559 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
561 return mPressedSignal;
564 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
566 return mReleasedSignal;
569 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
571 return mClickedSignal;
574 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
576 return mStateChangedSignal;
579 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
581 Dali::BaseHandle handle( object );
583 bool connected( true );
584 Toolkit::Button button = Toolkit::Button::DownCast( handle );
586 if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
588 button.PressedSignal().Connect( tracker, functor );
590 else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
592 button.ReleasedSignal().Connect( tracker, functor );
594 else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
596 button.ClickedSignal().Connect( tracker, functor );
598 else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
600 button.StateChangedSignal().Connect( tracker, functor );
604 // signalName does not match any signal
611 void Button::OnInitialize()
613 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnInitialize\n" );
617 mTapDetector = TapGestureDetector::New();
618 mTapDetector.Attach( self );
619 mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
621 self.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE, true );
622 self.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true );
624 self.TouchedSignal().Connect( this, &Button::OnTouch );
627 bool Button::OnAccessibilityActivated()
629 return OnKeyboardEnter();
632 bool Button::OnTouch( Actor actor, const TouchEvent& touch )
634 if( !IsDisabled() && (actor == touch.GetHitActor(0)) )
636 if ( 1 == touch.GetPointCount() )
638 switch( touch.GetState( 0 ) )
640 case PointState::DOWN:
650 case PointState::INTERRUPTED:
652 OnTouchPointInterrupted();
655 case PointState::LEAVE:
660 case PointState::MOTION:
661 case PointState::STATIONARY: // FALLTHROUGH
668 else if( 1 < touch.GetPointCount() )
670 OnTouchPointLeave(); // Notification for derived classes.
672 // Sets the button state to the default
673 mButtonPressedState = UNPRESSED;
679 bool Button::OnKeyboardEnter()
681 // When the enter key is pressed, or button is activated, the click action is performed.
682 Property::Map attributes;
683 bool ret = DoClickAction( attributes );
688 void Button::OnSceneDisconnection()
690 if( DEPRESSED == mButtonPressedState )
692 if( !mTogglableButton )
698 mAutoRepeatingTimer.Reset();
703 mButtonPressedState = UNPRESSED;
705 Control::OnSceneDisconnection(); // Visuals will be set off stage
708 void Button::OnSceneConnection( int depth )
710 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnSceneConnection ptr(%p) \n", this );
711 OnButtonVisualRemoval( VISUAL_INDEX_FOR_STATE[ mPreviousButtonState ][ BACKGROUND ] );
712 OnButtonVisualRemoval( VISUAL_INDEX_FOR_STATE[ mPreviousButtonState ][ FOREGROUND ] );
713 SelectRequiredVisual( Toolkit::Button::Property::LABEL );
714 SelectRequiredVisual( VISUAL_INDEX_FOR_STATE[ mButtonState ][ BACKGROUND ] );
715 SelectRequiredVisual( VISUAL_INDEX_FOR_STATE[ mButtonState ][ FOREGROUND ] );
716 Control::OnSceneConnection( depth ); // Enabled visuals will be put on stage
720 Vector3 Button::GetNaturalSize()
722 Vector3 size = Vector3::ZERO;
724 bool horizontalAlignment = mTextLabelAlignment == BEGIN || mTextLabelAlignment == END; // label and visual side by side
726 // Get natural size of foreground ( largest of the possible visuals )
727 Size largestProvidedVisual;
728 Size labelSize = Size::ZERO;
730 bool foreGroundVisualUsed = false;
732 for ( int state = Button::UNSELECTED_STATE; state < Button::STATE_COUNT; state++ )
734 Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, VISUAL_INDEX_FOR_STATE[state][FOREGROUND] );
738 visual.GetNaturalSize( visualSize );
739 largestProvidedVisual.width = std::max(largestProvidedVisual.width, visualSize.width );
740 largestProvidedVisual.height = std::max(largestProvidedVisual.height, visualSize.height );
741 foreGroundVisualUsed = true;
745 if ( !foreGroundVisualUsed ) // If foreground visual not supplied then use the background visual to calculate Natural size
747 for ( int state = Button::UNSELECTED_STATE; state < Button::STATE_COUNT; state++ )
749 Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, VISUAL_INDEX_FOR_STATE[state][BACKGROUND] );
753 visual.GetNaturalSize( visualSize );
754 largestProvidedVisual.width = std::max(largestProvidedVisual.width, visualSize.width );
755 largestProvidedVisual.height = std::max(largestProvidedVisual.height, visualSize.height );
760 // Get horizontal padding total
761 if ( largestProvidedVisual.width > 0 ) // if visual exists
763 size.width += largestProvidedVisual.width + mForegroundPadding.left + mForegroundPadding.right;
765 // Get vertical padding total
766 if ( largestProvidedVisual.height > 0 )
768 size.height += largestProvidedVisual.height + mForegroundPadding.top + mForegroundPadding.bottom;
771 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetNaturalSize visual Size(%f,%f)\n",
772 largestProvidedVisual.width, largestProvidedVisual.height );
774 // Get natural size of label if text has been set
775 if ( mTextStringSetFlag )
777 Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, Toolkit::Button::Property::LABEL );
781 visual.GetNaturalSize( labelSize );
783 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetNaturalSize labelSize(%f,%f) padding(%f,%f)\n",
784 labelSize.width, labelSize.height, mLabelPadding.left + mLabelPadding.right, mLabelPadding.top + mLabelPadding.bottom);
786 labelSize.width += mLabelPadding.left + mLabelPadding.right;
787 labelSize.height += mLabelPadding.top + mLabelPadding.bottom;
789 // Add label size to height or width depending on alignment position
790 if ( horizontalAlignment )
792 size.width += labelSize.width;
793 size.height = std::max(size.height, labelSize.height );
797 size.height += labelSize.height;
798 size.width = std::max(size.width, labelSize.width );
803 if( size.width < 1 && size.height < 1 )
805 // if no image or label then use Control's natural size
806 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetNaturalSize Using control natural size\n");
807 size = Control::GetNaturalSize();
810 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "Button GetNaturalSize (%f,%f)\n", size.width, size.height );
815 void Button::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
817 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnSetResizePolicy\n");
822 * Visuals are sized and positioned in this function.
823 * Whilst the control has it's size negotiated it has to size it's visuals explicitly here.
826 void Button::OnRelayout( const Vector2& size, RelayoutContainer& container )
828 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout targetSize(%f,%f) ptr(%p) state[%d]\n", size.width, size.height, this, mButtonState );
830 Toolkit::Visual::Base currentVisual = DevelControl::GetVisual( *this, VISUAL_INDEX_FOR_STATE[mButtonState][FOREGROUND] );
831 Toolkit::Visual::Base currentBackGroundVisual = DevelControl::GetVisual( *this, VISUAL_INDEX_FOR_STATE[mButtonState][BACKGROUND] );
833 // Sizes and padding set to zero, if not present then values will no effect calculations.
834 Vector2 visualPosition = Vector2::ZERO;
835 Vector2 labelPosition = Vector2::ZERO;
836 Size visualSize = Size::ZERO;
837 Padding foregroundVisualPadding = Padding(0.0f, 0.0f, 0.0f, 0.0f );
838 Padding labelVisualPadding = Padding(0.0f, 0.0f, 0.0f, 0.0f );
840 if ( mTextStringSetFlag )
842 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Label padding setting padding:%f,%f,%f,%f\n", mLabelPadding.y, mLabelPadding.x, mLabelPadding.width,mLabelPadding.height );
843 labelVisualPadding = mLabelPadding;
848 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Foreground Visual setting padding:%f,%f,%f,%f\n", mForegroundPadding.y, mForegroundPadding.x, mForegroundPadding.width,mForegroundPadding.height );
849 currentVisual.GetNaturalSize( visualSize );
850 foregroundVisualPadding = mForegroundPadding;
853 Toolkit::Align::Type visualAnchorPoint = Toolkit::Align::TOP_BEGIN;
855 Vector2 visualAndPaddingSize = Vector2( ( foregroundVisualPadding.x + visualSize.width + foregroundVisualPadding.y ),
856 ( foregroundVisualPadding.width + visualSize.height + foregroundVisualPadding.height ));
858 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout visualAndPaddingSize(%f,%f)\n", visualAndPaddingSize.width, visualAndPaddingSize.height);
860 // Text Visual should take all space available after foreground visual size and all padding is considered.
861 // Remaining Space priority, Foreground padding, foreground visual, Text padding then Text visual.
862 Size remainingSpaceForText = Size::ZERO;
864 switch ( mTextLabelAlignment )
868 visualAnchorPoint = Toolkit::Align::TOP_END;
869 visualPosition.x = foregroundVisualPadding.right;
870 visualPosition.y = foregroundVisualPadding.top;
872 labelPosition.x = labelVisualPadding.x;
873 labelPosition.y = labelVisualPadding.top;
875 remainingSpaceForText.width = size.width - visualAndPaddingSize.width - labelVisualPadding.x - labelVisualPadding.y;
876 remainingSpaceForText.height = size.height - labelVisualPadding.top - labelVisualPadding.bottom;
881 visualAnchorPoint = Toolkit::Align::TOP_BEGIN;
882 visualPosition.x = foregroundVisualPadding.left;
883 visualPosition.y = foregroundVisualPadding.top;
885 labelPosition.x = visualAndPaddingSize.width + labelVisualPadding.x;
886 labelPosition.y = labelVisualPadding.top;
888 remainingSpaceForText.width = size.width - visualAndPaddingSize.width - labelVisualPadding.x - labelVisualPadding.y;
889 remainingSpaceForText.height = size.height - labelVisualPadding.top - labelVisualPadding.bottom;
894 visualAnchorPoint = Toolkit::Align::BOTTOM_END;
895 visualPosition.x = foregroundVisualPadding.left;
896 visualPosition.y = foregroundVisualPadding.bottom;
898 labelPosition.x = labelVisualPadding.left;
899 labelPosition.y = labelVisualPadding.top;
901 remainingSpaceForText.width = size.width - labelVisualPadding.x - labelVisualPadding.y;
902 remainingSpaceForText.height = size.height - visualAndPaddingSize.height - labelVisualPadding.top - labelVisualPadding.bottom;
908 visualAnchorPoint = Toolkit::Align::TOP_END;
909 visualPosition.x = foregroundVisualPadding.left;
910 visualPosition.y = foregroundVisualPadding.top;
912 labelPosition.x = labelVisualPadding.left;
913 labelPosition.y = visualAndPaddingSize.height + labelVisualPadding.top;
915 remainingSpaceForText.width = size.width - labelVisualPadding.x - labelVisualPadding.y;
916 remainingSpaceForText.height = size.height - visualAndPaddingSize.height - labelVisualPadding.top - labelVisualPadding.bottom;
922 if ( currentBackGroundVisual )
924 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Setting visual background size to(%f,%f)\n", size.width, size.height);
926 Property::Map visualTransform;
928 visualTransform.Add( Toolkit::Visual::Transform::Property::SIZE, size )
929 .Add( Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) );
931 currentBackGroundVisual.SetTransformAndSize( visualTransform, size );
936 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Setting visual size to(%f,%f)\n", visualSize.width, visualSize.height);
938 Property::Map visualTransform;
940 visualTransform.Add( Toolkit::Visual::Transform::Property::SIZE, visualSize )
941 .Add( Toolkit::Visual::Transform::Property::OFFSET, visualPosition )
942 .Add( Toolkit::Visual::Transform::Property::OFFSET_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) )
943 .Add( Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) )
944 .Add( Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN )
945 .Add( Toolkit::Visual::Transform::Property::ANCHOR_POINT, visualAnchorPoint );
947 currentVisual.SetTransformAndSize( visualTransform, size );
950 if ( mTextStringSetFlag )
952 Toolkit::Visual::Base textVisual = DevelControl::GetVisual( *this, Toolkit::Button::Property::LABEL ); // No need to search for Label visual if no text set.
956 if ( !currentVisual )
958 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Only Text\n");
959 labelPosition.x = labelVisualPadding.left;
960 labelPosition.y = labelVisualPadding.height;
963 Vector2 preSize = Vector2( static_cast< int >( remainingSpaceForText.x ), static_cast< int >( remainingSpaceForText.y ));
965 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout text Size(%f,%f) text Position(%f,%f) \n", remainingSpaceForText.width, remainingSpaceForText.height, labelPosition.x, labelPosition.y);
967 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout text Size -- (%f,%f) text Position(%f,%f) \n", preSize.width, preSize.height, labelPosition.x, labelPosition.y);
970 Property::Map textVisualTransform;
971 textVisualTransform.Add( Toolkit::Visual::Transform::Property::SIZE, preSize )
972 .Add( Toolkit::Visual::Transform::Property::OFFSET, labelPosition )
973 .Add( Toolkit::Visual::Transform::Property::OFFSET_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) )
974 .Add( Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) )
975 .Add( Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN )
976 .Add( Toolkit::Visual::Transform::Property::ANCHOR_POINT, visualAnchorPoint );
978 textVisual.SetTransformAndSize( textVisualTransform, size );
982 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout selected (%s) \n", IsSelected()?"yes":"no" );
984 DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout << \n");
987 void Button::OnTap(Actor actor, const TapGesture& tap)
989 // Prevents Parent getting a tap event
992 void Button::SetUpTimer( float delay )
994 mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
995 mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
996 mAutoRepeatingTimer.Start();
999 bool Button::AutoRepeatingSlot()
1001 bool consumed = false;
1004 // Restart the autorepeat timer.
1005 SetUpTimer( mNextAutoRepeatingDelay );
1009 Toolkit::Button handle( GetOwner() );
1012 consumed = mReleasedSignal.Emit( handle );
1013 consumed = mClickedSignal.Emit( handle );
1014 consumed |= mPressedSignal.Emit( handle );
1020 void Button::Pressed()
1022 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::Pressed\n" );
1024 if( mButtonState == UNSELECTED_STATE )
1026 ChangeState( SELECTED_STATE );
1027 OnPressed(); // Notifies the derived class the button has been pressed.
1031 void Button::Released()
1033 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::Released\n" );
1035 if( mButtonState == SELECTED_STATE && !mTogglableButton )
1037 ChangeState( UNSELECTED_STATE );
1038 OnReleased(); // // Notifies the derived class the button has been released.
1040 mButtonPressedState = UNPRESSED;
1043 void Button::SelectRequiredVisual( Property::Index visualIndex )
1045 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SelectRequiredVisual index(%d) state(%d)\n", visualIndex, mButtonState );
1046 // only enable visuals that exist
1047 if( DevelControl::GetVisual( *this, visualIndex ) )
1049 DevelControl::EnableVisual( *this, visualIndex, true );
1053 void Button::RemoveVisual( Property::Index visualIndex )
1055 // Use OnButtonVisualRemoval if want button developer to have the option to override removal.
1056 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::RemoveVisual index(%d) state(%d)\n", visualIndex, mButtonState );
1058 Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, visualIndex );
1062 DevelControl::EnableVisual( *this, visualIndex, false );
1066 void Button::OnButtonVisualRemoval( Property::Index visualIndex )
1068 // Derived Buttons can over ride this to prevent default removal.
1069 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnButtonVisualRemoval index(%d)\n", visualIndex );
1070 RemoveVisual( visualIndex );
1073 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
1075 Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1077 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetProperty index[%d]\n", index );
1083 case Toolkit::Button::Property::DISABLED:
1085 GetImplementation( button ).SetDisabled( value.Get< bool >() );
1089 case Toolkit::Button::Property::AUTO_REPEATING:
1091 GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
1095 case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1097 GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
1101 case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1103 GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
1107 case Toolkit::Button::Property::TOGGLABLE:
1109 GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
1113 case Toolkit::Button::Property::SELECTED:
1115 GetImplementation( button ).SetSelected( value.Get< bool >() );
1119 case Toolkit::Button::Property::UNSELECTED_VISUAL:
1120 case Toolkit::Button::Property::SELECTED_VISUAL:
1121 case Toolkit::Button::Property::DISABLED_SELECTED_VISUAL:
1122 case Toolkit::Button::Property::DISABLED_UNSELECTED_VISUAL:
1124 GetImplementation( button ).CreateVisualsForComponent( index, value, DepthIndex::CONTENT );
1128 case Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL:
1129 case Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL:
1130 case Toolkit::Button::Property::DISABLED_SELECTED_BACKGROUND_VISUAL:
1131 case Toolkit::Button::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL:
1133 GetImplementation( button ).CreateVisualsForComponent( index , value, DepthIndex::BACKGROUND);
1137 case Toolkit::Button::Property::LABEL:
1139 Property::Map outTextVisualProperties;
1140 std::string textString;
1142 if ( value.Get( textString ) )
1144 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetProperty Setting TextVisual with string[%s]\n", textString.c_str() );
1146 Property::Map setPropertyMap;
1147 setPropertyMap.Add( Toolkit::Visual::Property::TYPE, Toolkit::Visual::TEXT )
1148 .Add( Toolkit::TextVisual::Property::TEXT, textString );
1150 GetImplementation( button ).MergeWithExistingLabelProperties( setPropertyMap, outTextVisualProperties );
1154 // Get a Property::Map from the property if possible.
1155 const Property::Map* setPropertyMap = value.GetMap();
1156 if( setPropertyMap )
1158 Property::Map indexKeys = TextVisual::ConvertStringKeysToIndexKeys( *setPropertyMap );
1159 GetImplementation( button ).MergeWithExistingLabelProperties( indexKeys, outTextVisualProperties );
1163 if( !outTextVisualProperties.Empty() )
1165 GetImplementation( button ).CreateVisualsForComponent( index, outTextVisualProperties, DepthIndex::CONTENT );
1170 case Toolkit::DevelButton::Property::LABEL_RELATIVE_ALIGNMENT:
1172 Button::Align labelAlignment(END);
1173 Scripting::GetEnumeration< Button::Align> ( value.Get< std::string >().c_str(),
1174 ALIGNMENT_TABLE, ALIGNMENT_TABLE_COUNT,
1177 GetImplementation( button ).SetLabelAlignment( labelAlignment );
1181 case Toolkit::DevelButton::Property::LABEL_PADDING:
1183 Vector4 padding ( value.Get< Vector4 >() );
1184 GetImplementation( button ).SetLabelPadding( Padding( padding.x, padding.y, padding.z, padding.w ) );
1188 case Toolkit::DevelButton::Property::VISUAL_PADDING:
1190 Vector4 padding ( value.Get< Vector4 >() );
1191 GetImplementation( button ).SetForegroundPadding( Padding( padding.x, padding.y, padding.z, padding.w ) );
1198 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
1200 Property::Value value;
1202 Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1206 switch ( propertyIndex )
1208 case Toolkit::Button::Property::DISABLED:
1210 value = GetImplementation( button ).IsDisabled();
1214 case Toolkit::Button::Property::AUTO_REPEATING:
1216 value = GetImplementation( button ).mAutoRepeating;
1220 case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1222 value = GetImplementation( button ).mInitialAutoRepeatingDelay;
1226 case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1228 value = GetImplementation( button ).mNextAutoRepeatingDelay;
1232 case Toolkit::Button::Property::TOGGLABLE:
1234 value = GetImplementation( button ).mTogglableButton;
1238 case Toolkit::Button::Property::SELECTED:
1240 value = GetImplementation( button ).IsSelected();
1244 case Toolkit::Button::Property::UNSELECTED_VISUAL:
1245 case Toolkit::Button::Property::SELECTED_VISUAL:
1246 case Toolkit::Button::Property::DISABLED_SELECTED_VISUAL:
1247 case Toolkit::Button::Property::DISABLED_UNSELECTED_VISUAL:
1248 case Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL:
1249 case Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL:
1250 case Toolkit::Button::Property::DISABLED_SELECTED_BACKGROUND_VISUAL:
1251 case Toolkit::Button::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL:
1252 case Toolkit::Button::Property::LABEL:
1254 Property::Map visualProperty;
1255 if ( GetImplementation( button ).GetPropertyMapForVisual( propertyIndex, visualProperty ) )
1257 value = visualProperty;
1262 case Toolkit::DevelButton::Property::LABEL_RELATIVE_ALIGNMENT:
1264 const char* alignment = Scripting::GetEnumerationName< Button::Align >( GetImplementation( button ).GetLabelAlignment(),
1265 ALIGNMENT_STRING_TABLE,
1266 ALIGNMENT_STRING_TABLE_COUNT );
1269 value = std::string( alignment );
1275 case Toolkit::DevelButton::Property::LABEL_PADDING:
1277 Padding padding = GetImplementation( button ).GetLabelPadding();
1278 value = Vector4( padding.x, padding.y, padding.top, padding.bottom);
1282 case Toolkit::DevelButton::Property::VISUAL_PADDING:
1284 Padding padding = GetImplementation( button ).GetForegroundPadding();
1285 value = Vector4( padding.x, padding.y, padding.top, padding.bottom);
1293 void Button::SetLabelPadding( const Padding& padding)
1295 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetLabelPadding padding(%f,%f,%f,%f)\n", padding.left, padding.right, padding.bottom, padding.top );
1296 mLabelPadding = Padding( padding.left, padding.right, padding.bottom, padding.top );
1300 Padding Button::GetLabelPadding()
1302 return mLabelPadding;
1305 void Button::SetForegroundPadding( const Padding& padding)
1307 DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetForegroundPadding padding(%f,%f,%f,%f)\n", padding.left, padding.right, padding.bottom, padding.top );
1308 mForegroundPadding = Padding( padding.left, padding.right, padding.bottom, padding.top );
1312 Padding Button::GetForegroundPadding()
1314 return mForegroundPadding;
1317 std::string Button::AccessibleImpl::GetNameRaw()
1319 auto slf = Toolkit::Button::DownCast( self );
1321 Property::Map label = slf.GetProperty<Property::Map>( Toolkit::Button::Property::LABEL );
1323 std::string labelText;
1324 label.Find( Toolkit::TextVisual::Property::TEXT )->Get( labelText );
1329 Dali::Accessibility::States Button::AccessibleImpl::CalculateStates()
1331 auto tmp = Control::Impl::AccessibleImpl::CalculateStates();
1332 tmp[Dali::Accessibility::State::SELECTABLE] = true;
1333 auto slf = Toolkit::Button::DownCast( self );
1334 tmp[Dali::Accessibility::State::ENABLED] = !slf.GetProperty<bool>( Toolkit::Button::Property::DISABLED );
1335 tmp[Dali::Accessibility::State::CHECKED] = slf.GetProperty<bool>( Toolkit::Button::Property::SELECTED );
1339 } // namespace Internal
1341 } // namespace Toolkit