X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Fpublic-api%2Fcontrols%2Fcontrol-impl.cpp;h=c62684fce1b3478e7ac959a1ebb9b068d4d50ab2;hb=refs%2Fchanges%2F64%2F220864%2F1;hp=719c6a8f60cd607a31ace3f4bdb58b1f0c106332;hpb=805ae527fca54726f894fb9936c288c7c0f7dbe7;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp old mode 100644 new mode 100755 index 719c6a8..c469d1c --- 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) 2019 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,25 +22,28 @@ #include // for strcmp #include #include +#include #include -#include -#include #include -#include #include #include #include // INTERNAL INCLUDES -#include +#include #include +#include #include +#include +#include #include -#include +#include #include +#include #include -#include -#include +#include +#include +#include namespace Dali { @@ -48,362 +51,91 @@ namespace Dali namespace Toolkit { -namespace +namespace Internal { -/** - * Creates control through type registry - */ -BaseHandle Create() +namespace { - return Internal::Control::New(); -} + +#if defined(DEBUG_ENABLED) +Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_CONTROL_VISUALS"); +#endif /** - * Performs actions as requested using the action name. - * @param[in] object The object on which to perform the action. - * @param[in] actionName The action to perform. - * @param[in] attributes The attributes with which to perfrom this action. - * @return true if action has been accepted by this control + * @brief Replace the background visual if it's a color visual with the renderIfTransparent property set as required. + * @param[in] controlImpl The control implementation + * @param[in] renderIfTransaparent Whether we should render if the color is transparent */ -const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated"; -static bool DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes ) +void ChangeBackgroundColorVisual( Control& controlImpl, bool renderIfTransparent ) { - bool ret = false; + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl ); - if( object && ( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED ) ) ) + Toolkit::Visual::Base backgroundVisual = controlDataImpl.GetVisual( Toolkit::Control::Property::BACKGROUND ); + if( backgroundVisual ) { - Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) ); - if( control ) + Property::Map map; + backgroundVisual.CreatePropertyMap( map ); + Property::Value* typeValue = map.Find( Toolkit::Visual::Property::TYPE ); + if( typeValue && typeValue->Get< int >() == Toolkit::Visual::COLOR ) { - // if cast succeeds there is an implementation so no need to check - ret = Internal::GetImplementation( control ).OnAccessibilityActivated(); + // Only change it if it's a color visual + map[ Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT ] = renderIfTransparent; + controlImpl.SetBackground( map ); } } - - return ret; } /** - * Connects a callback function with the object's signals. - * @param[in] object The object providing the signal. - * @param[in] tracker Used to disconnect the signal. - * @param[in] signalName The signal to connect to. - * @param[in] functor A newly allocated FunctorDelegate. - * @return True if the signal was connected. - * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor. + * @brief Creates a clipping renderer if required. + * (EG. If no renders exist and clipping is enabled). + * @param[in] controlImpl The control implementation. */ -const char* SIGNAL_KEY_EVENT = "keyEvent"; -const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained"; -const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost"; -const char* SIGNAL_TAPPED = "tapped"; -const char* SIGNAL_PANNED = "panned"; -const char* SIGNAL_PINCHED = "pinched"; -const char* SIGNAL_LONG_PRESSED = "longPressed"; -static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) -{ - Dali::BaseHandle handle( object ); - - bool connected( false ); - Toolkit::Control control = Toolkit::Control::DownCast( handle ); - if ( control ) - { - Internal::Control& controlImpl( Internal::GetImplementation( control ) ); - connected = true; - - if ( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_EVENT ) ) - { - controlImpl.KeyEventSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED ) ) - { - controlImpl.KeyInputFocusGainedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST ) ) - { - controlImpl.KeyInputFocusLostSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_TAPPED ) ) - { - controlImpl.EnableGestureDetection( Gesture::Tap ); - controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_PANNED ) ) - { - controlImpl.EnableGestureDetection( Gesture::Pan ); - controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_PINCHED ) ) - { - controlImpl.EnableGestureDetection( Gesture::Pinch ); - controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_LONG_PRESSED ) ) - { - controlImpl.EnableGestureDetection( Gesture::LongPress ); - controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor ); - } - } - return connected; -} - -// Setup signals and actions using the type-registry. -DALI_TYPE_REGISTRATION_BEGIN( Control, CustomActor, Create ); - -// Note: Properties are registered separately below. - -SignalConnectorType registerSignal1( typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal ); -SignalConnectorType registerSignal2( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal ); -SignalConnectorType registerSignal3( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal ); -SignalConnectorType registerSignal4( typeRegistration, SIGNAL_TAPPED, &DoConnectSignal ); -SignalConnectorType registerSignal5( typeRegistration, SIGNAL_PANNED, &DoConnectSignal ); -SignalConnectorType registerSignal6( typeRegistration, SIGNAL_PINCHED, &DoConnectSignal ); -SignalConnectorType registerSignal7( typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal ); - -TypeAction registerAction( typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction ); - -DALI_TYPE_REGISTRATION_END() - -} // unnamed namespace - -namespace Internal +void CreateClippingRenderer( Control& controlImpl ) { - -class Control::Impl : public ConnectionTracker -{ -public: - - // Construction & Destruction - Impl(Control& controlImpl) -: mControlImpl( controlImpl ), - mStyleName(""), - mBackgroundRenderer(), - mBackgroundColor(Color::TRANSPARENT), - mStartingPinchScale( NULL ), - mKeyEventSignal(), - mPinchGestureDetector(), - mPanGestureDetector(), - mTapGestureDetector(), - mLongPressGestureDetector(), - mFlags( Control::ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ), - mIsKeyboardNavigationSupported( false ), - mIsKeyboardFocusGroup( false ) -{ -} - - ~Impl() - { - // All gesture detectors will be destroyed so no need to disconnect. - delete mStartingPinchScale; - } - - // Gesture Detection Methods - - void PinchDetected(Actor actor, const PinchGesture& pinch) - { - mControlImpl.OnPinch(pinch); - } - - void PanDetected(Actor actor, const PanGesture& pan) - { - mControlImpl.OnPan(pan); - } - - void TapDetected(Actor actor, const TapGesture& tap) + // We want to add a transparent background if we do not have one for clipping. + Actor self( controlImpl.Self() ); + int clippingMode = ClippingMode::DISABLED; + if( self.GetProperty( Actor::Property::CLIPPING_MODE ).Get( clippingMode ) ) { - mControlImpl.OnTap(tap); - } - - void LongPressDetected(Actor actor, const LongPressGesture& longPress) - { - mControlImpl.OnLongPress(longPress); - } - - // Properties - - /** - * Called when a property of an object of this type is set. - * @param[in] object The object whose property is set. - * @param[in] index The property index. - * @param[in] value The new property value. - */ - static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) - { - Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) ); - - if ( control ) + switch( clippingMode ) { - Control& controlImpl( GetImplementation( control ) ); - - switch ( index ) + case ClippingMode::CLIP_CHILDREN: { - case Toolkit::Control::Property::STYLE_NAME: - { - controlImpl.SetStyleName( value.Get< std::string >() ); - break; - } - - case Toolkit::Control::Property::BACKGROUND_COLOR: - { - DALI_LOG_WARNING( "BACKGROUND_COLOR property is deprecated. Use BACKGROUND property instead\n" ); - controlImpl.SetBackgroundColor( value.Get< Vector4 >() ); - break; - } - - case Toolkit::Control::Property::BACKGROUND_IMAGE: - { - DALI_LOG_WARNING( "BACKGROUND_IMAGE property is deprecated. Use BACKGROUND property instead\n" ); - Image image = Scripting::NewImage( value ); - if ( image ) - { - controlImpl.SetBackgroundImage( image ); - } - else - { - // An empty map means the background is no longer required - controlImpl.ClearBackground(); - } - break; - } - - case Toolkit::Control::Property::KEY_INPUT_FOCUS: - { - if ( value.Get< bool >() ) - { - controlImpl.SetKeyInputFocus(); - } - else - { - controlImpl.ClearKeyInputFocus(); - } - break; - } - - case Toolkit::Control::Property::BACKGROUND: + if( self.GetRendererCount() == 0u ) { - const Property::Map* map = value.GetMap(); - if( map ) + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl ); + if( controlDataImpl.mVisuals.Empty() ) { - controlImpl.SetBackground( *map ); + controlImpl.SetBackgroundColor( Color::TRANSPARENT ); } else { - // The background is not a property map, so we should clear the background - controlImpl.ClearBackground(); + // We have visuals, check if we've set the background and re-create it to + // render even if transparent (only if it's a color visual) + ChangeBackgroundColorVisual( controlImpl, true ); } - break; } + break; } - } - } - - /** - * Called to retrieve a property of an object of this type. - * @param[in] object The object whose property is to be retrieved. - * @param[in] index The property index. - * @return The current value of the property. - */ - static Property::Value GetProperty( BaseObject* object, Property::Index index ) - { - Property::Value value; - - Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) ); - if ( control ) - { - Control& controlImpl( GetImplementation( control ) ); - - switch ( index ) + case ClippingMode::DISABLED: + case ClippingMode::CLIP_TO_BOUNDING_BOX: { - case Toolkit::Control::Property::STYLE_NAME: - { - value = controlImpl.GetStyleName(); - break; - } - - case Toolkit::Control::Property::BACKGROUND_COLOR: - { - DALI_LOG_WARNING( "BACKGROUND_COLOR property is deprecated. Use BACKGROUND property instead\n" ); - value = controlImpl.GetBackgroundColor(); - break; - } - - case Toolkit::Control::Property::BACKGROUND_IMAGE: - { - DALI_LOG_WARNING( "BACKGROUND_IMAGE property is deprecated. Use BACKGROUND property instead\n" ); - Property::Map map; - if( controlImpl.mImpl->mBackgroundRenderer ) - { - controlImpl.mImpl->mBackgroundRenderer.CreatePropertyMap( map ); - } - value = map; - break; - } - - case Toolkit::Control::Property::KEY_INPUT_FOCUS: - { - value = controlImpl.HasKeyInputFocus(); - break; - } - - case Toolkit::Control::Property::BACKGROUND: - { - Property::Map map; - if( controlImpl.mImpl->mBackgroundRenderer ) - { - (controlImpl.mImpl->mBackgroundRenderer).CreatePropertyMap( map ); - } - - value = map; - break; - } - + // If we have a background visual, check if it's a color visual and remove the render if transparent flag + ChangeBackgroundColorVisual( controlImpl, false ); + break; } } - - return value; } +} + +} // unnamed namespace - // Data - - Control& mControlImpl; - std::string mStyleName; - Toolkit::Visual mBackgroundRenderer; ///< The control renderer to render the background - Vector4 mBackgroundColor; ///< The color of the background renderer - Vector3* mStartingPinchScale; ///< The scale when a pinch gesture starts, TODO: consider removing this - Toolkit::Control::KeyEventSignalType mKeyEventSignal; - Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusGainedSignal; - Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusLostSignal; - - // Gesture Detection - PinchGestureDetector mPinchGestureDetector; - PanGestureDetector mPanGestureDetector; - TapGestureDetector mTapGestureDetector; - LongPressGestureDetector mLongPressGestureDetector; - - 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. - 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; -}; - -// 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 ); Toolkit::Control Control::New() { // Create the implementation, temporarily owned on stack - IntrusivePtr controlImpl = new Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ); + IntrusivePtr controlImpl = new Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ); // Pass ownership to handle Toolkit::Control handle( *controlImpl ); @@ -415,11 +147,6 @@ Toolkit::Control Control::New() return handle; } -Control::~Control() -{ - delete mImpl; -} - void Control::SetStyleName( const std::string& styleName ) { if( styleName != mImpl->mStyleName ) @@ -442,47 +169,42 @@ const std::string& Control::GetStyleName() const void Control::SetBackgroundColor( const Vector4& color ) { - Actor self( Self() ); mImpl->mBackgroundColor = color; Property::Map map; - map[ RENDERER_TYPE ] = COLOR_RENDERER; - map[ "mixColor" ] = color; - InitializeVisual( self, mImpl->mBackgroundRenderer, map ); - if( mImpl->mBackgroundRenderer ) + map[ Toolkit::Visual::Property::TYPE ] = Toolkit::Visual::COLOR; + map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color; + + int clippingMode = ClippingMode::DISABLED; + if( ( Self().GetProperty( Actor::Property::CLIPPING_MODE ).Get( clippingMode ) ) && + ( clippingMode == ClippingMode::CLIP_CHILDREN ) ) { - mImpl->mBackgroundRenderer.SetDepthIndex( DepthIndex::BACKGROUND ); + // If clipping-mode is set to CLIP_CHILDREN, then force visual to add the render even if transparent + map[ Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT ] = true; } -} -Vector4 Control::GetBackgroundColor() const -{ - return mImpl->mBackgroundColor; + SetBackground( map ); } void Control::SetBackground( const Property::Map& map ) { - Actor self( Self() ); - InitializeVisual( self, mImpl->mBackgroundRenderer, map ); - if( mImpl->mBackgroundRenderer ) + Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map ); + visual.SetName("background"); + if( visual ) { - mImpl->mBackgroundRenderer.SetDepthIndex( DepthIndex::BACKGROUND ); - } -} + mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND ); -void Control::SetBackgroundImage( Image image ) -{ - Actor self( Self() ); - InitializeVisual( self, mImpl->mBackgroundRenderer, image ); - if( mImpl->mBackgroundRenderer ) - { - mImpl->mBackgroundRenderer.SetDepthIndex( DepthIndex::BACKGROUND ); + // Trigger a size negotiation request that may be needed by the new visual to relayout its contents. + RelayoutRequest(); } } void Control::ClearBackground() { - Actor self( Self() ); - mImpl->mBackgroundRenderer.RemoveAndReset( self ); + mImpl->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) @@ -586,7 +308,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; } @@ -685,13 +411,15 @@ bool Control::EmitKeyEventSignal( const KeyEvent& event ) bool consumed = false; + consumed = mImpl->FilterKeyEvent( event ); + // signals are allocated dynamically when someone connects - if ( !mImpl->mKeyEventSignal.Empty() ) + if ( !consumed && !mImpl->mKeyEventSignal.Empty() ) { consumed = mImpl->mKeyEventSignal.Emit( handle, event ); } - if (!consumed) + if ( !consumed ) { // Notification for derived classes consumed = OnKeyEvent(event); @@ -707,12 +435,18 @@ 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. OnInitialize(); - if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS ) + if( (mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS) || + !(mImpl->mFlags & DISABLE_STYLE_CHANGE_SIGNALS) ) { Toolkit::StyleManager styleManager = StyleManager::Get(); @@ -753,6 +487,7 @@ void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Ty if( styleManager && change == StyleChange::THEME_CHANGE ) { GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); + RelayoutRequest(); } } @@ -808,20 +543,31 @@ void Control::EmitKeyInputFocusSignal( bool focusGained ) void Control::OnStageConnection( int depth ) { - if( mImpl->mBackgroundRenderer) + 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++) { - Actor self( Self() ); - mImpl->mBackgroundRenderer.SetOnStage( self ); + // 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 ); + Toolkit::GetImplementation((*iter)->visual).SetOnStage( self ); + } } + + // The clipping renderer is only created if required. + CreateClippingRenderer( *this ); + + // Request to be laid out when the control is connected to the Stage. + // Signal that a Relayout may be needed } + void Control::OnStageDisconnection() { - if( mImpl->mBackgroundRenderer ) - { - Actor self( Self() ); - mImpl->mBackgroundRenderer.SetOffStage( self ); - } + mImpl->OnStageDisconnection(); } void Control::OnKeyInputFocusGained() @@ -846,12 +592,24 @@ void Control::OnChildRemove(Actor& child) OnControlChildRemove( child ); } +void Control::OnPropertySet( Property::Index index, Property::Value propertyValue ) +{ + // If the clipping mode has been set, we may need to create a renderer. + // Only do this if we are already on-stage as the OnStageConnection will handle the off-stage clipping controls. + if( ( index == Actor::Property::CLIPPING_MODE ) && Self().OnStage() ) + { + // Note: This method will handle whether creation of the renderer is required. + CreateClippingRenderer( *this ); + } +} + void Control::OnSizeSet(const Vector3& targetSize) { - if( mImpl->mBackgroundRenderer ) + Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND ); + if( visual ) { Vector2 size( targetSize ); - mImpl->mBackgroundRenderer.SetSize( size ); + visual.SetTransformAndSize( Property::Map(), size ); // Send an empty map as we do not want to modify the visual's set transform } } @@ -884,7 +642,41 @@ void Control::OnRelayout( const Vector2& size, RelayoutContainer& container ) { for( unsigned int i = 0, numChildren = Self().GetChildCount(); i < numChildren; ++i ) { - container.Add( Self().GetChildAt( i ), size ); + Actor child = Self().GetChildAt( i ); + Vector2 newChildSize( size ); + + // When set the padding or margin on the control, child should be resized and repositioned. + if( ( mImpl->mPadding.start != 0 ) || ( mImpl->mPadding.end != 0 ) || ( mImpl->mPadding.top != 0 ) || ( mImpl->mPadding.bottom != 0 ) || + ( mImpl->mMargin.start != 0 ) || ( mImpl->mMargin.end != 0 ) || ( mImpl->mMargin.top != 0 ) || ( mImpl->mMargin.bottom != 0 ) ) + { + Extents padding = mImpl->mPadding; + + Dali::CustomActor ownerActor(GetOwner()); + Dali::LayoutDirection::Type layoutDirection = static_cast( ownerActor.GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get() ); + + if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection ) + { + std::swap( padding.start, padding.end ); + } + + newChildSize.width = size.width - ( padding.start + padding.end ); + newChildSize.height = size.height - ( padding.top + padding.bottom ); + + // Cannot use childs Position property as it can already have padding and margin applied on it, + // so we end up cumulatively applying them over and over again. + Vector2 childOffset( 0.f, 0.f ); + childOffset.x += ( mImpl->mMargin.start + padding.start ); + childOffset.y += ( mImpl->mMargin.top + padding.top ); + + child.SetPosition( childOffset.x, childOffset.y ); + } + container.Add( child, newChildSize ); + } + + Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND ); + if( visual ) + { + visual.SetTransformAndSize( Property::Map(), size ); // Send an empty map as we do not want to modify the visual's set transform } } @@ -894,11 +686,15 @@ void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dime Vector3 Control::GetNaturalSize() { - if( mImpl->mBackgroundRenderer ) + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::GetNaturalSize for %s\n", Self().GetName().c_str() ); + Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND ); + if( visual ) { Vector2 naturalSize; - mImpl->mBackgroundRenderer.GetNaturalSize(naturalSize); - return Vector3(naturalSize); + visual.GetNaturalSize( naturalSize ); + naturalSize.width += ( mImpl->mPadding.start + mImpl->mPadding.end ); + naturalSize.height += ( mImpl->mPadding.top + mImpl->mPadding.bottom ); + return Vector3( naturalSize ); } return Vector3::ZERO; }