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=c469d1c3e6898bde30b5eba3e20db85a97271000;hp=525a02eb113ded0b4d0190a9d012741927be725c;hb=1061baa5912952ac998c34584b1e2e5e030e0e5f;hpb=6fa08daf440e496896babb230e404aae7e77a5bb 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 525a02e..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) 2017 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. @@ -26,23 +26,23 @@ #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 namespace Dali @@ -61,49 +61,77 @@ namespace 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 ) - /** - * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter + * @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 */ -bool FindVisual( Property::Index targetIndex, RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter ) +void ChangeBackgroundColorVisual( Control& controlImpl, bool renderIfTransparent ) { - for ( iter = visuals.Begin(); iter != visuals.End(); iter++ ) + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl ); + + Toolkit::Visual::Base backgroundVisual = controlDataImpl.GetVisual( Toolkit::Control::Property::BACKGROUND ); + if( backgroundVisual ) { - if ( (*iter)->index == targetIndex ) + Property::Map map; + backgroundVisual.CreatePropertyMap( map ); + Property::Value* typeValue = map.Find( Toolkit::Visual::Property::TYPE ); + if( typeValue && typeValue->Get< int >() == Toolkit::Visual::COLOR ) { - return true; + // Only change it if it's a color visual + map[ Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT ] = renderIfTransparent; + controlImpl.SetBackground( map ); } } - return false; } -Toolkit::Visual::Base GetVisualByName( - RegisteredVisualContainer& visuals, - const std::string& visualName ) +/** + * @brief Creates a clipping renderer if required. + * (EG. If no renders exist and clipping is enabled). + * @param[in] controlImpl The control implementation. + */ +void CreateClippingRenderer( Control& controlImpl ) { - Toolkit::Visual::Base visualHandle; - - RegisteredVisualContainer::Iterator iter; - for ( iter = visuals.Begin(); iter != visuals.End(); iter++ ) + // 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 ) ) { - Toolkit::Visual::Base visual = (*iter)->visual; - if( visual && visual.GetName() == visualName ) + switch( clippingMode ) { - visualHandle = visual; - break; + case ClippingMode::CLIP_CHILDREN: + { + if( self.GetRendererCount() == 0u ) + { + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl ); + if( controlDataImpl.mVisuals.Empty() ) + { + controlImpl.SetBackgroundColor( Color::TRANSPARENT ); + } + else + { + // 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 ClippingMode::DISABLED: + case ClippingMode::CLIP_TO_BOUNDING_BOX: + { + // 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 visualHandle; } } // unnamed namespace - Toolkit::Control Control::New() { // Create the implementation, temporarily owned on stack @@ -143,43 +171,36 @@ void Control::SetBackgroundColor( const Vector4& color ) { mImpl->mBackgroundColor = color; Property::Map map; - map[ Toolkit::DevelVisual::Property::TYPE ] = Toolkit::Visual::COLOR; + map[ Toolkit::Visual::Property::TYPE ] = Toolkit::Visual::COLOR; map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color; - SetBackground( map ); -} + 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; + } -Vector4 Control::GetBackgroundColor() const -{ - return mImpl->mBackgroundColor; + SetBackground( map ); } void Control::SetBackground( const Property::Map& map ) { 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::SetBackgroundImage( Image image ) -{ - Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( image ); - if( visual ) - { - RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual ); - visual.SetDepthIndex( DepthIndex::BACKGROUND ); - } -} - void Control::ClearBackground() { - UnregisterVisual( Toolkit::Control::Property::BACKGROUND ); + mImpl->UnregisterVisual( Toolkit::Control::Property::BACKGROUND ); mImpl->mBackgroundColor = Color::TRANSPARENT; // Trigger a size negotiation request that may be needed when unregistering a visual. @@ -329,202 +350,6 @@ 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 ); - } - - mImpl->StopObservingVisual( (*iter)->visual ); - mImpl->StartObservingVisual( visual ); - - (*iter)->visual = visual; - visualReplaced = true; - } - } - - // 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 ) ); - - // monitor when the visuals resources are ready - mImpl->StartObservingVisual( visual ); - - } - - if( visual && self.OnStage() && enabled ) - { - 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 ) -{ - RegisteredVisualContainer::Iterator iter; - if ( FindVisual( index, mImpl->mVisuals, iter ) ) - { - // stop observing visual - mImpl->StopObservingVisual( (*iter)->visual ); - - 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 %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, 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 %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 %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. - } - } - } -} - -bool Control::IsVisualEnabled( Property::Index index ) const -{ - RegisteredVisualContainer::Iterator iter; - if ( FindVisual( index, mImpl->mVisuals, iter ) ) - { - return (*iter)->enabled; - } - 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); - - Toolkit::Visual::Base visual = GetVisualByName( mImpl->mVisuals, animator->objectName ); - - if( visual ) - { - Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual ); - visualImpl.AnimateProperty( transition, *animator ); - } - else - { - // Otherwise, try any actor children of control (Including the control) - Actor child = Self().FindChildByName( animator->objectName ); - if( child ) - { - Property::Index propertyIndex = DevelHandle::GetPropertyIndex( child, animator->propertyKey ); - if( propertyIndex != Property::INVALID_INDEX ) - { - 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 ) ); - } - } - } - } - } - } - - return transition; -} - bool Control::OnAccessibilityActivated() { return false; // Accessibility activation is not handled by default @@ -586,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); @@ -730,35 +557,17 @@ void Control::OnStageConnection( int depth ) } } - 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 + // The clipping renderer is only created if required. + CreateClippingRenderer( *this ); - if( clippingMode == ClippingMode::CLIP_CHILDREN ) - { - // Create a transparent background visual which will also get staged. - SetBackgroundColor( Color::TRANSPARENT ); - } - } - } + // Request to be laid out when the control is connected to the Stage. + // Signal that a Relayout may be needed } + void Control::OnStageDisconnection() { - for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++) - { - // 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->OnStageDisconnection(); } void Control::OnKeyInputFocusGained() @@ -785,30 +594,18 @@ void Control::OnChildRemove(Actor& child) void Control::OnPropertySet( Property::Index index, Property::Value propertyValue ) { - Actor self( Self() ); - if( index == Actor::Property::CLIPPING_MODE ) + // 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() ) { - // 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 ); - } - } - } + // Note: This method will handle whether creation of the renderer is required. + CreateClippingRenderer( *this ); } } void Control::OnSizeSet(const Vector3& targetSize) { - Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND ); + Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND ); if( visual ) { Vector2 size( targetSize ); @@ -845,10 +642,38 @@ 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 = GetVisual( Toolkit::Control::Property::BACKGROUND ); + 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 @@ -861,11 +686,14 @@ void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dime Vector3 Control::GetNaturalSize() { - Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND ); + 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; 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;