X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Fbuttons%2Fbutton-impl.cpp;h=3bebcdefcc22efabc60667b8c118b0be4594c063;hp=faac0dc684b9d471719a393a0a867ba806cb1716;hb=b1e8521ad77e7b4e62b59613b2edef64429130e9;hpb=709f6618b60d366c84e259564c53b6ef0c43b717 diff --git a/dali-toolkit/internal/controls/buttons/button-impl.cpp b/dali-toolkit/internal/controls/buttons/button-impl.cpp index faac0dc..3bebcde 100644 --- a/dali-toolkit/internal/controls/buttons/button-impl.cpp +++ b/dali-toolkit/internal/controls/buttons/button-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,42 +20,32 @@ // EXTERNAL INCLUDES #include // for strcmp -#include -#include +#include +#include +#include #include #include +#include +#include #include // INTERNAL INCLUDES #include #include #include +#include +#include +#include +#include +#include #include +#include +#include +#include - -/** - * Button states and contents - * (3) mSelectedContent - * (2) mUnselectedContent (2) mSelectedBackgroundContent - * (1) mBackgroundContent (1) mBackgroundContent - * < unselected > ----------------------- < selected > - * | OnSelect() | - * | OnDisabled() | OnDisabled() - * | | - * < disabled > < disabled-selected > - * (2) mDisabledContent (2) mDisabledSelectedContent - * (1) mDisabledBackgroundContent (1) mDisabledBackgroundContent - * - * The drawing order of child actors is as follows. - * - * Top mLabel - * | mUnselectedContent / mSelectedContent / mDisabledContent / mDisabledSelectedContent - * | mSelectedBackgroundContent - * Bottom mBackgroundContent / mDisabledBackgroundContent - * - * Some of contents may be missed. - * And 2 images - fade-in image and fade-out image - in the same layer can be shown during the transition animation. Fade-in image should be above fade-out image. - */ +#if defined(DEBUG_ENABLED) + Debug::Filter* gLogButtonFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_BUTTON_CONTROL"); +#endif namespace Dali { @@ -76,23 +66,26 @@ BaseHandle Create() } // Setup properties, signals and actions using the type-registry. -DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Button, Toolkit::Control, Create ); - -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabled", BOOLEAN, DISABLED ) -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "autoRepeating", BOOLEAN, AUTO_REPEATING ) -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "initialAutoRepeatingDelay", FLOAT, INITIAL_AUTO_REPEATING_DELAY ) -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "nextAutoRepeatingDelay", FLOAT, NEXT_AUTO_REPEATING_DELAY ) -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "togglable", BOOLEAN, TOGGLABLE ) -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selected", BOOLEAN, SELECTED ) -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "unselectedStateImage", STRING, UNSELECTED_STATE_IMAGE ) -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selectedStateImage", STRING, SELECTED_STATE_IMAGE ) -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledStateImage", STRING, DISABLED_STATE_IMAGE ) -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "unselectedColor", VECTOR4, UNSELECTED_COLOR ) -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selectedColor", VECTOR4, SELECTED_COLOR ) -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "label", MAP, LABEL ) - -// Deprecated properties: -DALI_PROPERTY_REGISTRATION( Toolkit, Button, "labelText", STRING, LABEL_TEXT ) +DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Button, Toolkit::Control, Create ) + +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabled", BOOLEAN, DISABLED ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "autoRepeating", BOOLEAN, AUTO_REPEATING ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "initialAutoRepeatingDelay", FLOAT, INITIAL_AUTO_REPEATING_DELAY ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "nextAutoRepeatingDelay", FLOAT, NEXT_AUTO_REPEATING_DELAY ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "togglable", BOOLEAN, TOGGLABLE ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selected", BOOLEAN, SELECTED ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "unselectedVisual", MAP, UNSELECTED_VISUAL ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selectedVisual", MAP, SELECTED_VISUAL ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledSelectedVisual", MAP, DISABLED_SELECTED_VISUAL ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledUnselectedVisual", MAP, DISABLED_UNSELECTED_VISUAL ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "unselectedBackgroundVisual", MAP, UNSELECTED_BACKGROUND_VISUAL ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "label", MAP, LABEL ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selectedBackgroundVisual", MAP, SELECTED_BACKGROUND_VISUAL ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledUnselectedBackgroundVisual", MAP, DISABLED_UNSELECTED_BACKGROUND_VISUAL ) +DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledSelectedBackgroundVisual", MAP, DISABLED_SELECTED_BACKGROUND_VISUAL ) +DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, Button, "labelRelativeAlignment", STRING, LABEL_RELATIVE_ALIGNMENT ) +DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, Button, "labelPadding", VECTOR4, LABEL_PADDING ) +DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, Button, "visualPadding", VECTOR4, VISUAL_PADDING ) // Signals: DALI_SIGNAL_REGISTRATION( Toolkit, Button, "pressed", SIGNAL_PRESSED ) @@ -105,647 +98,325 @@ DALI_ACTION_REGISTRATION( Toolkit, Button, "buttonClick", DALI_TYPE_REGISTRATION_END() -const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f ); -const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f ); - -} // unnamed namespace +DALI_ENUM_TO_STRING_TABLE_BEGIN( ALIGNMENT ) +DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::Internal::Button, BEGIN ) +DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::Internal::Button, END ) +DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::Internal::Button, TOP ) +DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::Internal::Button, BOTTOM ) +DALI_ENUM_TO_STRING_TABLE_END( ALIGNMENT ) -Button::Button() -: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ), - mAutoRepeatingTimer(), - mUnselectedColor( Color::WHITE ), // The natural colors of the specified images will be used by default. - mSelectedColor( Color::WHITE ), - mDisabled( false ), - mAutoRepeating( false ), - mTogglableButton( false ), - mSelected( false ), - mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ), - mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ), - mAnimationTime( 0.0f ), - mClickActionPerforming( false ), - mState( ButtonUp ), - mPaintState( UnselectedState ) +const Scripting::StringEnum ALIGNMENT_STRING_TABLE[] = { -} + { "BEGIN", Button::BEGIN }, + { "END", Button::END }, + { "TOP", Button::TOP }, + { "BOTTOM", Button::BOTTOM }, +}; -Button::~Button() -{ -} +const unsigned int ALIGNMENT_STRING_TABLE_COUNT = sizeof( ALIGNMENT_STRING_TABLE ) / sizeof( ALIGNMENT_STRING_TABLE[0] ); -void Button::SetDisabled( bool disabled ) +const Property::Index VISUAL_INDEX_FOR_STATE[][Button::STATE_COUNT] = { - if( disabled == mDisabled ) - { - return; - } - - StopTransitionAnimation(); - - mDisabled = disabled; + { Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::UNSELECTED_VISUAL }, + { Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::SELECTED_VISUAL }, + { Toolkit::Button::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::DISABLED_UNSELECTED_VISUAL }, + { Toolkit::Button::Property::DISABLED_SELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::DISABLED_SELECTED_VISUAL } +}; - // Notifies the derived class the button has been disabled. - OnDisabled(); - - switch( mPaintState ) +/** + * Checks if given map contains a text string + */ +bool MapContainsTextString( Property::Map& map ) +{ + bool result = false; + Property::Value* value = map.Find( Toolkit::TextVisual::Property::TEXT ); + if ( value ) { - case UnselectedState: - { - //Layer Order - //(3) mDisabledContent (Inserted) - //(4) mUnselectedContent - //(2) mDisabledBackgroundContent (Inserted) - //(1) mBackgroundContent - - AddButtonImage( mBackgroundContent ); - TransitionButtonImage( mDisabledBackgroundContent ); - AddButtonImage( mUnselectedContent ); - TransitionButtonImage( mDisabledContent ); - - AddButtonImage( mDecoration[ UNSELECTED_DECORATION ] ); - ReAddLabel(); - - TransitionOut( mDecoration[ SELECTED_DECORATION ] ); - TransitionOut( mUnselectedContent ); - TransitionOut( mSelectedContent ); - TransitionOut( mBackgroundContent ); - TransitionOut( mSelectedBackgroundContent ); - TransitionOut( mDisabledSelectedContent ); - - mPaintState = DisabledUnselectedState; - break; - } - case SelectedState: - { - //Layer Order - //(5) mDisabledSelectedContent (Inserted) - //(4) mSelectedContent - //(3) mDisabledBackgroundContent (Inserted) - //(2) mSelectedBackgroundContent - //(1) mBackgroundContent - - AddButtonImage( mBackgroundContent ); - AddButtonImage( mSelectedBackgroundContent ); - TransitionButtonImage( mDisabledBackgroundContent ); - AddButtonImage( mSelectedContent ); - TransitionButtonImage( mDisabledSelectedContent ); - - AddButtonImage( mDecoration[ SELECTED_DECORATION ] ); - ReAddLabel(); - - TransitionOut( mDecoration[ UNSELECTED_DECORATION ] ); - TransitionOut( mUnselectedContent ); - TransitionOut( mSelectedContent ); - TransitionOut( mBackgroundContent ); - TransitionOut( mSelectedBackgroundContent ); - TransitionOut( mDisabledContent ); - - mPaintState = DisabledSelectedState; - break; - } - case DisabledUnselectedState: - { - //Layer Order - //(3) mUnselectedContent (Inserted) - //(4) mDisabledContent - //(2) mBackgroundContent (Inserted) - //(1) mDisabledBackgroundContent - - AddButtonImage( mDisabledBackgroundContent ); - TransitionButtonImage( mBackgroundContent ); - AddButtonImage( mDisabledContent ); - TransitionButtonImage( mUnselectedContent ); - - AddButtonImage( mDecoration[ UNSELECTED_DECORATION ] ); - ReAddLabel(); - - TransitionOut( mDecoration[ SELECTED_DECORATION ] ); - TransitionOut( mSelectedContent ); - TransitionOut( mSelectedBackgroundContent ); - TransitionOut( mDisabledContent ); - TransitionOut( mDisabledSelectedContent ); - TransitionOut( mDisabledBackgroundContent ); - - mPaintState = UnselectedState; - break; - } - case DisabledSelectedState: + std::string textString; + value->Get( textString ); + if ( !textString.empty() ) { - //Layer Order - //(4) mSelectedContent (Inserted) - //(5) mDisabledSelectedContent - //(3) mSelectedBackgroundContent (Inserted) - //(2) mBackgroundContent (Inserted) - //(1) mDisabledBackgroundContent - - AddButtonImage( mDisabledBackgroundContent ); - TransitionButtonImage( mBackgroundContent ); - TransitionButtonImage( mSelectedBackgroundContent ); - AddButtonImage( mDisabledSelectedContent ); - TransitionButtonImage( mSelectedContent ); - - AddButtonImage( mDecoration[ SELECTED_DECORATION ] ); - ReAddLabel(); - - TransitionOut( mDecoration[ UNSELECTED_DECORATION ] ); - TransitionOut( mUnselectedContent ); - TransitionOut( mDisabledContent ); - TransitionOut( mDisabledSelectedContent ); - TransitionOut( mDisabledBackgroundContent ); - - mPaintState = SelectedState; - break; + result = true; } } + return result; +} + +} // unnamed namespace - StartTransitionAnimation(); +Button::Button() +: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ), + mAutoRepeatingTimer(), + mTextLabelAlignment( END ), + mAutoRepeating( false ), + mTogglableButton( false ), + mTextStringSetFlag( false ), + mInitialAutoRepeatingDelay( 0.0f ), + mNextAutoRepeatingDelay( 0.0f ), + mAnimationTime( 0.0f ), + mButtonPressedState( UNPRESSED ), + mButtonState( UNSELECTED_STATE ), + mPreviousButtonState( mButtonState ), + mClickActionPerforming( false ) +{ } -bool Button::IsDisabled() const +Button::~Button() { - return mDisabled; } void Button::SetAutoRepeating( bool autoRepeating ) { mAutoRepeating = autoRepeating; - // An autorepeating button can't be a togglable button. + // An autorepeating button can't be a toggle button. if( autoRepeating ) { - mTogglableButton = false; - - if( mSelected ) + if( IsSelected() ) { - // Emit a signal is not wanted, only change the appearance. - SetSelected( false, false ); + SetSelected( false ); // UnSelect before switching off Toggle feature. } + mTogglableButton = false; } } -bool Button::IsAutoRepeating() const -{ - return mAutoRepeating; -} - void Button::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay ) { - DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f ); + DALI_ASSERT_DEBUG( initialAutoRepeatingDelay > 0.f ); mInitialAutoRepeatingDelay = initialAutoRepeatingDelay; } -float Button::GetInitialAutoRepeatingDelay() const -{ - return mInitialAutoRepeatingDelay; -} - void Button::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay ) { - DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f ); + DALI_ASSERT_DEBUG( nextAutoRepeatingDelay > 0.f ); mNextAutoRepeatingDelay = nextAutoRepeatingDelay; } -float Button::GetNextAutoRepeatingDelay() const -{ - return mNextAutoRepeatingDelay; -} - void Button::SetTogglableButton( bool togglable ) { mTogglableButton = togglable; - // A togglable button can't be an autorepeating button. + // A toggle button can't be an autorepeating button. if( togglable ) { mAutoRepeating = false; } } -bool Button::IsTogglableButton() const -{ - return mTogglableButton; -} - void Button::SetSelected( bool selected ) { - if( !mDisabled && mTogglableButton && ( selected != mSelected ) ) + if( mTogglableButton ) { - SetSelected( selected, true ); - } -} - -void Button::SetSelected( bool selected, bool emitSignal ) -{ - StopTransitionAnimation(); - - mSelected = selected; + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetSelected (%s)\n", (selected?"true":"false") ); - // Notifies the derived class the button has been selected. - OnSelected(); - - switch( mPaintState ) - { - case UnselectedState: + if ( selected && ( mButtonState != SELECTED_STATE ) ) { - //Layer Order - //(3) mSelectedContent (Inserted) - //(4) mUnselectedContent - //(2) mSelectedBackgroundContent (Inserted) - //(1) mBackgroundContent - - AddButtonImage( mBackgroundContent ); - TransitionButtonImage( mSelectedBackgroundContent ); - AddButtonImage( mUnselectedContent ); - TransitionButtonImage( mSelectedContent ); - - AddButtonImage( mDecoration[ UNSELECTED_DECORATION ] ); - TransitionButtonImage( mDecoration[ SELECTED_DECORATION ] ); - ReAddLabel(); - - TransitionOut( mDecoration[ UNSELECTED_DECORATION ] ); - TransitionOut( mUnselectedContent ); - TransitionOut( mDisabledContent ); - TransitionOut( mDisabledSelectedContent ); - TransitionOut( mDisabledBackgroundContent ); - - mPaintState = SelectedState; - break; - } - case SelectedState: - { - //Layer Order - //(3) mUnselectedContent (Inserted) - //(2) mSelectedContent - //(1) mBackgroundContent - - AddButtonImage( mBackgroundContent ); - AddButtonImage( mSelectedContent ); - TransitionButtonImage( mUnselectedContent ); - - AddButtonImage( mDecoration[ SELECTED_DECORATION ] ); - TransitionButtonImage( mDecoration[ UNSELECTED_DECORATION ] ); - ReAddLabel(); - - TransitionOut( mDecoration[ SELECTED_DECORATION ] ); - TransitionOut( mSelectedContent ); - TransitionOut( mSelectedBackgroundContent ); - TransitionOut( mDisabledContent ); - TransitionOut( mDisabledSelectedContent ); - TransitionOut( mDisabledBackgroundContent ); - - mPaintState = UnselectedState; - break; + ChangeState( SELECTED_STATE ); } - case DisabledUnselectedState: - case DisabledSelectedState: - { - DALI_ASSERT_DEBUG( 0 && "Shouldn't be able to change paint state if the button is disabled." ); - break; - } - } - - StartTransitionAnimation(); - - if( emitSignal ) - { - Toolkit::Button handle( GetOwner() ); - - // Emit signal. - mStateChangedSignal.Emit( handle ); - } - - RelayoutRequest(); -} - -bool Button::IsSelected() const -{ - return mTogglableButton && mSelected; -} - -void Button::SetAnimationTime( float animationTime ) -{ - mAnimationTime = animationTime; -} - -float Button::GetAnimationTime() const -{ - return mAnimationTime; -} - -void Button::SetLabelText( const std::string& label ) -{ - Property::Map labelProperty; - labelProperty.Insert( "text", label ); - ModifyLabel( labelProperty ); -} - -std::string Button::GetLabelText() const -{ - Toolkit::TextLabel label = Dali::Toolkit::TextLabel::DownCast( mLabel ); - if( label ) - { - return label.GetProperty( Dali::Toolkit::TextLabel::Property::TEXT ); - } - return std::string(); -} - -void Button::ModifyLabel( const Property::Map& properties ) -{ - // If we don't have a label yet, create one. - if( !mLabel ) - { - // If we don't have a label, create one and set it up. - // Note: The label text is set from the passed in property map after creation. - mLabel = Toolkit::TextLabel::New(); - mLabel.SetPosition( 0.0f, 0.0f ); - // label should be the top of the button - Self().Add( mLabel ); - } - - // Set any properties specified for the label by iterating through all property key-value pairs. - for( unsigned int i = 0, mapCount = properties.Count(); i < mapCount; ++i ) - { - const StringValuePair& propertyPair( properties.GetPair( i ) ); - - // Convert the property string to a property index. - Property::Index setPropertyIndex = mLabel.GetPropertyIndex( propertyPair.first ); - if( setPropertyIndex != Property::INVALID_INDEX ) + else if ( !selected && ( mButtonState != UNSELECTED_STATE ) ) { - // If the conversion worked, we have a valid property index, - // Set the property to the new value. - mLabel.SetProperty( setPropertyIndex, propertyPair.second ); + ChangeState( UNSELECTED_STATE ); } } - - // Notify derived button classes of the change. - OnLabelSet( false ); - - RelayoutRequest(); -} - -Actor& Button::GetLabelActor() -{ - return mLabel; -} - -void Button::SetDecoration( DecorationState state, Actor actor ) -{ - if( mDecoration[ state ] && mDecoration[ state ].GetParent() ) - { - mDecoration[ state ].Unparent(); - } - - mDecoration[ state ] = actor; - mDecoration[ state ].SetColorMode( USE_OWN_COLOR ); - - ResetImageLayers(); - RelayoutRequest(); } -Actor& Button::GetDecoration( DecorationState state ) +void Button::SetDisabled( bool disabled ) { - return mDecoration[ state ]; -} + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetDisabled(%s) state(%d)\n", (disabled)?"disabled":"active", mButtonState ); -void Button::SetupContent( Actor& actorToModify, Actor newActor ) -{ - if( newActor ) + if ( disabled ) { - StopTransitionAnimation(); - - if( actorToModify && actorToModify.GetParent() ) + if ( mButtonState == SELECTED_STATE ) { - actorToModify.Unparent(); + ChangeState( DISABLED_SELECTED_STATE ); } - - actorToModify = newActor; - - if( actorToModify ) + else if ( mButtonState == UNSELECTED_STATE ) { - actorToModify.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - actorToModify.SetParentOrigin( ParentOrigin::TOP_LEFT ); - actorToModify.SetPosition( 0.f, 0.f ); + ChangeState( DISABLED_UNSELECTED_STATE ); } - - ResetImageLayers(); - } -} - -const Vector4 Button::GetUnselectedColor() const -{ - return mUnselectedColor; -} - -void Button::SetColor( const Vector4& color, Button::PaintState selectedState ) -{ - Actor* contentActor = NULL; // Using a pointer as SetupContent assigns the new Actor to this. - bool imageFileExists = false; - Property::Index visualIndex = Toolkit::Button::Property::SELECTED_STATE_IMAGE; - - if ( selectedState == SelectedState || selectedState == DisabledSelectedState ) - { - mSelectedColor = color; - contentActor = &mSelectedContent; - imageFileExists = !GetSelectedImageFilename().empty(); } else { - mUnselectedColor = color; - contentActor = &mUnselectedContent; - imageFileExists = !GetUnselectedImageFilename().empty(); - visualIndex = Toolkit::Button::Property::UNSELECTED_STATE_IMAGE; - } - - if ( contentActor ) - { - if( imageFileExists ) + if ( mButtonState == DISABLED_SELECTED_STATE ) { - // If there is existing unselected content, change the color on it directly. - contentActor->SetColor( color ); + ChangeState( SELECTED_STATE ); } - else + else if ( mButtonState == DISABLED_UNSELECTED_STATE ) { - // If there is no existing content, create a new actor to use for flat color. - Actor placementActor = Actor::New(); - Toolkit::VisualFactory visualFactory = Toolkit::VisualFactory::Get(); - Toolkit::Visual::Base visual; - - Property::Map map; - map[ Toolkit::Visual::Property::TYPE ] = Toolkit::Visual::COLOR; - map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color; - - visual = visualFactory.CreateVisual( map ); - - RegisterVisual( visualIndex, placementActor, visual ); - - SetupContent( *contentActor, placementActor ); // - contentActor->SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); + ChangeState( UNSELECTED_STATE ); } } } -const Vector4 Button::GetSelectedColor() const +bool Button::IsDisabled() const { - return mSelectedColor; + return ( mButtonState == DISABLED_SELECTED_STATE || mButtonState == DISABLED_UNSELECTED_STATE ) ; } -void Button::SetUnselectedImage( const std::string& filename ) +bool Button::ValidateState( State requestedState ) { - Toolkit::ImageView newContent; - if( !filename.empty() ) - { - newContent = Toolkit::ImageView::New( filename ); - } - else - { - newContent = Toolkit::ImageView::New(); - } - - if( newContent ) - { - SetupContent( mUnselectedContent, newContent ); + /* Below tables shows allowed state transitions + * Match rows in first column to following columns, if true then transition allowed. + * eg UNSELECTED_STATE to DISABLED_UNSELECTED_STATE is true so state transition allowed. + * + to| UNSELECTED_STATE | SELECTED_STATE | DISABLED_UNSELECTED_STATE | DISABLED_SELECTED_STATE |*/ + /* from*/ + bool transitionTable[4][4] = { /* UNSELECTED_STATE*/ { false, true, true, false }, + /* SELECTED_STATE*/ { true, false, false, true }, + /* DISABLED_UNSELECTED_STATE*/{ true, true, false, false }, + /* DISABLED_SELECTED_STATE*/ { false, true, false, false } + }; - mUnselectedContent.SetColor( mUnselectedColor ); + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::ValidateState ReuestedState:%d, CurrentState:%d, result:%s\n", + requestedState, mButtonState, (transitionTable[mButtonState][requestedState])?"change-accepted":"change-denied"); - OnUnselectedImageSet(); - RelayoutRequest(); - } + return transitionTable[mButtonState][requestedState]; } -Actor& Button::GetUnselectedImage() +void Button::ChangeState( State requestedState ) { - return mUnselectedContent; -} + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::ChangeState ReuestedState(%d)\n", requestedState ); -void Button::SetSelectedImage( const std::string& filename ) -{ - Toolkit::ImageView newContent; - if( !filename.empty() ) + // Validate State before changing + if ( !ValidateState( requestedState )) { - newContent = Toolkit::ImageView::New( filename ); - } - else - { - newContent = Toolkit::ImageView::New(); + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::ChangeState ReuestedState(%d) not validated\n", requestedState ); + return; } - if( newContent ) - { - SetupContent( mSelectedContent, newContent ); - - mSelectedContent.SetColor( mSelectedColor ); + // If not on stage the button could have still been set to selected so update state + mPreviousButtonState = mButtonState; // Store previous state for visual removal (used when animations ended) + mButtonState = requestedState; // Update current state - OnSelectedImageSet(); + if ( Self().GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) ) + { + OnStateChange( mButtonState ); // Notify derived buttons + SelectRequiredVisual( VISUAL_INDEX_FOR_STATE[ mButtonState ][ BACKGROUND ] ); + SelectRequiredVisual( VISUAL_INDEX_FOR_STATE[ mButtonState ][ FOREGROUND ] ); + // If animation supported then visual removal should be performed after any transition animation has completed. + // If Required Visual is not loaded before current visual is removed then a flickering will be evident. + // Derived button can override OnButtonVisualRemoval + OnButtonVisualRemoval( VISUAL_INDEX_FOR_STATE[ mPreviousButtonState ][ BACKGROUND ] ); + OnButtonVisualRemoval( VISUAL_INDEX_FOR_STATE[ mPreviousButtonState ][ FOREGROUND ] ); RelayoutRequest(); } -} - -Actor& Button::GetSelectedImage() -{ - return mSelectedContent; -} - -void Button::SetBackgroundImage( const std::string& filename ) -{ - SetupContent( mBackgroundContent, Toolkit::ImageView::New( filename ) ); - OnBackgroundImageSet(); - RelayoutRequest(); + Toolkit::Button handle( GetOwner() ); + // Emit signal. + mStateChangedSignal.Emit( handle ); } -Actor& Button::GetBackgroundImage() +bool Button::IsSelected() const { - return mBackgroundContent; + bool selected = ( mButtonState == SELECTED_STATE ) || ( mButtonState == DISABLED_SELECTED_STATE ); + return mTogglableButton && selected; } -void Button::SetSelectedBackgroundImage( const std::string& filename ) +void Button::MergeWithExistingLabelProperties( const Property::Map& inMap, Property::Map& outMap ) { - SetupContent( mSelectedBackgroundContent, Toolkit::ImageView::New( filename ) ); + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties with %d properties\n", inMap.Count() ); - OnSelectedBackgroundImageSet(); - RelayoutRequest(); -} + /** + * Properties for the Label visual could be from a style sheet but after being set the "TEXT" property could be set. + * Hence would need to create the Text Visual with the complete merged set of properties. + * + * 1) Find Label Visual + * 2) Retrieve current properties ( settings ) + * 3) Merge with new properties ( settings ) + * 4) Return new merged map + */ + Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, Toolkit::Button::Property::LABEL ); + if ( visual ) + { + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties Visual already exists, retrieving existing map\n"); + visual.CreatePropertyMap( outMap ); + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties retrieved %d properties\n", outMap.Count() ); + } -Actor& Button::GetSelectedBackgroundImage() -{ - return mSelectedBackgroundContent; -} + outMap.Merge( inMap ); -void Button::SetDisabledImage( const std::string& filename ) -{ - SetupContent( mDisabledContent, Toolkit::ImageView::New( filename ) ); + // Store if a text string has been supplied. - OnDisabledImageSet(); - RelayoutRequest(); -} + mTextStringSetFlag = MapContainsTextString( outMap ); -Actor& Button::GetDisabledImage() -{ - return mDisabledContent; + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties now has %d properties\n", outMap.Count() ); } -void Button::SetDisabledSelectedImage( const std::string& filename ) +void Button::SetLabelAlignment( Button::Align labelAlignment) { - SetupContent( mDisabledSelectedContent, Toolkit::ImageView::New( filename ) ); - - OnDisabledSelectedImageSet(); + mTextLabelAlignment = labelAlignment; RelayoutRequest(); } -Actor& Button::GetDisabledSelectedImage() -{ - return mDisabledSelectedContent; -} - -void Button::SetDisabledBackgroundImage( const std::string& filename ) +Button::Align Button::GetLabelAlignment() { - SetupContent( mDisabledBackgroundContent, Toolkit::ImageView::New( filename ) ); - - OnDisabledBackgroundImageSet(); - RelayoutRequest(); + return mTextLabelAlignment; } -Actor& Button::GetDisabledBackgroundImage() +/** + * Create Visual for given index from a property map or url. + * 1) Check if value passed in is a url and create visual + * 2) Create visual from map if step (1) is false + * 3) Register visual with control with false for enable flag. Button will later enable visual when needed ( Button::SelectRequiredVisual ) + * 4) Unregister visual if empty map was provided. This is the method to remove a visual + */ +void Button::CreateVisualsForComponent( Property::Index index, const Property::Value& value, const int visualDepth ) { - return mDisabledBackgroundContent; -} + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent index(%d)\n", index ); + Toolkit::VisualFactory visualFactory = Toolkit::VisualFactory::Get(); + Toolkit::Visual::Base buttonVisual; -std::string Button::GetUnselectedImageFilename() const -{ - if( mUnselectedContent ) + std::string imageUrl; + if( value.Get( imageUrl ) ) { - ResourceImage image = ResourceImage::DownCast( mUnselectedContent ); - if( image ) + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent Using image URL(%d)\n", index ); + if ( !imageUrl.empty() ) { - return image.GetUrl(); + DALI_ASSERT_DEBUG( index != Toolkit::Button::Property::LABEL && "Creating a Image Visual instead of Text Visual " ); + buttonVisual = visualFactory.CreateVisual( imageUrl, ImageDimensions() ); } } - return std::string(); -} - -std::string Button::GetSelectedImageFilename() const -{ - if( mSelectedContent ) + else { - ResourceImage image = ResourceImage::DownCast( mSelectedContent ); - if( image ) + // if its not a string then get a Property::Map from the property if possible. + Property::Map *map = value.GetMap(); + if( map && !map->Empty() ) // Empty map results in current visual removal. { - return image.GetUrl(); + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent Using Map(%d)\n", index ); + buttonVisual = visualFactory.CreateVisual( *map ); } } - return std::string(); + + if ( buttonVisual ) + { + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent RegisterVisual index(%d) enabled(%s)\n", + index, DevelControl::IsVisualEnabled( *this, index )?"true":"false" ); + // enable the visual if needed for current state + const bool enabled = ( ( index == VISUAL_INDEX_FOR_STATE[ mButtonState ][ BACKGROUND ] )|| + ( index == VISUAL_INDEX_FOR_STATE[ mButtonState ][ FOREGROUND ] )|| + ( index == Toolkit::Button::Property::LABEL ) ); + DevelControl::RegisterVisual( *this, index, buttonVisual, enabled, visualDepth ); + } + else + { + DevelControl::UnregisterVisual( *this, index ); + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "CreateVisualsForComponent Visual not created or empty map (clearing visual).(%d)\n", index); + } + RelayoutRequest(); } -std::string Button::GetDisabledImageFilename() const +bool Button::GetPropertyMapForVisual( Property::Index visualIndex, Property::Map& retreivedMap ) const { - if( mDisabledContent ) + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetPropertyMapForVisual visual(%d)\n", visualIndex); + bool success = false; + Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, visualIndex ); + if ( visual ) { - ResourceImage image = ResourceImage::DownCast( mDisabledContent ); - if( image ) - { - return image.GetUrl(); - } + visual.CreatePropertyMap( retreivedMap ); + success = true; } - return std::string(); + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetPropertyMapForVisual %s\n", success?"Success":"Failure"); + return success; } bool Button::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes ) @@ -756,7 +427,7 @@ bool Button::DoAction( BaseObject* object, const std::string& actionName, const Toolkit::Button button = Toolkit::Button::DownCast( handle ); - DALI_ASSERT_ALWAYS( button ); + DALI_ASSERT_DEBUG( button ); if( 0 == strcmp( actionName.c_str(), ACTION_BUTTON_CLICK ) ) { @@ -773,9 +444,12 @@ bool Button::DoClickAction( const Property::Map& attributes ) if( !mClickActionPerforming ) { mClickActionPerforming = true; - OnButtonDown(); - mState = ButtonDown; - OnButtonUp(); + ButtonDown(); + if ( !mTogglableButton ) + { + mButtonPressedState = DEPRESSED; + } + ButtonUp(); mClickActionPerforming = false; return true; @@ -784,15 +458,27 @@ bool Button::DoClickAction( const Property::Map& attributes ) return false; } -void Button::OnButtonDown() +void Button::ButtonDown() { - if( !mTogglableButton ) + if( mTogglableButton ) + { + if ( mButtonState != SELECTED_STATE ) + { + SetSelected( true ); + mButtonPressedState = TOGGLE_DEPRESSED; + } + else + { + mButtonPressedState = DEPRESSED; + } + } + else { Pressed(); - + mButtonPressedState = DEPRESSED; if( mAutoRepeating ) { - SetUpTimer( mInitialAutoRepeatingDelay ); + SetUpTimer( mInitialAutoRepeatingDelay ); } } @@ -801,24 +487,33 @@ void Button::OnButtonDown() mPressedSignal.Emit( handle ); } -void Button::OnButtonUp() +void Button::ButtonUp() { - if( ButtonDown == mState ) + bool emitSignalsForPressAndReleaseAction = false; + + if( DEPRESSED == mButtonPressedState ) { - if( mTogglableButton ) + if( mTogglableButton ) // Button up will change state { - SetSelected( !mSelected ); + emitSignalsForPressAndReleaseAction = OnToggleReleased(); // Derived toggle buttons can override this to provide custom behaviour } else { - Released(); - + Released(); // Button up will result in unselected state if( mAutoRepeating ) { mAutoRepeatingTimer.Reset(); } + emitSignalsForPressAndReleaseAction = true; } + } + else if ( TOGGLE_DEPRESSED == mButtonPressedState ) + { + emitSignalsForPressAndReleaseAction = true; // toggle released after being pressed, a click + } + if ( emitSignalsForPressAndReleaseAction ) + { // The clicked and released signals should be emitted regardless of toggle mode. Toolkit::Button handle( GetOwner() ); mReleasedSignal.Emit( handle ); @@ -826,9 +521,17 @@ void Button::OnButtonUp() } } +bool Button::OnToggleReleased() +{ + SetSelected( !IsSelected() ); + mButtonPressedState = UNPRESSED; + return true; +} + + void Button::OnTouchPointLeave() { - if( ButtonDown == mState ) + if( DEPRESSED == mButtonPressedState ) { if( !mTogglableButton ) { @@ -840,6 +543,8 @@ void Button::OnTouchPointLeave() } } + mButtonPressedState = UNPRESSED; + // The released signal should be emitted regardless of toggle mode. Toolkit::Button handle( GetOwner() ); mReleasedSignal.Emit( handle ); @@ -905,13 +610,15 @@ bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tr void Button::OnInitialize() { + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnInitialize\n" ); + Actor self = Self(); mTapDetector = TapGestureDetector::New(); mTapDetector.Attach( self ); mTapDetector.DetectedSignal().Connect(this, &Button::OnTap); - self.SetKeyboardFocusable( true ); + self.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE, true ); self.TouchSignal().Connect( this, &Button::OnTouch ); } @@ -921,424 +628,453 @@ bool Button::OnAccessibilityActivated() return OnKeyboardEnter(); } -bool Button::OnKeyboardEnter() -{ - // When the enter key is pressed, or button is activated, the click action is performed. - Property::Map attributes; - bool ret = DoClickAction( attributes ); - - return ret; -} - -void Button::OnStageDisconnection() +bool Button::OnTouch( Actor actor, const TouchEvent& touch ) { - if( ButtonDown == mState ) + if( !IsDisabled() && (actor == touch.GetHitActor(0)) ) { - if( !mTogglableButton ) + if ( 1 == touch.GetPointCount() ) { - Released(); - - if( mAutoRepeating ) + switch( touch.GetState( 0 ) ) { - mAutoRepeatingTimer.Reset(); - } - } - } - - mState = ButtonUp; - - Control::OnStageDisconnection(); + case PointState::DOWN: + { + ButtonDown(); + break; + } + case PointState::UP: + { + ButtonUp(); + break; + } + case PointState::INTERRUPTED: + { + OnTouchPointInterrupted(); + break; + } + case PointState::LEAVE: + { + OnTouchPointLeave(); + break; + } + case PointState::MOTION: + case PointState::STATIONARY: // FALLTHROUGH + { + // Nothing to do + break; + } + } + } + else if( 1 < touch.GetPointCount() ) + { + OnTouchPointLeave(); // Notification for derived classes. + + // Sets the button state to the default + mButtonPressedState = UNPRESSED; + } + } + return false; } -bool Button::OnTouch( Actor actor, const TouchData& touch ) +bool Button::OnKeyboardEnter() { - // Only events are processed when the button is not disabled and the touch event has only - // one touch point. - if( ( !mDisabled ) && ( 1 == touch.GetPointCount() ) ) - { - switch( touch.GetState( 0 ) ) - { - case PointState::DOWN: - { - OnButtonDown(); // Notification for derived classes. - - // Sets the button state to ButtonDown. - mState = ButtonDown; - break; - } - case PointState::UP: - { - OnButtonUp(); // Notification for derived classes. + // When the enter key is pressed, or button is activated, the click action is performed. + Property::Map attributes; + bool ret = DoClickAction( attributes ); - // Sets the button state to ButtonUp. - mState = ButtonUp; - break; - } - case PointState::INTERRUPTED: - { - OnTouchPointInterrupted(); // Notification for derived classes. + return ret; +} - // Sets the button state to the default (ButtonUp). - mState = ButtonUp; - break; - } - case PointState::LEAVE: - { - OnTouchPointLeave(); // Notification for derived classes. +void Button::OnSceneDisconnection() +{ + if( DEPRESSED == mButtonPressedState ) + { + if( !mTogglableButton ) + { + Released(); - // Sets the button state to the default (ButtonUp). - mState = ButtonUp; - break; - } - case PointState::MOTION: - case PointState::STATIONARY: // FALLTHROUGH + if( mAutoRepeating ) { - // Nothing to do - break; + mAutoRepeatingTimer.Reset(); } } } - else if( 1 < touch.GetPointCount() ) - { - OnTouchPointLeave(); // Notification for derived classes. - // Sets the button state to the default (ButtonUp). - mState = ButtonUp; - } + mButtonPressedState = UNPRESSED; - return false; + Control::OnSceneDisconnection(); // Visuals will be set off stage } -void Button::OnTap(Actor actor, const TapGesture& tap) +void Button::OnSceneConnection( int depth ) { - // Do nothing. + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnSceneConnection ptr(%p) \n", this ); + OnButtonVisualRemoval( VISUAL_INDEX_FOR_STATE[ mPreviousButtonState ][ BACKGROUND ] ); + OnButtonVisualRemoval( VISUAL_INDEX_FOR_STATE[ mPreviousButtonState ][ FOREGROUND ] ); + SelectRequiredVisual( Toolkit::Button::Property::LABEL ); + SelectRequiredVisual( VISUAL_INDEX_FOR_STATE[ mButtonState ][ BACKGROUND ] ); + SelectRequiredVisual( VISUAL_INDEX_FOR_STATE[ mButtonState ][ FOREGROUND ] ); + Control::OnSceneConnection( depth ); // Enabled visuals will be put on stage + RelayoutRequest(); } -void Button::SetUpTimer( float delay ) +Vector3 Button::GetNaturalSize() { - mAutoRepeatingTimer = Dali::Timer::New( static_cast( 1000.f * delay ) ); - mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot ); - mAutoRepeatingTimer.Start(); -} + Vector3 size = Vector3::ZERO; -bool Button::AutoRepeatingSlot() -{ - bool consumed = false; - if( !mDisabled ) - { - // Restart the autorepeat timer. - SetUpTimer( mNextAutoRepeatingDelay ); + bool horizontalAlignment = mTextLabelAlignment == BEGIN || mTextLabelAlignment == END; // label and visual side by side - Pressed(); + // Get natural size of foreground ( largest of the possible visuals ) + Size largestProvidedVisual; + Size labelSize = Size::ZERO; - Toolkit::Button handle( GetOwner() ); + bool foreGroundVisualUsed = false; - //Emit signal. - consumed = mReleasedSignal.Emit( handle ); - consumed |= mClickedSignal.Emit( handle ); - consumed |= mPressedSignal.Emit( handle ); - } + for ( int state = Button::UNSELECTED_STATE; state < Button::STATE_COUNT; state++ ) + { + Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, VISUAL_INDEX_FOR_STATE[state][FOREGROUND] ); + Size visualSize; + if ( visual ) + { + visual.GetNaturalSize( visualSize ); + largestProvidedVisual.width = std::max(largestProvidedVisual.width, visualSize.width ); + largestProvidedVisual.height = std::max(largestProvidedVisual.height, visualSize.height ); + foreGroundVisualUsed = true; + } + } - return consumed; -} + if ( !foreGroundVisualUsed ) // If foreground visual not supplied then use the background visual to calculate Natural size + { + for ( int state = Button::UNSELECTED_STATE; state < Button::STATE_COUNT; state++ ) + { + Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, VISUAL_INDEX_FOR_STATE[state][BACKGROUND] ); + Size visualSize; + if ( visual ) + { + visual.GetNaturalSize( visualSize ); + largestProvidedVisual.width = std::max(largestProvidedVisual.width, visualSize.width ); + largestProvidedVisual.height = std::max(largestProvidedVisual.height, visualSize.height ); + } + } + } -void Button::Pressed() -{ - if( mPaintState == UnselectedState ) + // Get horizontal padding total + if ( largestProvidedVisual.width > 0 ) // if visual exists { - StopTransitionAnimation(); + size.width += largestProvidedVisual.width + mForegroundPadding.left + mForegroundPadding.right; + } + // Get vertical padding total + if ( largestProvidedVisual.height > 0 ) + { + size.height += largestProvidedVisual.height + mForegroundPadding.top + mForegroundPadding.bottom; + } - // Notifies the derived class the button has been pressed. - OnPressed(); + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetNaturalSize visual Size(%f,%f)\n", + largestProvidedVisual.width, largestProvidedVisual.height ); - //Layer Order - //(4) mSelectedContent (Inserted) - //(3) mUnselectedContent - //(2) mSelectedBackgroundContent (Inserted) - //(1) mBackgroundContent + // Get natural size of label if text has been set + if ( mTextStringSetFlag ) + { + Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, Toolkit::Button::Property::LABEL ); - AddButtonImage( mBackgroundContent ); - TransitionButtonImage( mSelectedBackgroundContent ); - AddButtonImage( mUnselectedContent ); - TransitionButtonImage( mSelectedContent ); + if ( visual ) + { + visual.GetNaturalSize( labelSize ); - AddButtonImage( mDecoration[ UNSELECTED_DECORATION ] ); - TransitionButtonImage( mDecoration[ SELECTED_DECORATION ] ); - ReAddLabel(); + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetNaturalSize labelSize(%f,%f) padding(%f,%f)\n", + labelSize.width, labelSize.height, mLabelPadding.left + mLabelPadding.right, mLabelPadding.top + mLabelPadding.bottom); - TransitionOut( mDecoration[ UNSELECTED_DECORATION ] ); - TransitionOut( mUnselectedContent ); - TransitionOut( mDisabledContent ); - TransitionOut( mDisabledSelectedContent ); - TransitionOut( mDisabledBackgroundContent ); + labelSize.width += mLabelPadding.left + mLabelPadding.right; + labelSize.height += mLabelPadding.top + mLabelPadding.bottom; - mPaintState = SelectedState; + // Add label size to height or width depending on alignment position + if ( horizontalAlignment ) + { + size.width += labelSize.width; + size.height = std::max(size.height, labelSize.height ); + } + else + { + size.height += labelSize.height; + size.width = std::max(size.width, labelSize.width ); + } + } + } - StartTransitionAnimation(); + if( size.width < 1 && size.height < 1 ) + { + // if no image or label then use Control's natural size + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetNaturalSize Using control natural size\n"); + size = Control::GetNaturalSize(); } + + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "Button GetNaturalSize (%f,%f)\n", size.width, size.height ); + + return size; } -void Button::Released() +void Button::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) { - if( mPaintState == SelectedState ) - { - StopTransitionAnimation(); - - // Notifies the derived class the button has been released. - OnReleased(); + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnSetResizePolicy\n"); + RelayoutRequest(); +} - //Layer Order - //(3) mUnselectedContent (Inserted) - //(2) mSelectedContent - //(1) mBackgroundContent +/** + * Visuals are sized and positioned in this function. + * Whilst the control has it's size negotiated it has to size it's visuals explicitly here. + */ - AddButtonImage( mBackgroundContent ); - AddButtonImage( mSelectedContent ); - TransitionButtonImage( mUnselectedContent ); +void Button::OnRelayout( const Vector2& size, RelayoutContainer& container ) +{ + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout targetSize(%f,%f) ptr(%p) state[%d]\n", size.width, size.height, this, mButtonState ); - AddButtonImage( mDecoration[ SELECTED_DECORATION ] ); - TransitionButtonImage( mDecoration[ UNSELECTED_DECORATION ] ); - ReAddLabel(); + Toolkit::Visual::Base currentVisual = DevelControl::GetVisual( *this, VISUAL_INDEX_FOR_STATE[mButtonState][FOREGROUND] ); + Toolkit::Visual::Base currentBackGroundVisual = DevelControl::GetVisual( *this, VISUAL_INDEX_FOR_STATE[mButtonState][BACKGROUND] ); - TransitionOut( mDecoration[ SELECTED_DECORATION ] ); - TransitionOut( mSelectedContent ); - TransitionOut( mSelectedBackgroundContent ); - TransitionOut( mDisabledContent ); - TransitionOut( mDisabledSelectedContent ); - TransitionOut( mDisabledBackgroundContent ); + // Sizes and padding set to zero, if not present then values will no effect calculations. + Vector2 visualPosition = Vector2::ZERO; + Vector2 labelPosition = Vector2::ZERO; + Size visualSize = Size::ZERO; + Padding foregroundVisualPadding = Padding(0.0f, 0.0f, 0.0f, 0.0f ); + Padding labelVisualPadding = Padding(0.0f, 0.0f, 0.0f, 0.0f ); - mPaintState = UnselectedState; + if ( mTextStringSetFlag ) + { + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Label padding setting padding:%f,%f,%f,%f\n", mLabelPadding.y, mLabelPadding.x, mLabelPadding.width,mLabelPadding.height ); + labelVisualPadding = mLabelPadding; + } - StartTransitionAnimation(); + if ( currentVisual ) + { + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Foreground Visual setting padding:%f,%f,%f,%f\n", mForegroundPadding.y, mForegroundPadding.x, mForegroundPadding.width,mForegroundPadding.height ); + currentVisual.GetNaturalSize( visualSize ); + foregroundVisualPadding = mForegroundPadding; } -} -Button::ButtonState Button::GetState() -{ - return mState; -} + Toolkit::Align::Type visualAnchorPoint = Toolkit::Align::TOP_BEGIN; -Button::PaintState Button::GetPaintState() -{ - return mPaintState; -} + Vector2 visualAndPaddingSize = Vector2( ( foregroundVisualPadding.x + visualSize.width + foregroundVisualPadding.y ), + ( foregroundVisualPadding.width + visualSize.height + foregroundVisualPadding.height )); -void Button::PrepareAddButtonImage( Actor& actor ) -{ - if( actor ) - { - Self().Add( actor ); - PrepareForTranstionOut( actor ); - } -} + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout visualAndPaddingSize(%f,%f)\n", visualAndPaddingSize.width, visualAndPaddingSize.height); -void Button::TransitionButtonImage( Actor& actor ) -{ - if( actor ) + // Text Visual should take all space available after foreground visual size and all padding is considered. + // Remaining Space priority, Foreground padding, foreground visual, Text padding then Text visual. + Size remainingSpaceForText = Size::ZERO; + + switch ( mTextLabelAlignment ) { - if( !actor.GetParent() ) + case BEGIN : { - Self().Add( actor ); + visualAnchorPoint = Toolkit::Align::TOP_END; + visualPosition.x = foregroundVisualPadding.right; + visualPosition.y = foregroundVisualPadding.top; + + labelPosition.x = labelVisualPadding.x; + labelPosition.y = labelVisualPadding.top; + + remainingSpaceForText.width = size.width - visualAndPaddingSize.width - labelVisualPadding.x - labelVisualPadding.y; + remainingSpaceForText.height = size.height - labelVisualPadding.top - labelVisualPadding.bottom; + break; + } + case END : + { + visualAnchorPoint = Toolkit::Align::TOP_BEGIN; + visualPosition.x = foregroundVisualPadding.left; + visualPosition.y = foregroundVisualPadding.top; + + labelPosition.x = visualAndPaddingSize.width + labelVisualPadding.x; + labelPosition.y = labelVisualPadding.top; + + remainingSpaceForText.width = size.width - visualAndPaddingSize.width - labelVisualPadding.x - labelVisualPadding.y; + remainingSpaceForText.height = size.height - labelVisualPadding.top - labelVisualPadding.bottom; + break; + } + case TOP : + { + visualAnchorPoint = Toolkit::Align::BOTTOM_END; + visualPosition.x = foregroundVisualPadding.left; + visualPosition.y = foregroundVisualPadding.bottom; + + labelPosition.x = labelVisualPadding.left; + labelPosition.y = labelVisualPadding.top; + + remainingSpaceForText.width = size.width - labelVisualPadding.x - labelVisualPadding.y; + remainingSpaceForText.height = size.height - visualAndPaddingSize.height - labelVisualPadding.top - labelVisualPadding.bottom; + + break; } + case BOTTOM : + { + visualAnchorPoint = Toolkit::Align::TOP_END; + visualPosition.x = foregroundVisualPadding.left; + visualPosition.y = foregroundVisualPadding.top; + + labelPosition.x = labelVisualPadding.left; + labelPosition.y = visualAndPaddingSize.height + labelVisualPadding.top; - OnTransitionIn( actor ); + remainingSpaceForText.width = size.width - labelVisualPadding.x - labelVisualPadding.y; + remainingSpaceForText.height = size.height - visualAndPaddingSize.height - labelVisualPadding.top - labelVisualPadding.bottom; + + break; + } } -} -void Button::AddButtonImage( Actor& actor ) -{ - if( actor ) + if ( currentBackGroundVisual ) { - Self().Add( actor ); + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Setting visual background size to(%f,%f)\n", size.width, size.height); + + Property::Map visualTransform; + + visualTransform.Add( Toolkit::Visual::Transform::Property::SIZE, size ) + .Add( Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) ); + + currentBackGroundVisual.SetTransformAndSize( visualTransform, size ); } -} -void Button::ReAddLabel() -{ - if( mLabel ) + if ( currentVisual ) { - mLabel.Unparent(); - Self().Add( mLabel ); + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Setting visual size to(%f,%f)\n", visualSize.width, visualSize.height); + + Property::Map visualTransform; + + visualTransform.Add( Toolkit::Visual::Transform::Property::SIZE, visualSize ) + .Add( Toolkit::Visual::Transform::Property::OFFSET, visualPosition ) + .Add( Toolkit::Visual::Transform::Property::OFFSET_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) ) + .Add( Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) ) + .Add( Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN ) + .Add( Toolkit::Visual::Transform::Property::ANCHOR_POINT, visualAnchorPoint ); + + currentVisual.SetTransformAndSize( visualTransform, size ); } -} -void Button::RemoveButtonImage( Actor& actor ) -{ - if( actor ) + if ( mTextStringSetFlag ) { - if( actor.GetParent() ) + Toolkit::Visual::Base textVisual = DevelControl::GetVisual( *this, Toolkit::Button::Property::LABEL ); // No need to search for Label visual if no text set. + + if ( textVisual ) { - Self().Remove( actor ); - } - PrepareForTranstionIn( actor ); - } -} + if ( !currentVisual ) + { + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Only Text\n"); + labelPosition.x = labelVisualPadding.left; + labelPosition.y = labelVisualPadding.height; + } -unsigned int Button::FindChildIndex( Actor& actor ) -{ - Actor self = Self(); - unsigned int childrenNum = self.GetChildCount(); + Vector2 preSize = Vector2( static_cast< int >( remainingSpaceForText.x ), static_cast< int >( remainingSpaceForText.y )); - for( unsigned int i = 0; i < childrenNum; i++ ) - { - Actor child = self.GetChildAt( i ); - if( child == actor ) - { - return i; + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout text Size(%f,%f) text Position(%f,%f) \n", remainingSpaceForText.width, remainingSpaceForText.height, labelPosition.x, labelPosition.y); + + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout text Size -- (%f,%f) text Position(%f,%f) \n", preSize.width, preSize.height, labelPosition.x, labelPosition.y); + + + Property::Map textVisualTransform; + textVisualTransform.Add( Toolkit::Visual::Transform::Property::SIZE, preSize ) + .Add( Toolkit::Visual::Transform::Property::OFFSET, labelPosition ) + .Add( Toolkit::Visual::Transform::Property::OFFSET_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) ) + .Add( Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) ) + .Add( Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN ) + .Add( Toolkit::Visual::Transform::Property::ANCHOR_POINT, visualAnchorPoint ); + + textVisual.SetTransformAndSize( textVisualTransform, size ); } } - return childrenNum; + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout selected (%s) \n", IsSelected()?"yes":"no" ); + + DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout << \n"); } -void Button::TransitionOut( Actor actor ) +void Button::OnTap(Actor actor, const TapGesture& tap) { - OnTransitionOut( actor ); + // Prevents Parent getting a tap event } -void Button::ResetImageLayers() +void Button::SetUpTimer( float delay ) { - // Ensure that all layers are in the correct order and state according to the paint state + mAutoRepeatingTimer = Dali::Timer::New( static_cast( 1000.f * delay ) ); + mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot ); + mAutoRepeatingTimer.Start(); +} - switch( mPaintState ) +bool Button::AutoRepeatingSlot() +{ + bool consumed = false; + if( !IsDisabled() ) { - case UnselectedState: - { - //Layer Order - //(2) mUnselectedContent - //(1) mBackgroundContent - - RemoveButtonImage( mDecoration[ SELECTED_DECORATION ] ); - RemoveButtonImage( mSelectedContent ); - RemoveButtonImage( mSelectedBackgroundContent ); - RemoveButtonImage( mDisabledContent ); - RemoveButtonImage( mDisabledSelectedContent ); - RemoveButtonImage( mDisabledBackgroundContent ); - - PrepareAddButtonImage( mBackgroundContent ); - PrepareAddButtonImage( mUnselectedContent ); - - PrepareAddButtonImage( mDecoration[ UNSELECTED_DECORATION ] ); - ReAddLabel(); - break; - } - case SelectedState: - { - //Layer Order - //(3) mSelectedContent - //(2) mSelectedBackgroundContent - //(1) mBackgroundContent - - RemoveButtonImage( mDecoration[ UNSELECTED_DECORATION ] ); - RemoveButtonImage( mUnselectedContent ); - RemoveButtonImage( mDisabledContent ); - RemoveButtonImage( mDisabledSelectedContent ); - RemoveButtonImage( mDisabledBackgroundContent ); - - PrepareAddButtonImage( mBackgroundContent ); - PrepareAddButtonImage( mSelectedBackgroundContent ); - PrepareAddButtonImage( mSelectedContent ); - - PrepareAddButtonImage( mDecoration[ SELECTED_DECORATION ] ); - ReAddLabel(); - break; - } - case DisabledUnselectedState: - { - //Layer Order - //(2) mDisabledContent - //(1) mDisabledBackgroundContent - - RemoveButtonImage( mDecoration[ UNSELECTED_DECORATION ] ); - RemoveButtonImage( mUnselectedContent ); - RemoveButtonImage( mBackgroundContent ); - RemoveButtonImage( mDecoration[ SELECTED_DECORATION ] ); - RemoveButtonImage( mSelectedContent ); - RemoveButtonImage( mDisabledSelectedContent ); - RemoveButtonImage( mSelectedBackgroundContent ); - - PrepareAddButtonImage( mDisabledBackgroundContent ? mDisabledBackgroundContent : mBackgroundContent ); - PrepareAddButtonImage( mDisabledContent ? mDisabledContent : mUnselectedContent ); - - PrepareAddButtonImage( mDecoration[ UNSELECTED_DECORATION ] ); - ReAddLabel(); - break; - } - case DisabledSelectedState: - { - //Layer Order - // (2) mDisabledSelectedContent - // (1) mDisabledBackgroundContent - - RemoveButtonImage( mDecoration[ UNSELECTED_DECORATION ] ); - RemoveButtonImage( mUnselectedContent ); - RemoveButtonImage( mDecoration[ SELECTED_DECORATION ] ); - RemoveButtonImage( mSelectedContent ); - RemoveButtonImage( mBackgroundContent ); - RemoveButtonImage( mSelectedBackgroundContent ); - RemoveButtonImage( mDisabledContent ); - - if( mDisabledBackgroundContent ) - { - PrepareAddButtonImage( mDisabledBackgroundContent ); - } - else - { - PrepareAddButtonImage( mBackgroundContent ); - PrepareAddButtonImage( mSelectedBackgroundContent ); - } + // Restart the autorepeat timer. + SetUpTimer( mNextAutoRepeatingDelay ); - PrepareAddButtonImage( mDisabledSelectedContent ? mDisabledSelectedContent : mSelectedContent ); + Pressed(); - PrepareAddButtonImage( mDecoration[ SELECTED_DECORATION ] ); - ReAddLabel(); - break; - } - } + Toolkit::Button handle( GetOwner() ); + + //Emit signal. + consumed = mReleasedSignal.Emit( handle ); + consumed = mClickedSignal.Emit( handle ); + consumed |= mPressedSignal.Emit( handle ); + } + + return consumed; } -void Button::StartTransitionAnimation() +void Button::Pressed() { - if( mTransitionAnimation ) + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::Pressed\n" ); + + if( mButtonState == UNSELECTED_STATE ) { - mTransitionAnimation.Play(); + ChangeState( SELECTED_STATE ); + OnPressed(); // Notifies the derived class the button has been pressed. } - else +} + +void Button::Released() +{ + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::Released\n" ); + + if( mButtonState == SELECTED_STATE && !mTogglableButton ) { - ResetImageLayers(); + ChangeState( UNSELECTED_STATE ); + OnReleased(); // // Notifies the derived class the button has been released. } + mButtonPressedState = UNPRESSED; } -void Button::StopTransitionAnimation() +void Button::SelectRequiredVisual( Property::Index visualIndex ) { - if( mTransitionAnimation ) + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SelectRequiredVisual index(%d) state(%d)\n", visualIndex, mButtonState ); + // only enable visuals that exist + if( DevelControl::GetVisual( *this, visualIndex ) ) { - mTransitionAnimation.Clear(); - mTransitionAnimation.Reset(); + DevelControl::EnableVisual( *this, visualIndex, true ); } } -Dali::Animation Button::GetTransitionAnimation() +void Button::RemoveVisual( Property::Index visualIndex ) { - if( !mTransitionAnimation ) + // Use OnButtonVisualRemoval if want button developer to have the option to override removal. + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::RemoveVisual index(%d) state(%d)\n", visualIndex, mButtonState ); + + Toolkit::Visual::Base visual = DevelControl::GetVisual( *this, visualIndex ); + + if( visual ) { - mTransitionAnimation = Dali::Animation::New( GetAnimationTime() ); - mTransitionAnimation.FinishedSignal().Connect( this, &Button::TransitionAnimationFinished ); + DevelControl::EnableVisual( *this, visualIndex, false ); } - - return mTransitionAnimation; } -void Button::TransitionAnimationFinished( Dali::Animation& source ) +void Button::OnButtonVisualRemoval( Property::Index visualIndex ) { - StopTransitionAnimation(); - ResetImageLayers(); + // Derived Buttons can over ride this to prevent default removal. + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnButtonVisualRemoval index(%d)\n", visualIndex ); + RemoveVisual( visualIndex ); } void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) { Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) ); + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetProperty index[%d]\n", index ); + if ( button ) { switch ( index ) @@ -1379,52 +1115,81 @@ void Button::SetProperty( BaseObject* object, Property::Index index, const Prope break; } - case Toolkit::Button::Property::UNSELECTED_STATE_IMAGE: + case Toolkit::Button::Property::UNSELECTED_VISUAL: + case Toolkit::Button::Property::SELECTED_VISUAL: + case Toolkit::Button::Property::DISABLED_SELECTED_VISUAL: + case Toolkit::Button::Property::DISABLED_UNSELECTED_VISUAL: { - GetImplementation( button ).SetUnselectedImage( value.Get< std::string >() ); + GetImplementation( button ).CreateVisualsForComponent( index, value, DepthIndex::CONTENT ); break; } - case Toolkit::Button::Property::SELECTED_STATE_IMAGE: + case Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL: + case Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL: + case Toolkit::Button::Property::DISABLED_SELECTED_BACKGROUND_VISUAL: + case Toolkit::Button::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL: { - GetImplementation( button ).SetSelectedImage( value.Get< std::string >() ); + GetImplementation( button ).CreateVisualsForComponent( index , value, DepthIndex::BACKGROUND); break; } - case Toolkit::Button::Property::DISABLED_STATE_IMAGE: + case Toolkit::Button::Property::LABEL: { - GetImplementation( button ).SetDisabledImage( value.Get< std::string >() ); - break; - } + Property::Map outTextVisualProperties; + std::string textString; - case Toolkit::Button::Property::UNSELECTED_COLOR: - { - GetImplementation( button ).SetColor( value.Get< Vector4 >(), UnselectedState ); + if ( value.Get( textString ) ) + { + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetProperty Setting TextVisual with string[%s]\n", textString.c_str() ); + + Property::Map setPropertyMap; + setPropertyMap.Add( Toolkit::Visual::Property::TYPE, Toolkit::Visual::TEXT ) + .Add( Toolkit::TextVisual::Property::TEXT, textString ); + + GetImplementation( button ).MergeWithExistingLabelProperties( setPropertyMap, outTextVisualProperties ); + } + else + { + // Get a Property::Map from the property if possible. + Property::Map* setPropertyMap = value.GetMap(); + if( setPropertyMap ) + { + TextVisual::ConvertStringKeysToIndexKeys( *setPropertyMap ); + GetImplementation( button ).MergeWithExistingLabelProperties( *setPropertyMap, outTextVisualProperties ); + } + } + + if( !outTextVisualProperties.Empty() ) + { + GetImplementation( button ).CreateVisualsForComponent( index, outTextVisualProperties, DepthIndex::CONTENT ); + } break; } - case Toolkit::Button::Property::SELECTED_COLOR: + case Toolkit::DevelButton::Property::LABEL_RELATIVE_ALIGNMENT: { - GetImplementation( button ).SetColor( value.Get< Vector4 >(), SelectedState ); + Button::Align labelAlignment(END); + Scripting::GetEnumeration< Button::Align> ( value.Get< std::string >().c_str(), + ALIGNMENT_TABLE, ALIGNMENT_TABLE_COUNT, + labelAlignment ); + + GetImplementation( button ).SetLabelAlignment( labelAlignment ); break; } - case Toolkit::Button::Property::LABEL_TEXT: + case Toolkit::DevelButton::Property::LABEL_PADDING: { - GetImplementation( button ).SetLabelText( value.Get< std::string >() ); + Vector4 padding ( value.Get< Vector4 >() ); + GetImplementation( button ).SetLabelPadding( Padding( padding.x, padding.y, padding.z, padding.w ) ); break; } - case Toolkit::Button::Property::LABEL: + case Toolkit::DevelButton::Property::VISUAL_PADDING: { - // Get a Property::Map from the property if possible. - Property::Map setPropertyMap; - if( value.Get( setPropertyMap ) ) - { - GetImplementation( button ).ModifyLabel( setPropertyMap ); - } + Vector4 padding ( value.Get< Vector4 >() ); + GetImplementation( button ).SetForegroundPadding( Padding( padding.x, padding.y, padding.z, padding.w ) ); + break; } - break; } } } @@ -1441,7 +1206,7 @@ Property::Value Button::GetProperty( BaseObject* object, Property::Index propert { case Toolkit::Button::Property::DISABLED: { - value = GetImplementation( button ).mDisabled; + value = GetImplementation( button ).IsDisabled(); break; } @@ -1471,51 +1236,52 @@ Property::Value Button::GetProperty( BaseObject* object, Property::Index propert case Toolkit::Button::Property::SELECTED: { - value = GetImplementation( button ).mSelected; + value = GetImplementation( button ).IsSelected(); break; } - case Toolkit::Button::Property::UNSELECTED_STATE_IMAGE: - { - value = GetImplementation( button ).GetUnselectedImageFilename(); - break; - } - - case Toolkit::Button::Property::SELECTED_STATE_IMAGE: - { - value = GetImplementation( button ).GetSelectedImageFilename(); - break; - } - - case Toolkit::Button::Property::DISABLED_STATE_IMAGE: + case Toolkit::Button::Property::UNSELECTED_VISUAL: + case Toolkit::Button::Property::SELECTED_VISUAL: + case Toolkit::Button::Property::DISABLED_SELECTED_VISUAL: + case Toolkit::Button::Property::DISABLED_UNSELECTED_VISUAL: + case Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL: + case Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL: + case Toolkit::Button::Property::DISABLED_SELECTED_BACKGROUND_VISUAL: + case Toolkit::Button::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL: + case Toolkit::Button::Property::LABEL: { - value = GetImplementation( button ).GetDisabledImageFilename(); + Property::Map visualProperty; + if ( GetImplementation( button ).GetPropertyMapForVisual( propertyIndex, visualProperty ) ) + { + value = visualProperty; + } break; } - case Toolkit::Button::Property::UNSELECTED_COLOR: + case Toolkit::DevelButton::Property::LABEL_RELATIVE_ALIGNMENT: { - value = GetImplementation( button ).GetUnselectedColor(); - break; - } + const char* alignment = Scripting::GetEnumerationName< Button::Align >( GetImplementation( button ).GetLabelAlignment(), + ALIGNMENT_STRING_TABLE, + ALIGNMENT_STRING_TABLE_COUNT ); + if( alignment ) + { + value = std::string( alignment ); + } - case Toolkit::Button::Property::SELECTED_COLOR: - { - value = GetImplementation( button ).GetSelectedColor(); break; } - case Toolkit::Button::Property::LABEL_TEXT: + case Toolkit::DevelButton::Property::LABEL_PADDING: { - value = GetImplementation( button ).GetLabelText(); + Padding padding = GetImplementation( button ).GetLabelPadding(); + value = Vector4( padding.x, padding.y, padding.top, padding.bottom); break; } - case Toolkit::Button::Property::LABEL: + case Toolkit::DevelButton::Property::VISUAL_PADDING: { - Property::Map emptyMap; - value = emptyMap; - break; + Padding padding = GetImplementation( button ).GetForegroundPadding(); + value = Vector4( padding.x, padding.y, padding.top, padding.bottom); } } } @@ -1523,132 +1289,30 @@ Property::Value Button::GetProperty( BaseObject* object, Property::Index propert return value; } -// Deprecated API - -void Button::SetLabel( Actor label ) -{ - if( mLabel != label ) - { - if( mLabel && mLabel.GetParent() ) - { - mLabel.GetParent().Remove( mLabel ); - } - - mLabel = label; - mLabel.SetPosition( 0.0f, 0.0f ); - - // label should be the top of the button - Self().Add( mLabel ); - - ResetImageLayers(); - OnLabelSet( true ); - - RelayoutRequest(); - } -} - -void Button::SetButtonImage( Actor image ) -{ - if( image ) - { - StopTransitionAnimation(); - - SetupContent( mUnselectedContent, image ); - - OnUnselectedImageSet(); - RelayoutRequest(); - } -} - -void Button::SetSelectedImage( Actor image ) +void Button::SetLabelPadding( const Padding& padding) { - if( image ) - { - StopTransitionAnimation(); - - SetupContent( mSelectedContent, image ); - - OnSelectedImageSet(); - RelayoutRequest(); - } -} - -void Button::SetBackgroundImage( Actor image ) -{ - if( image ) - { - StopTransitionAnimation(); - - SetupContent( mBackgroundContent, image ); - - OnBackgroundImageSet(); - RelayoutRequest(); - } -} - -void Button::SetSelectedBackgroundImage( Actor image ) -{ - if( image ) - { - StopTransitionAnimation(); - - SetupContent( mSelectedBackgroundContent, image ); - - OnSelectedBackgroundImageSet(); - RelayoutRequest(); - } -} - -void Button::SetDisabledImage( Actor image ) -{ - if( image ) - { - StopTransitionAnimation(); - - SetupContent( mDisabledContent, image ); - - OnDisabledImageSet(); - RelayoutRequest(); - } -} - -void Button::SetDisabledSelectedImage( Actor image ) -{ - if( image ) - { - StopTransitionAnimation(); - - SetupContent( mDisabledSelectedContent, image ); - - OnDisabledSelectedImageSet(); - RelayoutRequest(); - } + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetLabelPadding padding(%f,%f,%f,%f)\n", padding.left, padding.right, padding.bottom, padding.top ); + mLabelPadding = Padding( padding.left, padding.right, padding.bottom, padding.top ); + RelayoutRequest(); } -void Button::SetDisabledBackgroundImage( Actor image ) +Padding Button::GetLabelPadding() { - if( image ) - { - StopTransitionAnimation(); - - SetupContent( mDisabledBackgroundContent, image ); - - OnDisabledBackgroundImageSet(); - RelayoutRequest(); - } + return mLabelPadding; } -Actor Button::GetButtonImage() const +void Button::SetForegroundPadding( const Padding& padding) { - return mUnselectedContent; + DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetForegroundPadding padding(%f,%f,%f,%f)\n", padding.left, padding.right, padding.bottom, padding.top ); + mForegroundPadding = Padding( padding.left, padding.right, padding.bottom, padding.top ); + RelayoutRequest(); } -Actor Button::GetSelectedImage() const +Padding Button::GetForegroundPadding() { - return mSelectedContent; + return mForegroundPadding; } - } // namespace Internal } // namespace Toolkit