X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Fpublic-api%2Fcontrols%2Fcontrol-impl.cpp;h=fffbe6962a4516972ff6482fc990c736007e04ea;hp=d3f43622f7cf8a556f8712fa19a9b084da2f508e;hb=9795d65d103bdf0524aa92e96475019eff2705f3;hpb=a2519d330569f4898996dfcc74b8d30433bace42 diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp index d3f4362..fffbe69 100644 --- a/dali-toolkit/public-api/controls/control-impl.cpp +++ b/dali-toolkit/public-api/controls/control-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 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. @@ -22,6 +22,7 @@ #include // for strcmp #include #include +#include #include #include #include @@ -29,6 +30,8 @@ #include #include #include +#include +#include #include #include @@ -37,14 +40,19 @@ #include #include #include +#include #include -#include +#include +#include +#include #include #include #include #include #include +#include #include +#include namespace Dali { @@ -52,13 +60,34 @@ namespace Dali namespace Toolkit { +namespace Internal +{ + +extern const Dali::Scripting::StringEnum ControlStateTable[]; +extern const unsigned int ControlStateTableCount; + + +// Not static or anonymous - shared with other translation units +const Scripting::StringEnum ControlStateTable[] = { + { "NORMAL", Toolkit::DevelControl::NORMAL }, + { "FOCUSED", Toolkit::DevelControl::FOCUSED }, + { "DISABLED", Toolkit::DevelControl::DISABLED }, +}; const unsigned int ControlStateTableCount = sizeof( ControlStateTable ) / sizeof( ControlStateTable[0] ); + +} // Internal namespace + namespace { #if defined(DEBUG_ENABLED) -Debug::Filter* gLogFilter = Debug::Filter::New( Debug::General, false, "LOG_CONTROL_VISUALS"); +Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_CONTROL_VISUALS"); #endif +DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE ) +DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED ) +DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN ) +DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE ) + /** * Struct used to store Visual within the control, index is a unique key for each visual. */ @@ -68,29 +97,12 @@ struct RegisteredVisual Toolkit::Visual::Base visual; bool enabled; - RegisteredVisual( Property::Index aIndex, Toolkit::Visual::Base &aVisual, bool aEnabled) : - index(aIndex), visual(aVisual), enabled(aEnabled) {} -}; - -struct HandleIndex -{ - Handle handle; ///< a handle to the target object - Property::Index index; ///< The index of a property provided by the referenced object - - HandleIndex( ) - : handle(), - index( Property::INVALID_INDEX ) - { - } - - HandleIndex( Handle& handle, Property::Index index ) - : handle( handle ), - index( index ) + RegisteredVisual( Property::Index aIndex, Toolkit::Visual::Base &aVisual, bool aEnabled) + : index(aIndex), visual(aVisual), enabled(aEnabled) { } }; - typedef Dali::OwnerContainer< RegisteredVisual* > RegisteredVisualContainer; /** @@ -108,73 +120,23 @@ bool FindVisual( Property::Index targetIndex, RegisteredVisualContainer& visuals return false; } -HandleIndex GetVisualProperty( - Internal::Control& controlImpl, +Toolkit::Visual::Base GetVisualByName( RegisteredVisualContainer& visuals, - const std::string& visualName, - Property::Key propertyKey ) + const std::string& visualName ) { -#if defined(DEBUG_ENABLED) - std::ostringstream oss; - oss << "Control::GetHandleIndex(" << visualName << ", " << propertyKey << ")" << std::endl; - DALI_LOG_INFO( gLogFilter, Debug::General, oss.str().c_str() ); -#endif + Toolkit::Visual::Base visualHandle; - // Find visualName in the control RegisteredVisualContainer::Iterator iter; for ( iter = visuals.Begin(); iter != visuals.End(); iter++ ) { - if ( (*iter)->visual.GetName() == visualName ) + Toolkit::Visual::Base visual = (*iter)->visual; + if( visual && visual.GetName() == visualName ) { + visualHandle = visual; break; } } - - // Does it's renderer have an associated property? - if( iter != visuals.End() ) - { - Actor self = controlImpl.Self(); - Property::Index index = self.GetPropertyIndex( propertyKey ); - if( index != Property::INVALID_INDEX ) - { - // It's an actor property: - return HandleIndex( self, index ); - } - else - { - // Check if it is a renderer property: - if( self.GetRendererCount() > 0 ) - { - // @todo Need to use correct renderer index - Renderer renderer = self.GetRendererAt(0); - Property::Index index = renderer.GetPropertyIndex( propertyKey ); - if( index != Property::INVALID_INDEX ) - { - // It's a renderer property: - return HandleIndex( renderer, index ); - } - } - else - { - std::ostringstream oss; - oss << propertyKey; - DALI_LOG_WARNING( "Control::GetHandleIndex(%s, %s) No renderers\n", visualName.c_str(), oss.str().c_str() ); - } - } - } - Handle handle; - return HandleIndex( handle, Property::INVALID_INDEX ); -} - -void SetDefaultTransform( Property::Map& propertyMap ) -{ - propertyMap.Clear(); - propertyMap - .Add( Toolkit::Visual::DevelProperty::Transform::Property::OFFSET, Vector2(0.0f, 0.0f) ) - .Add( Toolkit::Visual::DevelProperty::Transform::Property::SIZE, Vector2(1.0f, 1.0f) ) - .Add( Toolkit::Visual::DevelProperty::Transform::Property::ORIGIN, Toolkit::Align::CENTER ) - .Add( Toolkit::Visual::DevelProperty::Transform::Property::ANCHOR_POINT, Toolkit::Align::CENTER ) - .Add( Toolkit::Visual::DevelProperty::Transform::Property::OFFSET_SIZE_MODE, Vector4::ZERO ); + return visualHandle; } /** @@ -302,6 +264,12 @@ public: // Construction & Destruction Impl(Control& controlImpl) : mControlImpl( controlImpl ), + mState( Toolkit::DevelControl::NORMAL ), + mSubStateName(""), + mLeftFocusableActorId( -1 ), + mRightFocusableActorId( -1 ), + mUpFocusableActorId( -1 ), + mDownFocusableActorId( -1 ), mStyleName(""), mBackgroundColor(Color::TRANSPARENT), mStartingPinchScale( NULL ), @@ -368,6 +336,83 @@ public: break; } + case Toolkit::DevelControl::Property::STATE: + { + bool withTransitions=true; + const Property::Value* valuePtr=&value; + Property::Map* map = value.GetMap(); + if(map) + { + Property::Value* value2 = map->Find("withTransitions"); + if( value2 ) + { + withTransitions = value2->Get(); + } + + valuePtr = map->Find("state"); + } + + if( valuePtr ) + { + Toolkit::DevelControl::State state( controlImpl.mImpl->mState ); + if( Scripting::GetEnumerationProperty< Toolkit::DevelControl::State >( *valuePtr, ControlStateTable, ControlStateTableCount, state ) ) + { + controlImpl.mImpl->SetState( state, withTransitions ); + } + } + } + break; + + case Toolkit::DevelControl::Property::SUB_STATE: + { + std::string subState; + if( value.Get( subState ) ) + { + controlImpl.mImpl->SetSubState( subState ); + } + } + break; + + case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID: + { + int focusId; + if( value.Get( focusId ) ) + { + controlImpl.mImpl->mLeftFocusableActorId = focusId; + } + } + break; + + case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID: + { + int focusId; + if( value.Get( focusId ) ) + { + controlImpl.mImpl->mRightFocusableActorId = focusId; + } + } + break; + + case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID: + { + int focusId; + if( value.Get( focusId ) ) + { + controlImpl.mImpl->mUpFocusableActorId = focusId; + } + } + break; + + case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID: + { + int focusId; + if( value.Get( focusId ) ) + { + controlImpl.mImpl->mDownFocusableActorId = focusId; + } + } + break; + case Toolkit::Control::Property::BACKGROUND_COLOR: { DALI_LOG_WARNING( "BACKGROUND_COLOR property is deprecated. Use BACKGROUND property instead\n" ); @@ -406,11 +451,27 @@ public: case Toolkit::Control::Property::BACKGROUND: { + std::string url; + Vector4 color; const Property::Map* map = value.GetMap(); if( map && !map->Empty() ) { controlImpl.SetBackground( *map ); } + else if( value.Get( url ) ) + { + // don't know the size to load + Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( url, ImageDimensions() ); + if( visual ) + { + controlImpl.RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual ); + visual.SetDepthIndex( DepthIndex::BACKGROUND ); + } + } + else if( value.Get( color ) ) + { + controlImpl.SetBackgroundColor(color); + } else { // The background is an empty property map, so we should clear the background @@ -418,6 +479,16 @@ public: } break; } + + case Toolkit::DevelControl::Property::TOOLTIP: + { + TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip; + if( ! tooltipPtr ) + { + tooltipPtr = Tooltip::New( control ); + } + tooltipPtr->SetProperties( value ); + } } } } @@ -446,6 +517,42 @@ public: break; } + case Toolkit::DevelControl::Property::STATE: + { + value = controlImpl.mImpl->mState; + break; + } + + case Toolkit::DevelControl::Property::SUB_STATE: + { + value = controlImpl.mImpl->mSubStateName; + break; + } + + case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID: + { + value = controlImpl.mImpl->mLeftFocusableActorId; + break; + } + + case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID: + { + value = controlImpl.mImpl->mRightFocusableActorId; + break; + } + + case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID: + { + value = controlImpl.mImpl->mUpFocusableActorId; + break; + } + + case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID: + { + value = controlImpl.mImpl->mDownFocusableActorId; + break; + } + case Toolkit::Control::Property::BACKGROUND_COLOR: { DALI_LOG_WARNING( "BACKGROUND_COLOR property is deprecated. Use BACKGROUND property instead\n" ); @@ -485,15 +592,323 @@ public: break; } + case Toolkit::DevelControl::Property::TOOLTIP: + { + Property::Map map; + if( controlImpl.mImpl->mTooltip ) + { + controlImpl.mImpl->mTooltip->CreatePropertyMap( map ); + } + value = map; + break; + } + } } return value; } + + void CopyInstancedProperties( RegisteredVisualContainer& visuals, Dictionary& instancedProperties ) + { + for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter!= visuals.End(); iter++) + { + if( (*iter)->visual ) + { + Property::Map instanceMap; + Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap); + instancedProperties.Add( (*iter)->visual.GetName(), instanceMap ); + } + } + } + + template + void Remove( Dictionary& keyValues, const std::string& name ) + { + keyValues.Remove(name); + } + + void Remove( DictionaryKeys& keys, const std::string& name ) + { + DictionaryKeys::iterator iter = std::find( keys.begin(), keys.end(), name ); + if( iter != keys.end()) + { + keys.erase(iter); + } + } + + void FindChangableVisuals( Dictionary& stateVisualsToAdd, + Dictionary& stateVisualsToChange, + DictionaryKeys& stateVisualsToRemove) + { + DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove; + + for( DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin(); + iter != copyOfStateVisualsToRemove.end(); ++iter ) + { + const std::string& visualName = (*iter); + Property::Map* toMap = stateVisualsToAdd.Find( visualName ); + if( toMap ) + { + stateVisualsToChange.Add( visualName, *toMap ); + stateVisualsToAdd.Remove( visualName ); + Remove( stateVisualsToRemove, visualName ); + } + } + } + + void RemoveVisual( RegisteredVisualContainer& visuals, const std::string& visualName ) + { + Actor self( mControlImpl.Self() ); + + for ( RegisteredVisualContainer::Iterator visualIter = visuals.Begin(); + visualIter != visuals.End(); ++visualIter ) + { + Toolkit::Visual::Base visual = (*visualIter)->visual; + if( visual && visual.GetName() == visualName ) + { + Toolkit::GetImplementation(visual).SetOffStage( self ); + (*visualIter)->visual.Reset(); + visuals.Erase( visualIter ); + break; + } + } + } + + void RemoveVisuals( RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals ) + { + Actor self( mControlImpl.Self() ); + for( DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter ) + { + const std::string visualName = *iter; + RemoveVisual( visuals, visualName ); + } + } + + Toolkit::DevelVisual::Type GetVisualTypeFromMap( const Property::Map& map ) + { + Property::Value* typeValue = map.Find( Toolkit::DevelVisual::Property::TYPE, VISUAL_TYPE ); + Toolkit::DevelVisual::Type type = Toolkit::DevelVisual::IMAGE; + if( typeValue ) + { + Scripting::GetEnumerationProperty( *typeValue, VISUAL_TYPE_TABLE, VISUAL_TYPE_TABLE_COUNT, type ); + } + return type; + } + + /** + * Go through the list of visuals that are common to both states. + * If they are different types, or are both image types with different + * URLs, then the existing visual needs moving and the new visual creating + */ + void RecreateChangedVisuals( Dictionary& stateVisualsToChange, + Dictionary& instancedProperties ) + { + Dali::CustomActor handle( mControlImpl.GetOwner() ); + for( Dictionary::iterator iter = stateVisualsToChange.Begin(); + iter != stateVisualsToChange.End(); ++iter ) + { + const std::string& visualName = (*iter).key; + const Property::Map& toMap = (*iter).entry; + + // is it a candidate for re-creation? + bool recreate = false; + + Toolkit::Visual::Base visual = GetVisualByName( mVisuals, visualName ); + if( visual ) + { + Property::Map fromMap; + visual.CreatePropertyMap( fromMap ); + + Toolkit::DevelVisual::Type fromType = GetVisualTypeFromMap( fromMap ); + Toolkit::DevelVisual::Type toType = GetVisualTypeFromMap( toMap ); + + if( fromType != toType ) + { + recreate = true; + } + else + { + if( fromType == Toolkit::DevelVisual::IMAGE || fromType == Toolkit::DevelVisual::N_PATCH + || fromType == Toolkit::DevelVisual::SVG || fromType == Toolkit::DevelVisual::ANIMATED_IMAGE ) + { + Property::Value* fromUrl = fromMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME ); + Property::Value* toUrl = toMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME ); + + if( fromUrl && toUrl ) + { + std::string fromUrlString; + std::string toUrlString; + fromUrl->Get(fromUrlString); + toUrl->Get(toUrlString); + + if( fromUrlString != toUrlString ) + { + recreate = true; + } + } + } + } + + const Property::Map* instancedMap = instancedProperties.FindConst( visualName ); + if( recreate || instancedMap ) + { + RemoveVisual( mVisuals, visualName ); + Style::ApplyVisual( handle, visualName, toMap, instancedMap ); + } + else + { + // @todo check to see if we can apply toMap without recreating the visual + // e.g. by setting only animatable properties + // For now, recreate all visuals, but merge in instance data. + RemoveVisual( mVisuals, visualName ); + Style::ApplyVisual( handle, visualName, toMap, instancedMap ); + } + } + } + } + + void ReplaceStateVisualsAndProperties( const StylePtr oldState, const StylePtr newState, const std::string& subState ) + { + // Collect all old visual names + DictionaryKeys stateVisualsToRemove; + if( oldState ) + { + oldState->visuals.GetKeys( stateVisualsToRemove ); + if( ! subState.empty() ) + { + const StylePtr* oldSubState = oldState->subStates.FindConst(subState); + if( oldSubState ) + { + DictionaryKeys subStateVisualsToRemove; + (*oldSubState)->visuals.GetKeys( subStateVisualsToRemove ); + Merge( stateVisualsToRemove, subStateVisualsToRemove ); + } + } + } + + // Collect all new visual properties + Dictionary stateVisualsToAdd; + if( newState ) + { + stateVisualsToAdd = newState->visuals; + if( ! subState.empty() ) + { + const StylePtr* newSubState = newState->subStates.FindConst(subState); + if( newSubState ) + { + stateVisualsToAdd.Merge( (*newSubState)->visuals ); + } + } + } + + // If a name is in both add/remove, move it to change list. + Dictionary stateVisualsToChange; + FindChangableVisuals( stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove); + + // Copy instanced properties (e.g. text label) of current visuals + Dictionary instancedProperties; + CopyInstancedProperties( mVisuals, instancedProperties ); + + // For each visual in remove list, remove from mVisuals + RemoveVisuals( mVisuals, stateVisualsToRemove ); + + // For each visual in add list, create and add to mVisuals + Dali::CustomActor handle( mControlImpl.GetOwner() ); + Style::ApplyVisuals( handle, stateVisualsToAdd, instancedProperties ); + + // For each visual in change list, if it requires a new visual, + // remove old visual, create and add to mVisuals + RecreateChangedVisuals( stateVisualsToChange, instancedProperties ); + } + + void SetState( DevelControl::State newState, bool withTransitions=true ) + { + DevelControl::State oldState = mState; + Dali::CustomActor handle( mControlImpl.GetOwner() ); + DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", + (mState == DevelControl::NORMAL ? "NORMAL" :( + mState == DevelControl::FOCUSED ?"FOCUSED" : ( + mState == DevelControl::DISABLED?"DISABLED":"NONE" )))); + + if( mState != newState ) + { + // If mState was Disabled, and new state is Focused, should probably + // store that fact, e.g. in another property that FocusManager can access. + mState = newState; + + // Trigger state change and transitions + // Apply new style, if stylemanager is available + Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get(); + if( styleManager ) + { + const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) ); + + if( stylePtr ) + { + std::string oldStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( oldState, ControlStateTable, ControlStateTableCount ); + std::string newStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( newState, ControlStateTable, ControlStateTableCount ); + + const StylePtr* newStateStyle = stylePtr->subStates.Find( newStateName ); + const StylePtr* oldStateStyle = stylePtr->subStates.Find( oldStateName ); + if( oldStateStyle && newStateStyle ) + { + // Only change if both state styles exist + ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, mSubStateName ); + } + } + } + } + } + + void SetSubState( const std::string& subStateName, bool withTransitions=true ) + { + if( mSubStateName != subStateName ) + { + // Get existing sub-state visuals, and unregister them + Dali::CustomActor handle( mControlImpl.GetOwner() ); + + Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get(); + if( styleManager ) + { + const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) ); + if( stylePtr ) + { + // Stringify state + std::string stateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( mState, ControlStateTable, ControlStateTableCount ); + + const StylePtr* state = stylePtr->subStates.Find( stateName ); + if( state ) + { + StylePtr stateStyle(*state); + + const StylePtr* newStateStyle = stateStyle->subStates.Find( subStateName ); + const StylePtr* oldStateStyle = stateStyle->subStates.Find( mSubStateName ); + if( oldStateStyle && newStateStyle ) + { + std::string empty; + ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, empty ); + } + } + } + } + + mSubStateName = subStateName; + } + } + // Data Control& mControlImpl; + DevelControl::State mState; + std::string mSubStateName; + + int mLeftFocusableActorId; ///< Actor ID of Left focusable control. + int mRightFocusableActorId; ///< Actor ID of Right focusable control. + int mUpFocusableActorId; ///< Actor ID of Up focusable control. + int mDownFocusableActorId; ///< Actor ID of Down focusable control. + RegisteredVisualContainer mVisuals; // Stores visuals needed by the control, non trivial type so std::vector used. std::string mStyleName; Vector4 mBackgroundColor; ///< The color of the background visual @@ -508,24 +923,41 @@ public: TapGestureDetector mTapGestureDetector; LongPressGestureDetector mLongPressGestureDetector; + // Tooltip + TooltipPtr mTooltip; + ControlBehaviour mFlags : CONTROL_BEHAVIOUR_FLAG_COUNT; ///< Flags passed in from constructor. bool mIsKeyboardNavigationSupported :1; ///< Stores whether keyboard navigation is supported by the control. bool mIsKeyboardFocusGroup :1; ///< Stores whether the control is a focus group. - // Properties - these need to be members of Internal::Control::Impl as they need to function within this class. + // Properties - these need to be members of Internal::Control::Impl as they access private methods/data of Internal::Control and Internal::Control::Impl. static const PropertyRegistration PROPERTY_1; static const PropertyRegistration PROPERTY_2; static const PropertyRegistration PROPERTY_3; static const PropertyRegistration PROPERTY_4; static const PropertyRegistration PROPERTY_5; + static const PropertyRegistration PROPERTY_6; + static const PropertyRegistration PROPERTY_7; + static const PropertyRegistration PROPERTY_8; + static const PropertyRegistration PROPERTY_9; + static const PropertyRegistration PROPERTY_10; + static const PropertyRegistration PROPERTY_11; + static const PropertyRegistration PROPERTY_12; }; // Properties registered without macro to use specific member variables. -const PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); -const PropertyRegistration Control::Impl::PROPERTY_2( typeRegistration, "backgroundColor", Toolkit::Control::Property::BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); -const PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "backgroundImage", Toolkit::Control::Property::BACKGROUND_IMAGE, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); -const PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); -const PropertyRegistration Control::Impl::PROPERTY_5( typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +const PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "styleName", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +const PropertyRegistration Control::Impl::PROPERTY_2( typeRegistration, "backgroundColor", Toolkit::Control::Property::BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +const PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "backgroundImage", Toolkit::Control::Property::BACKGROUND_IMAGE, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +const PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "keyInputFocus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +const PropertyRegistration Control::Impl::PROPERTY_5( typeRegistration, "background", Toolkit::Control::Property::BACKGROUND, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +const PropertyRegistration Control::Impl::PROPERTY_6( typeRegistration, "tooltip", Toolkit::DevelControl::Property::TOOLTIP, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +const PropertyRegistration Control::Impl::PROPERTY_7( typeRegistration, "state", Toolkit::DevelControl::Property::STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +const PropertyRegistration Control::Impl::PROPERTY_8( typeRegistration, "subState", Toolkit::DevelControl::Property::SUB_STATE, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +const PropertyRegistration Control::Impl::PROPERTY_9( typeRegistration, "leftFocusableActorId", Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +const PropertyRegistration Control::Impl::PROPERTY_10( typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID,Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +const PropertyRegistration Control::Impl::PROPERTY_11( typeRegistration, "upFocusableActorId", Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +const PropertyRegistration Control::Impl::PROPERTY_12( typeRegistration, "downFocusableActorId", Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); Toolkit::Control Control::New() { @@ -542,11 +974,6 @@ Toolkit::Control Control::New() return handle; } -Control::~Control() -{ - delete mImpl; -} - void Control::SetStyleName( const std::string& styleName ) { if( styleName != mImpl->mStyleName ) @@ -571,7 +998,7 @@ void Control::SetBackgroundColor( const Vector4& color ) { mImpl->mBackgroundColor = color; Property::Map map; - map[ Toolkit::VisualProperty::TYPE ] = Toolkit::Visual::COLOR; + map[ Toolkit::DevelVisual::Property::TYPE ] = Toolkit::Visual::COLOR; map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color; SetBackground( map ); @@ -589,12 +1016,14 @@ void Control::SetBackground( const Property::Map& map ) { RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual ); visual.SetDepthIndex( DepthIndex::BACKGROUND ); + + // Trigger a size negotiation request that may be needed by the new visual to relayout its contents. + RelayoutRequest(); } } void Control::SetBackgroundImage( Image image ) { - DALI_LOG_WARNING( "SetBackgroundImage is for the depreciated Property::BACKGROUND_IMAGE use SetBackground( const Property::Map& map )\n" ); Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( image ); if( visual ) { @@ -607,6 +1036,9 @@ void Control::ClearBackground() { UnregisterVisual( Toolkit::Control::Property::BACKGROUND ); mImpl->mBackgroundColor = Color::TRANSPARENT; + + // Trigger a size negotiation request that may be needed when unregistering a visual. + RelayoutRequest(); } void Control::EnableGestureDetection(Gesture::Type type) @@ -710,7 +1142,11 @@ bool Control::HasKeyInputFocus() bool result = false; if( Self().OnStage() ) { - result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self())); + Toolkit::Control control = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl(); + if( Self() == control ) + { + result = true; + } } return result; } @@ -773,6 +1209,27 @@ void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visu } } + // If not set, set the name of the visual to the same name as the control's property. + // ( If the control has been type registered ) + if( visual.GetName().empty() ) + { + // Check if the control has been type registered: + TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( typeid(*this) ); + if( typeInfo ) + { + // Check if the property index has been registered: + Property::IndexContainer indices; + typeInfo.GetPropertyIndices( indices ); + Property::IndexContainer::Iterator iter = std::find( indices.Begin(), indices.End(), index ); + if( iter != indices.End() ) + { + // If it has, then get it's name and use that for the visual + std::string visualName = typeInfo.GetPropertyName( index ); + visual.SetName( visualName ); + } + } + } + if( !visualReplaced ) // New registration entry { mImpl->mVisuals.PushBack( new RegisteredVisual( index, visual, enabled ) ); @@ -782,6 +1239,8 @@ void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visu { Toolkit::GetImplementation(visual).SetOnStage( self ); } + + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled?"T":"F" ); } void Control::UnregisterVisual( Property::Index index ) @@ -814,7 +1273,7 @@ void Control::EnableVisual( Property::Index index, bool enable ) { if ( (*iter)->enabled == enable ) { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual Already enabled set (%s) \n", enable?"enabled":"disabled"); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled"); return; } @@ -824,12 +1283,12 @@ void Control::EnableVisual( Property::Index index, bool enable ) { if ( enable ) { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting Visual(%d) on stage \n", index ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index ); Toolkit::GetImplementation((*iter)->visual).SetOnStage( parentActor ); } else { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting Visual(%d) off stage \n", index ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index ); Toolkit::GetImplementation((*iter)->visual).SetOffStage( parentActor ); // No need to call if control not staged. } } @@ -859,51 +1318,50 @@ Dali::Animation Control::CreateTransition( const Toolkit::TransitionData& handle iter != end; ++iter ) { TransitionData::Animator* animator = (*iter); - HandleIndex handleIndex; - // Attempt to find the object name as a child actor - Actor child = Self().FindChildByName( animator->objectName ); - if( child ) + Toolkit::Visual::Base visual = GetVisualByName( mImpl->mVisuals, animator->objectName ); + + if( visual ) { - Property::Index propertyIndex = child.GetPropertyIndex( animator->propertyKey ); - handleIndex = HandleIndex( child, propertyIndex ); + Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual ); + visualImpl.AnimateProperty( transition, *animator ); } else { - handleIndex = GetVisualProperty( *this, mImpl->mVisuals, - animator->objectName, - animator->propertyKey ); - } - - if( handleIndex.handle && handleIndex.index != Property::INVALID_INDEX ) - { - if( animator->animate == false ) + // Otherwise, try any actor children of control (Including the control) + Actor child = Self().FindChildByName( animator->objectName ); + if( child ) { - if( animator->targetValue.GetType() != Property::NONE ) + Property::Index propertyIndex = DevelHandle::GetPropertyIndex( child, animator->propertyKey ); + if( propertyIndex != Property::INVALID_INDEX ) { - handleIndex.handle.SetProperty( handleIndex.index, animator->targetValue ); + if( animator->animate == false ) + { + if( animator->targetValue.GetType() != Property::NONE ) + { + child.SetProperty( propertyIndex, animator->targetValue ); + } + } + else // animate the property + { + if( animator->initialValue.GetType() != Property::NONE ) + { + child.SetProperty( propertyIndex, animator->initialValue ); + } + + if( ! transition ) + { + transition = Dali::Animation::New( 0.1f ); + } + + transition.AnimateTo( Property( child, propertyIndex ), + animator->targetValue, + animator->alphaFunction, + TimePeriod( animator->timePeriodDelay, + animator->timePeriodDuration ) ); + } } } - else - { - if( animator->initialValue.GetType() != Property::NONE ) - { - handleIndex.handle.SetProperty( handleIndex.index, animator->initialValue ); - } - - if( ! transition ) - { - // Create an animation with a default .1 second duration - the animators - // will automatically force it to the 'right' duration. - transition = Dali::Animation::New( 0.1f ); - } - - transition.AnimateTo( Property( handleIndex.handle, handleIndex.index ), - animator->targetValue, - animator->alphaFunction, - TimePeriod( animator->timePeriodDelay, - animator->timePeriodDuration ) ); - } } } } @@ -994,6 +1452,11 @@ Control::Control( ControlBehaviour behaviourFlags ) mImpl->mFlags = behaviourFlags; } +Control::~Control() +{ + delete mImpl; +} + void Control::Initialize() { // Call deriving classes so initialised before styling is applied to them. @@ -1041,8 +1504,8 @@ void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Ty if( styleManager && change == StyleChange::THEME_CHANGE ) { GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); + RelayoutRequest(); } - RelayoutRequest(); } void Control::OnPinch(const PinchGesture& pinch) @@ -1099,16 +1562,33 @@ void Control::OnStageConnection( int depth ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection number of registered visuals(%d)\n", mImpl->mVisuals.Size() ); + Actor self( Self() ); + for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++) { // Check whether the visual is empty and enabled if( (*iter)->visual && (*iter)->enabled ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection Setting visual(%d) on stage\n", (*iter)->index ); - Actor self( Self() ); Toolkit::GetImplementation((*iter)->visual).SetOnStage( self ); } } + + if( mImpl->mVisuals.Empty() && ! self.GetRendererCount() ) + { + Property::Value clippingValue = self.GetProperty( Actor::Property::CLIPPING_MODE ); + int clippingMode = ClippingMode::DISABLED; + if( clippingValue.Get( clippingMode ) ) + { + // Add a transparent background if we do not have any renderers or visuals so we clip our children + + if( clippingMode == ClippingMode::CLIP_CHILDREN ) + { + // Create a transparent background visual which will also get staged. + SetBackgroundColor( Color::TRANSPARENT ); + } + } + } } void Control::OnStageDisconnection() @@ -1147,15 +1627,36 @@ void Control::OnChildRemove(Actor& child) OnControlChildRemove( child ); } +void Control::OnPropertySet( Property::Index index, Property::Value propertyValue ) +{ + Actor self( Self() ); + if( index == Actor::Property::CLIPPING_MODE ) + { + // Only set the background if we're already on the stage and have no renderers or visuals + + if( mImpl->mVisuals.Empty() && ! self.GetRendererCount() && self.OnStage() ) + { + ClippingMode::Type clippingMode = ClippingMode::DISABLED; + if( Scripting::GetEnumerationProperty< ClippingMode::Type >( propertyValue, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, clippingMode ) ) + { + // Add a transparent background if we do not have one so we clip children + + if( clippingMode == ClippingMode::CLIP_CHILDREN ) + { + SetBackgroundColor( Color::TRANSPARENT ); + } + } + } + } +} + void Control::OnSizeSet(const Vector3& targetSize) { Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND ); if( visual ) { Vector2 size( targetSize ); - Property::Map transformMap; - SetDefaultTransform( transformMap ); - visual.SetTransformAndSize( transformMap, size ); + visual.SetTransformAndSize( Property::Map(), size ); // Send an empty map as we do not want to modify the visual's set transform } } @@ -1194,10 +1695,7 @@ void Control::OnRelayout( const Vector2& size, RelayoutContainer& container ) Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND ); if( visual ) { - Vector2 controlSize( size ); - Property::Map transformMap; - SetDefaultTransform( transformMap ); - visual.SetTransformAndSize( transformMap, controlSize ); + visual.SetTransformAndSize( Property::Map(), size ); // Send an empty map as we do not want to modify the visual's set transform } }