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=1fb9f44ef4da25a3047d24714678b6b9433b4492;hp=b71a080886513e44a21acd7de2f6a55a153a3dac;hb=2d49df397bf377d412321ff978bd90186d55ba6b;hpb=c6eb78824e08f7a863c55b3599d37b641c0313ba diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp index b71a080..684e695 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) 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. @@ -19,533 +19,125 @@ #include // EXTERNAL INCLUDES -#include // for strcmp -#include -#include +#include +#include #include -#include -#include #include -#include #include -#include -#include -#include -#include +#include // for strcmp +#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 +#include +#include +#include +#include +#include +#include +#include +#include namespace Dali { - namespace Toolkit { - +namespace Internal +{ 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 /** - * Struct used to store Visual within the control, index is a unique key for each visual. + * @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 */ -struct RegisteredVisual -{ - Property::Index index; - 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 ) - { - } -}; - - -typedef Dali::OwnerContainer< RegisteredVisual* > RegisteredVisualContainer; - -/** - * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter - */ -bool FindVisual( Property::Index targetIndex, RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter ) -{ - for ( iter = visuals.Begin(); iter != visuals.End(); iter++ ) - { - if ( (*iter)->index == targetIndex ) - { - return true; - } - } - return false; -} - -HandleIndex GetVisualProperty( - Internal::Control& controlImpl, - RegisteredVisualContainer& visuals, - const std::string& visualName, - Property::Key propertyKey ) +void ChangeBackgroundColorVisual(Control& controlImpl, bool renderIfTransparent) { -#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 + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(controlImpl); - // Find visualName in the control - RegisteredVisualContainer::Iterator iter; - for ( iter = visuals.Begin(); iter != visuals.End(); iter++ ) + Toolkit::Visual::Base backgroundVisual = controlDataImpl.GetVisual(Toolkit::Control::Property::BACKGROUND); + if(backgroundVisual && backgroundVisual.GetType() == Toolkit::Visual::COLOR) { - if ( (*iter)->visual.GetName() == visualName ) - { - break; - } - } + Property::Map map; + backgroundVisual.CreatePropertyMap(map); - // Does it's renderer have an associated property? - if( iter != visuals.End() ) - { - Actor self = controlImpl.Self(); - Property::Index index = DevelHandle::GetPropertyIndex( self, 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 = DevelHandle::GetPropertyIndex( renderer, 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() ); - } - } + // Only change it if it's a color visual + map[Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT] = renderIfTransparent; + controlImpl.SetBackground(map); } - Handle handle; - return HandleIndex( handle, Property::INVALID_INDEX ); -} - -void SetDefaultTransform( Property::Map& propertyMap ) -{ - propertyMap.Clear(); - propertyMap - .Add( Toolkit::DevelVisual::Transform::Property::OFFSET, Vector2(0.0f, 0.0f) ) - .Add( Toolkit::DevelVisual::Transform::Property::SIZE, Vector2(1.0f, 1.0f) ) - .Add( Toolkit::DevelVisual::Transform::Property::ORIGIN, Toolkit::Align::CENTER ) - .Add( Toolkit::DevelVisual::Transform::Property::ANCHOR_POINT, Toolkit::Align::CENTER ) - .Add( Toolkit::DevelVisual::Transform::Property::OFFSET_SIZE_MODE, Vector4::ZERO ); } /** - * Creates control through type registry + * @brief Creates a clipping renderer if required. + * (EG. If no renders exist and clipping is enabled). + * @param[in] controlImpl The control implementation. */ -BaseHandle Create() -{ - return Internal::Control::New(); -} - -/** - * 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 - */ -const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated"; -static bool DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes ) -{ - bool ret = false; - - if( object && ( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED ) ) ) - { - Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) ); - if( control ) - { - // if cast succeeds there is an implementation so no need to check - ret = Internal::GetImplementation( control ).OnAccessibilityActivated(); - } - } - - 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. - */ -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(""), - mBackgroundColor(Color::TRANSPARENT), - mStartingPinchScale( NULL ), - mKeyEventSignal(), - mPinchGestureDetector(), - mPanGestureDetector(), - mTapGestureDetector(), - mLongPressGestureDetector(), - mFlags( Control::ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ), - mIsKeyboardNavigationSupported( false ), - mIsKeyboardFocusGroup( false ) - { - } - - ~Impl() + // 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)) { - // 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) - { - 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: + if(self.GetRendererCount() == 0u) { - 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 + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(controlImpl); + if(controlDataImpl.mVisuals.Empty()) { - // An empty image means the background is no longer required - controlImpl.ClearBackground(); - } - break; - } - - case Toolkit::Control::Property::KEY_INPUT_FOCUS: - { - if ( value.Get< bool >() ) - { - controlImpl.SetKeyInputFocus(); + controlImpl.SetBackgroundColor(Color::TRANSPARENT); } else { - controlImpl.ClearKeyInputFocus(); + // 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; - } - - case Toolkit::Control::Property::BACKGROUND: - { - std::string url; - 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 - { - // The background is an empty property map, so we should clear the background - controlImpl.ClearBackground(); - } - 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; - Toolkit::Visual::Base visual = controlImpl.GetVisual( Toolkit::Control::Property::BACKGROUND ); - if( visual ) - { - visual.CreatePropertyMap( map ); - } - value = map; - break; - } - - case Toolkit::Control::Property::KEY_INPUT_FOCUS: - { - value = controlImpl.HasKeyInputFocus(); - break; - } - - case Toolkit::Control::Property::BACKGROUND: - { - Property::Map map; - Toolkit::Visual::Base visual = controlImpl.GetVisual( Toolkit::Control::Property::BACKGROUND ); - if( visual ) - { - visual.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; } +} - // Data - - Control& mControlImpl; - 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 - 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 ); +} // unnamed namespace Toolkit::Control Control::New() { // Create the implementation, temporarily owned on stack - IntrusivePtr controlImpl = new Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ); + IntrusivePtr controlImpl = new Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)); // Pass ownership to handle - Toolkit::Control handle( *controlImpl ); + Toolkit::Control handle(*controlImpl); // Second-phase init of the implementation // This can only be done after the CustomActor connection has been made... @@ -554,17 +146,17 @@ Toolkit::Control Control::New() return handle; } -void Control::SetStyleName( const std::string& styleName ) +void Control::SetStyleName(const std::string& styleName) { - if( styleName != mImpl->mStyleName ) + if(styleName != mImpl->mStyleName) { mImpl->mStyleName = styleName; // Apply new style, if stylemanager is available Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get(); - if( styleManager ) + if(styleManager) { - GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); + GetImpl(styleManager).ApplyThemeStyle(Toolkit::Control(GetOwner())); } } } @@ -574,78 +166,93 @@ const std::string& Control::GetStyleName() const return mImpl->mStyleName; } -void Control::SetBackgroundColor( const Vector4& color ) +void Control::SetBackgroundColor(const Vector4& color) { mImpl->mBackgroundColor = color; - Property::Map map; - map[ Toolkit::DevelVisual::Property::TYPE ] = Toolkit::Visual::COLOR; - map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color; - SetBackground( map ); -} + Property::Map map; + map[Toolkit::Visual::Property::TYPE] = Toolkit::Visual::COLOR; + map[Toolkit::ColorVisual::Property::MIX_COLOR] = color; -Vector4 Control::GetBackgroundColor() const -{ - return mImpl->mBackgroundColor; -} + bool renderIfTransparent = false; + int clippingMode = ClippingMode::DISABLED; + if((Self().GetProperty(Actor::Property::CLIPPING_MODE).Get(clippingMode)) && + (clippingMode == ClippingMode::CLIP_CHILDREN)) + { + // 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; + renderIfTransparent = true; + } -void Control::SetBackground( const Property::Map& map ) -{ - Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map ); - if( visual ) + Toolkit::Visual::Base visual = mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND); + if(visual && visual.GetType() == Toolkit::Visual::COLOR) { - RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual ); - visual.SetDepthIndex( DepthIndex::BACKGROUND ); + Property::Map visualMap; + visual.CreatePropertyMap(visualMap); - // Trigger a size negotiation request that may be needed by the new visual to relayout its contents. - RelayoutRequest(); + Property::Value* renderValue = visualMap.Find(Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT); + Property::Value* colorValue = visualMap.Find(Toolkit::ColorVisual::Property::MIX_COLOR); + if(renderValue && colorValue) + { + if((renderValue->Get() == true || colorValue->Get().a > 0.0f) && (renderIfTransparent || color.a > 0.0f)) + { + // Update background color only + mImpl->DoAction(Toolkit::Control::Property::BACKGROUND, DevelColorVisual::Action::UPDATE_PROPERTY, map); + return; + } + } } + + SetBackground(map); } -void Control::SetBackgroundImage( Image image ) +void Control::SetBackground(const Property::Map& map) { - 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 ) + Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(map); + visual.SetName("background"); + if(visual) { - RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual ); - visual.SetDepthIndex( DepthIndex::BACKGROUND ); + mImpl->RegisterVisual(Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND); + + // Trigger a size negotiation request that may be needed by the new visual to relayout its contents. + RelayoutRequest(); } } void Control::ClearBackground() { - UnregisterVisual( Toolkit::Control::Property::BACKGROUND ); - mImpl->mBackgroundColor = Color::TRANSPARENT; + mImpl->UnregisterVisual(Toolkit::Control::Property::BACKGROUND); + mImpl->mBackgroundColor = Color::TRANSPARENT; - // Trigger a size negotiation request that may be needed when unregistering a visual. - RelayoutRequest(); + // Trigger a size negotiation request that may be needed when unregistering a visual. + RelayoutRequest(); } -void Control::EnableGestureDetection(Gesture::Type type) +void Control::EnableGestureDetection(GestureType::Value type) { - if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector ) + if((type & GestureType::PINCH) && !mImpl->mPinchGestureDetector) { mImpl->mPinchGestureDetector = PinchGestureDetector::New(); mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected); mImpl->mPinchGestureDetector.Attach(Self()); } - if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector ) + if((type & GestureType::PAN) && !mImpl->mPanGestureDetector) { mImpl->mPanGestureDetector = PanGestureDetector::New(); + mImpl->mPanGestureDetector.SetMaximumTouchesRequired(2); mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected); mImpl->mPanGestureDetector.Attach(Self()); } - if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector ) + if((type & GestureType::TAP) && !mImpl->mTapGestureDetector) { mImpl->mTapGestureDetector = TapGestureDetector::New(); mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected); mImpl->mTapGestureDetector.Attach(Self()); } - if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector ) + if((type & GestureType::LONG_PRESS) && !mImpl->mLongPressGestureDetector) { mImpl->mLongPressGestureDetector = LongPressGestureDetector::New(); mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected); @@ -653,27 +260,27 @@ void Control::EnableGestureDetection(Gesture::Type type) } } -void Control::DisableGestureDetection(Gesture::Type type) +void Control::DisableGestureDetection(GestureType::Value type) { - if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector ) + if((type & GestureType::PINCH) && mImpl->mPinchGestureDetector) { mImpl->mPinchGestureDetector.Detach(Self()); mImpl->mPinchGestureDetector.Reset(); } - if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector ) + if((type & GestureType::PAN) && mImpl->mPanGestureDetector) { mImpl->mPanGestureDetector.Detach(Self()); mImpl->mPanGestureDetector.Reset(); } - if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector ) + if((type & GestureType::TAP) && mImpl->mTapGestureDetector) { mImpl->mTapGestureDetector.Detach(Self()); mImpl->mTapGestureDetector.Reset(); } - if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector) + if((type & GestureType::LONG_PRESS) && mImpl->mLongPressGestureDetector) { mImpl->mLongPressGestureDetector.Detach(Self()); mImpl->mLongPressGestureDetector.Reset(); @@ -712,7 +319,7 @@ bool Control::IsKeyboardNavigationSupported() void Control::SetKeyInputFocus() { - if( Self().OnStage() ) + if(Self().GetProperty(Actor::Property::CONNECTED_TO_SCENE)) { Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self())); } @@ -721,16 +328,20 @@ void Control::SetKeyInputFocus() bool Control::HasKeyInputFocus() { bool result = false; - if( Self().OnStage() ) + if(Self().GetProperty(Actor::Property::CONNECTED_TO_SCENE)) { - result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self())); + Toolkit::Control control = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl(); + if(Self() == control) + { + result = true; + } } return result; } void Control::ClearKeyInputFocus() { - if( Self().OnStage() ) + if(Self().GetProperty(Actor::Property::CONNECTED_TO_SCENE)) { Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self())); } @@ -761,174 +372,15 @@ void Control::KeyboardEnter() OnKeyboardEnter(); } -void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual ) -{ - RegisterVisual( index, visual, true ); -} - -void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled ) -{ - bool visualReplaced ( false ); - Actor self = Self(); - - if( !mImpl->mVisuals.Empty() ) - { - RegisteredVisualContainer::Iterator iter; - // Check if visual (index) is already registered. Replace if so. - if ( FindVisual( index, mImpl->mVisuals, iter ) ) - { - if( (*iter)->visual && self.OnStage() ) - { - Toolkit::GetImplementation((*iter)->visual).SetOffStage( self ); - } - (*iter)->visual = visual; - visualReplaced = true; - } - } - - if( !visualReplaced ) // New registration entry - { - mImpl->mVisuals.PushBack( new RegisteredVisual( index, visual, enabled ) ); - } - - if( visual && self.OnStage() && enabled ) - { - Toolkit::GetImplementation(visual).SetOnStage( self ); - } -} - -void Control::UnregisterVisual( Property::Index index ) -{ - RegisteredVisualContainer::Iterator iter; - if ( FindVisual( index, mImpl->mVisuals, iter ) ) - { - Actor self( Self() ); - Toolkit::GetImplementation((*iter)->visual).SetOffStage( self ); - (*iter)->visual.Reset(); - mImpl->mVisuals.Erase( iter ); - } -} - -Toolkit::Visual::Base Control::GetVisual( Property::Index index ) const -{ - RegisteredVisualContainer::Iterator iter; - if ( FindVisual( index, mImpl->mVisuals, iter ) ) - { - return (*iter)->visual; - } - - return Toolkit::Visual::Base(); -} - -void Control::EnableVisual( Property::Index index, bool enable ) -{ - RegisteredVisualContainer::Iterator iter; - if ( FindVisual( index, mImpl->mVisuals, iter ) ) - { - if ( (*iter)->enabled == enable ) - { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual Already enabled set (%s) \n", enable?"enabled":"disabled"); - return; - } - - (*iter)->enabled = enable; - Actor parentActor = Self(); - if ( Self().OnStage() ) // If control not on Stage then Visual will be added when StageConnection is called. - { - if ( enable ) - { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting Visual(%d) on stage \n", index ); - Toolkit::GetImplementation((*iter)->visual).SetOnStage( parentActor ); - } - else - { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting Visual(%d) off stage \n", index ); - Toolkit::GetImplementation((*iter)->visual).SetOffStage( parentActor ); // No need to call if control not staged. - } - } - } -} - -bool Control::IsVisualEnabled( Property::Index index ) const +bool Control::OnAccessibilityActivated() { - RegisteredVisualContainer::Iterator iter; - if ( FindVisual( index, mImpl->mVisuals, iter ) ) + if( Toolkit::KeyboardFocusManager::Get().SetCurrentFocusActor( Self() ) ) { - return (*iter)->enabled; + return OnKeyboardEnter(); } return false; } -Dali::Animation Control::CreateTransition( const Toolkit::TransitionData& handle ) -{ - Dali::Animation transition; - const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle ); - - if( transitionData.Count() > 0 ) - { - // Setup a Transition from TransitionData. - TransitionData::Iterator end = transitionData.End(); - for( TransitionData::Iterator iter = transitionData.Begin() ; - 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 ) - { - Property::Index propertyIndex = DevelHandle::GetPropertyIndex( child, animator->propertyKey ); - handleIndex = HandleIndex( child, propertyIndex ); - } - else - { - handleIndex = GetVisualProperty( *this, mImpl->mVisuals, - animator->objectName, - animator->propertyKey ); - } - - if( handleIndex.handle && handleIndex.index != Property::INVALID_INDEX ) - { - if( animator->animate == false ) - { - if( animator->targetValue.GetType() != Property::NONE ) - { - handleIndex.handle.SetProperty( handleIndex.index, animator->targetValue ); - } - } - 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 ) ); - } - } - } - } - - return transition; -} - -bool Control::OnAccessibilityActivated() -{ - return false; // Accessibility activation is not handled by default -} - bool Control::OnKeyboardEnter() { return false; // Keyboard enter is not handled by default @@ -939,11 +391,6 @@ bool Control::OnAccessibilityPan(PanGesture gesture) return false; // Accessibility pan gesture is not handled by default } -bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent) -{ - return false; // Accessibility touch event is not handled by default -} - bool Control::OnAccessibilityValueChange(bool isIncrease) { return false; // Accessibility value change action is not handled by default @@ -978,20 +425,22 @@ Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusLostSignal() return mImpl->mKeyInputFocusLostSignal; } -bool Control::EmitKeyEventSignal( const KeyEvent& event ) +bool Control::EmitKeyEventSignal(const KeyEvent& event) { // Guard against destruction during signal emission - Dali::Toolkit::Control handle( GetOwner() ); + Dali::Toolkit::Control handle(GetOwner()); 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 ); + consumed = mImpl->mKeyEventSignal.Emit(handle, event); } - if (!consumed) + if(!consumed) { // Notification for derived classes consumed = OnKeyEvent(event); @@ -1000,8 +449,8 @@ bool Control::EmitKeyEventSignal( const KeyEvent& event ) return consumed; } -Control::Control( ControlBehaviour behaviourFlags ) -: CustomActorImpl( static_cast< ActorFlags >( behaviourFlags ) ), +Control::Control(ControlBehaviour behaviourFlags) +: CustomActorImpl(static_cast(behaviourFlags)), mImpl(new Impl(*this)) { mImpl->mFlags = behaviourFlags; @@ -1017,69 +466,71 @@ void Control::Initialize() // Call deriving classes so initialised before styling is applied to them. OnInitialize(); - if( (mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS) || - !(mImpl->mFlags & DISABLE_STYLE_CHANGE_SIGNALS) ) + if(!(mImpl->mFlags & DISABLE_STYLE_CHANGE_SIGNALS)) { Toolkit::StyleManager styleManager = StyleManager::Get(); // if stylemanager is available - if( styleManager ) + if(styleManager) { - StyleManager& styleManagerImpl = GetImpl( styleManager ); + StyleManager& styleManagerImpl = GetImpl(styleManager); // Register for style changes - styleManagerImpl.ControlStyleChangeSignal().Connect( this, &Control::OnStyleChange ); + styleManagerImpl.ControlStyleChangeSignal().Connect(this, &Control::OnStyleChange); // Apply the current style - styleManagerImpl.ApplyThemeStyleAtInit( Toolkit::Control( GetOwner() ) ); + styleManagerImpl.ApplyThemeStyleAtInit(Toolkit::Control(GetOwner())); } } - if( mImpl->mFlags & REQUIRES_KEYBOARD_NAVIGATION_SUPPORT ) + if(mImpl->mFlags & REQUIRES_KEYBOARD_NAVIGATION_SUPPORT) { - SetKeyboardNavigationSupport( true ); + SetKeyboardNavigationSupport(true); } -} -void Control::OnInitialize() -{ -} + Dali::TypeInfo type; + Self().GetTypeInfo( type ); + if (type) + { + auto typeName = type.GetName(); + DevelControl::AppendAccessibilityAttribute( Self(), "t", typeName ); + } -void Control::OnControlChildAdd( Actor& child ) -{ + if (Accessibility::IsUp()) + mImpl->AccessibilityRegister(); } -void Control::OnControlChildRemove( Actor& child ) +void Control::OnInitialize() { } -void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change ) +void Control::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change) { // By default the control is only interested in theme (not font) changes - if( styleManager && change == StyleChange::THEME_CHANGE ) + if(styleManager && change == StyleChange::THEME_CHANGE) { - GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); + GetImpl(styleManager).ApplyThemeStyle(Toolkit::Control(GetOwner())); + RelayoutRequest(); } - RelayoutRequest(); } void Control::OnPinch(const PinchGesture& pinch) { - if( !( mImpl->mStartingPinchScale ) ) + if(!(mImpl->mStartingPinchScale)) { // lazy allocate mImpl->mStartingPinchScale = new Vector3; } - if( pinch.state == Gesture::Started ) + if(pinch.GetState() == GestureState::STARTED) { - *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale(); + *(mImpl->mStartingPinchScale) = Self().GetCurrentProperty(Actor::Property::SCALE); } - Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale ); + Self().SetProperty(Actor::Property::SCALE, *(mImpl->mStartingPinchScale) * pinch.GetScale()); } -void Control::OnPan( const PanGesture& pan ) +void Control::OnPan(const PanGesture& pan) { } @@ -1087,93 +538,154 @@ void Control::OnTap(const TapGesture& tap) { } -void Control::OnLongPress( const LongPressGesture& longPress ) +void Control::OnLongPress(const LongPressGesture& longPress) { } -void Control::EmitKeyInputFocusSignal( bool focusGained ) +void Control::EmitKeyInputFocusSignal(bool focusGained) { - Dali::Toolkit::Control handle( GetOwner() ); + Dali::Toolkit::Control handle(GetOwner()); - if ( focusGained ) + if( Accessibility::IsUp() ) + { + auto self = mImpl->GetAccessibilityObject( Self() ); + self->EmitFocused( focusGained ); + auto parent = self->GetParent(); + if( parent && !self->GetStates()[Dali::Accessibility::State::MANAGES_DESCENDANTS] ) + { + parent->EmitActiveDescendantChanged( parent, self ); + } + } + + if(focusGained) { // signals are allocated dynamically when someone connects - if ( !mImpl->mKeyInputFocusGainedSignal.Empty() ) + if(!mImpl->mKeyInputFocusGainedSignal.Empty()) { - mImpl->mKeyInputFocusGainedSignal.Emit( handle ); + mImpl->mKeyInputFocusGainedSignal.Emit(handle); } } else { // signals are allocated dynamically when someone connects - if ( !mImpl->mKeyInputFocusLostSignal.Empty() ) + if(!mImpl->mKeyInputFocusLostSignal.Empty()) { - mImpl->mKeyInputFocusLostSignal.Emit( handle ); + mImpl->mKeyInputFocusLostSignal.Emit(handle); } } } -void Control::OnStageConnection( int depth ) +void Control::OnSceneConnection(int depth) { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection number of registered visuals(%d)\n", mImpl->mVisuals.Size() ); + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::OnSceneConnection number of registered visuals(%d)\n", mImpl->mVisuals.Size()); - for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++) + 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 ) + 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 ); + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::OnSceneConnection Setting visual(%d) on scene\n", (*iter)->index); + Toolkit::GetImplementation((*iter)->visual).SetOnScene(self); } } + + // The clipping renderer is only created if required. + CreateClippingRenderer(*this); + + // Request to be laid out when the control is connected to the Scene. + // Signal that a Relayout may be needed + if( Accessibility::IsUp() ) + { + mImpl->AccessibilityRegister(); + } } -void Control::OnStageDisconnection() +void Control::OnSceneDisconnection() { - for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++) + if( Accessibility::IsUp() ) { - // Check whether the visual is empty - if( (*iter)->visual ) - { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageDisconnection Setting visual(%d) off stage\n", (*iter)->index ); - Actor self( Self() ); - Toolkit::GetImplementation((*iter)->visual).SetOffStage( self ); - } + mImpl->AccessibilityDeregister(); } + mImpl->OnSceneDisconnection(); } void Control::OnKeyInputFocusGained() { - EmitKeyInputFocusSignal( true ); + EmitKeyInputFocusSignal(true); } void Control::OnKeyInputFocusLost() { - EmitKeyInputFocusSignal( false ); + EmitKeyInputFocusSignal(false); } void Control::OnChildAdd(Actor& child) { - // Notify derived classes. - OnControlChildAdd( child ); } void Control::OnChildRemove(Actor& child) { - // Notify derived classes. - OnControlChildRemove( child ); +} + +void Control::OnPropertySet(Property::Index index, const 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 OnSceneConnection will handle the off-stage clipping controls. + switch( index ) + { + case Actor::Property::CLIPPING_MODE: + { + if( Self().GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE )) + { + // Note: This method will handle whether creation of the renderer is required. + CreateClippingRenderer( *this ); + } + break; + } + case Actor::Property::VISIBLE: + { + if( Dali::Accessibility::IsUp() ) + { + Dali::Accessibility::Accessible::Get(Self())->EmitVisible( Self().GetProperty( Actor::Property::VISIBLE ).Get() ); + } + break; + } + case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME: + { + if( Dali::Accessibility::IsUp() ) + { + Dali::Accessibility::Accessible::Get(Self())->Emit( Dali::Accessibility::ObjectPropertyChangeEvent::NAME ); + } + break; + } + case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE: + { + if( Dali::Accessibility::IsUp() ) + { + Dali::Accessibility::Accessible::Get(Self())->Emit( Dali::Accessibility::ObjectPropertyChangeEvent::ROLE ); + } + break; + } + case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION: + { + if( Dali::Accessibility::IsUp() ) + { + Dali::Accessibility::Accessible::Get(Self())->Emit( Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION ); + } + break; + } + } } void Control::OnSizeSet(const Vector3& targetSize) { - Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND ); - if( visual ) + Toolkit::Visual::Base visual = mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND); + if(visual) { - Vector2 size( targetSize ); - Property::Map transformMap; - SetDefaultTransform( transformMap ); - visual.SetTransformAndSize( transformMap, size ); + Vector2 size(targetSize); + visual.SetTransformAndSize(Property::Map(), size); // Send an empty map as we do not want to modify the visual's set transform } } @@ -1182,110 +694,123 @@ void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize) // @todo size negotiate background to new size, animate as well? } -bool Control::OnTouchEvent(const TouchEvent& event) +bool Control::OnKeyEvent(const KeyEvent& event) { return false; // Do not consume } -bool Control::OnHoverEvent(const HoverEvent& event) +void Control::OnRelayout(const Vector2& size, RelayoutContainer& container) { - return false; // Do not consume -} + for(unsigned int i = 0, numChildren = Self().GetChildCount(); i < numChildren; ++i) + { + Actor child = Self().GetChildAt(i); + Vector2 newChildSize(size); -bool Control::OnKeyEvent(const KeyEvent& event) -{ - return false; // Do not consume -} + // 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; -bool Control::OnWheelEvent(const WheelEvent& event) -{ - return false; // Do not consume -} + Dali::CustomActor ownerActor(GetOwner()); + Dali::LayoutDirection::Type layoutDirection = static_cast(ownerActor.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get()); -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 ); + 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.SetProperty(Actor::Property::POSITION, Vector2(childOffset.x, childOffset.y)); + } + container.Add(child, newChildSize); } - Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND ); - if( visual ) + Toolkit::Visual::Base visual = mImpl->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 } } -void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) +void Control::OnSetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension) { } Vector3 Control::GetNaturalSize() { - Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND ); - if( visual ) + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::GetNaturalSize for %s\n", Self().GetProperty(Dali::Actor::Property::NAME).c_str()); + Toolkit::Visual::Base visual = mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND); + if(visual) { Vector2 naturalSize; - visual.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; } -float Control::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension ) +float Control::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension) { - return CalculateChildSizeBase( child, dimension ); + return CalculateChildSizeBase(child, dimension); } -float Control::GetHeightForWidth( float width ) +float Control::GetHeightForWidth(float width) { - return GetHeightForWidthBase( width ); + return GetHeightForWidthBase(width); } -float Control::GetWidthForHeight( float height ) +float Control::GetWidthForHeight(float height) { - return GetWidthForHeightBase( height ); + return GetWidthForHeightBase(height); } -bool Control::RelayoutDependentOnChildren( Dimension::Type dimension ) +bool Control::RelayoutDependentOnChildren(Dimension::Type dimension) { - return RelayoutDependentOnChildrenBase( dimension ); + return RelayoutDependentOnChildrenBase(dimension); } -void Control::OnCalculateRelayoutSize( Dimension::Type dimension ) +void Control::OnCalculateRelayoutSize(Dimension::Type dimension) { } -void Control::OnLayoutNegotiated( float size, Dimension::Type dimension ) +void Control::OnLayoutNegotiated(float size, Dimension::Type dimension) { } -void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback ) +void Control::SignalConnected(SlotObserver* slotObserver, CallbackBase* callback) { - mImpl->SignalConnected( slotObserver, callback ); + mImpl->SignalConnected(slotObserver, callback); } -void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback ) +void Control::SignalDisconnected(SlotObserver* slotObserver, CallbackBase* callback) { - mImpl->SignalDisconnected( slotObserver, callback ); + mImpl->SignalDisconnected(slotObserver, callback); } -Control& GetImplementation( Dali::Toolkit::Control& handle ) +Control& GetImplementation(Dali::Toolkit::Control& handle) { CustomActorImpl& customInterface = handle.GetImplementation(); // downcast to control - Control& impl = dynamic_cast< Internal::Control& >( customInterface ); + Control& impl = dynamic_cast(customInterface); return impl; } -const Control& GetImplementation( const Dali::Toolkit::Control& handle ) +const Control& GetImplementation(const Dali::Toolkit::Control& handle) { const CustomActorImpl& customInterface = handle.GetImplementation(); // downcast to control - const Control& impl = dynamic_cast< const Internal::Control& >( customInterface ); + const Control& impl = dynamic_cast(customInterface); return impl; }