From: Adeel Kazmi Date: Tue, 1 Dec 2020 18:34:58 +0000 (+0000) Subject: Refactored Internal::Actor by moving some methods into the Relayouter X-Git-Tag: dali_2.0.4~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a87ef7daf42dd1195046228a3b558e9fc0e49453;p=platform%2Fcore%2Fuifw%2Fdali-core.git Refactored Internal::Actor by moving some methods into the Relayouter This reduces the LOC for Actor Change-Id: I02201d933ca315581765ea91d8e5ea191201499f --- diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp index bd47582..96e5a67 100755 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -57,7 +57,6 @@ using Dali::Internal::SceneGraph::PropertyBase; #if defined(DEBUG_ENABLED) Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" ); -Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" ); #endif namespace Dali @@ -2268,98 +2267,6 @@ float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSiz return 0.0f; // Default } -void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack ) -{ - // Check if it needs to be negotiated - if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) ) - { - // Check that we havn't gotten into an infinite loop - ActorDimensionPair searchActor = ActorDimensionPair( this, dimension ); - bool recursionFound = false; - for( auto& element : recursionStack ) - { - if( element == searchActor ) - { - recursionFound = true; - break; - } - } - - if( !recursionFound ) - { - // Record the path that we have taken - recursionStack.push_back( ActorDimensionPair( this, dimension ) ); - - // Dimension dependency check - for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) - { - Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i ); - - if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) ) - { - NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack ); - } - } - - // Parent dependency check - Actor* parent = GetParent(); - if( parent && RelayoutDependentOnParent( dimension ) ) - { - parent->NegotiateDimension( dimension, allocatedSize, recursionStack ); - } - - // Children dependency check - if( RelayoutDependentOnChildren( dimension ) ) - { - for( uint32_t i = 0, count = GetChildCount(); i < count; ++i ) - { - ActorPtr child = GetChildAt( i ); - - // Only relayout child first if it is not dependent on this actor - if( !child->RelayoutDependentOnParent( dimension ) ) - { - child->NegotiateDimension( dimension, allocatedSize, recursionStack ); - } - } - } - - // For deriving classes - OnCalculateRelayoutSize( dimension ); - - // All dependencies checked, calculate the size and set negotiated flag - const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension ); - - SetNegotiatedDimension( newSize, dimension ); - SetLayoutNegotiated( true, dimension ); - - // For deriving classes - OnLayoutNegotiated( newSize, dimension ); - - // This actor has been successfully processed, pop it off the recursion stack - recursionStack.pop_back(); - } - else - { - // TODO: Break infinite loop - SetLayoutNegotiated( true, dimension ); - } - } -} - -void Actor::NegotiateDimensions( const Vector2& allocatedSize ) -{ - // Negotiate all dimensions that require it - ActorDimensionStack recursionStack; - - for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) - { - const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i ); - - // Negotiate - NegotiateDimension( dimension, allocatedSize, recursionStack ); - } -} - Vector2 Actor::ApplySizeSetPolicy( const Vector2& size ) { return mRelayoutData->ApplySizeSetPolicy(*this, size); @@ -2393,56 +2300,7 @@ void Actor::SetNegotiatedSize( RelayoutContainer& container ) void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container ) { - // Force a size negotiation for actors that has assigned size during relayout - // This is required as otherwise the flags that force a relayout will not - // necessarilly be set. This will occur if the actor has already been laid out. - // The dirty flags are then cleared. Then if the actor is added back into the - // relayout container afterwards, the dirty flags would still be clear... - // causing a relayout to be skipped. Here we force any actors added to the - // container to be relayed out. - DALI_LOG_TIMER_START( NegSizeTimer1 ); - - if( GetUseAssignedSize(Dimension::WIDTH ) ) - { - SetLayoutNegotiated( false, Dimension::WIDTH ); - } - if( GetUseAssignedSize( Dimension::HEIGHT ) ) - { - SetLayoutNegotiated( false, Dimension::HEIGHT ); - } - - // Do the negotiation - NegotiateDimensions( allocatedSize ); - - // Set the actor size - SetNegotiatedSize( container ); - - // Negotiate down to children - for( uint32_t i = 0, count = GetChildCount(); i < count; ++i ) - { - ActorPtr child = GetChildAt( i ); - - // Forces children that have already been laid out to be relayed out - // if they have assigned size during relayout. - if( child->GetUseAssignedSize(Dimension::WIDTH) ) - { - child->SetLayoutNegotiated(false, Dimension::WIDTH); - child->SetLayoutDirty(true, Dimension::WIDTH); - } - - if( child->GetUseAssignedSize(Dimension::HEIGHT) ) - { - child->SetLayoutNegotiated(false, Dimension::HEIGHT); - child->SetLayoutDirty(true, Dimension::HEIGHT); - } - - // Only relayout if required - if( child->RelayoutRequired() ) - { - container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() ); - } - } - DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: "); + Relayouter::NegotiateSize(*this, allocatedSize, container); } void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension ) @@ -2470,27 +2328,7 @@ void Actor::RelayoutRequest( Dimension::Type dimension ) void Actor::SetPreferredSize( const Vector2& size ) { - EnsureRelayouter(); - - // If valid width or height, then set the resize policy to FIXED - // A 0 width or height may also be required so if the resize policy has not been changed, i.e. is still set to DEFAULT, - // then change to FIXED as well - - if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT ) - { - SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH ); - } - - if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT ) - { - SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT ); - } - - mRelayoutData->preferredSize = size; - - mUseAnimatedSize = AnimatedSizeFlag::CLEAR; - - RelayoutRequest(); + EnsureRelayouter().SetPreferredSize(*this, size); } Vector2 Actor::GetPreferredSize() const diff --git a/dali/internal/event/actors/actor-impl.h b/dali/internal/event/actors/actor-impl.h index 249de1f..b80c212 100755 --- a/dali/internal/event/actors/actor-impl.h +++ b/dali/internal/event/actors/actor-impl.h @@ -1004,28 +1004,6 @@ public: bool RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension ); /** - * Negotiate sizes for a control in all dimensions - * - * @param[in] allocatedSize The size constraint that the control must respect - */ - void NegotiateDimensions( const Vector2& allocatedSize ); - - /** - * Negotiate size for a specific dimension - * - * The algorithm adopts a recursive dependency checking approach. Meaning, that wherever dependencies - * are found, e.g. an actor dependent on its parent, the dependency will be calculated first with NegotiatedDimension and - * LayoutDimensionNegotiated flags being filled in on the actor. - * - * @post All actors that exist in the dependency chain connected to the given actor will have had their NegotiatedDimensions - * calculated and set as well as the LayoutDimensionNegotiated flags. - * - * @param[in] dimension The dimension to negotiate on - * @param[in] allocatedSize The size constraint that the actor must respect - */ - void NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack ); - - /** * @brief Calculate the size of a dimension * * @param[in] dimension The dimension to calculate the size for diff --git a/dali/internal/event/actors/actor-relayouter.cpp b/dali/internal/event/actors/actor-relayouter.cpp index 5348273..0e1fcf3 100644 --- a/dali/internal/event/actors/actor-relayouter.cpp +++ b/dali/internal/event/actors/actor-relayouter.cpp @@ -23,6 +23,13 @@ #include #include +namespace +{ +#if defined(DEBUG_ENABLED) +Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" ); +#endif +} // unnamed namespace + namespace Dali { @@ -363,6 +370,29 @@ bool Actor::Relayouter::IsLayoutDirty( Dimension::Type dimension ) const return false; } +void Actor::Relayouter::SetPreferredSize( Actor& actor, const Vector2& size ) +{ + // If valid width or height, then set the resize policy to FIXED + // A 0 width or height may also be required so if the resize policy has not been changed, i.e. is still set to DEFAULT, + // then change to FIXED as well + + if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT ) + { + actor.SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH ); + } + + if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT ) + { + actor.SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT ); + } + + actor.mRelayoutData->preferredSize = size; + + actor.mUseAnimatedSize = AnimatedSizeFlag::CLEAR; + + actor.RelayoutRequest(); +} + float Actor::Relayouter::ClampDimension( const Internal::Actor& actor, float size, Dimension::Type dimension ) { const float minSize = actor.GetMinimumSize( dimension ); @@ -371,6 +401,152 @@ float Actor::Relayouter::ClampDimension( const Internal::Actor& actor, float siz return std::max( minSize, std::min( size, maxSize ) ); } +void Actor::Relayouter::NegotiateDimension( Actor& actor, Dimension::Type dimension, const Vector2& allocatedSize, Actor::ActorDimensionStack& recursionStack ) +{ + // Check if it needs to be negotiated + if( actor.IsLayoutDirty( dimension ) && !actor.IsLayoutNegotiated( dimension ) ) + { + // Check that we havn't gotten into an infinite loop + Actor::ActorDimensionPair searchActor = Actor::ActorDimensionPair( &actor, dimension ); + bool recursionFound = false; + for( auto& element : recursionStack ) + { + if( element == searchActor ) + { + recursionFound = true; + break; + } + } + + if( !recursionFound ) + { + // Record the path that we have taken + recursionStack.push_back( Actor::ActorDimensionPair( &actor, dimension ) ); + + // Dimension dependency check + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i ); + + if( actor.RelayoutDependentOnDimension( dimension, dimensionToCheck ) ) + { + NegotiateDimension( actor, dimensionToCheck, allocatedSize, recursionStack ); + } + } + + // Parent dependency check + Actor* parent = actor.GetParent(); + if( parent && actor.RelayoutDependentOnParent( dimension ) ) + { + NegotiateDimension( *parent, dimension, allocatedSize, recursionStack ); + } + + // Children dependency check + if( actor.RelayoutDependentOnChildren( dimension ) ) + { + for( uint32_t i = 0, count = actor.GetChildCount(); i < count; ++i ) + { + ActorPtr child = actor.GetChildAt( i ); + + // Only relayout child first if it is not dependent on this actor + if( !child->RelayoutDependentOnParent( dimension ) ) + { + NegotiateDimension( *child, dimension, allocatedSize, recursionStack ); + } + } + } + + // For deriving classes + actor.OnCalculateRelayoutSize( dimension ); + + // All dependencies checked, calculate the size and set negotiated flag + const float newSize = ClampDimension( actor, actor.CalculateSize( dimension, allocatedSize ), dimension ); + + actor.SetNegotiatedDimension( newSize, dimension ); + actor.SetLayoutNegotiated( true, dimension ); + + // For deriving classes + actor.OnLayoutNegotiated( newSize, dimension ); + + // This actor has been successfully processed, pop it off the recursion stack + recursionStack.pop_back(); + } + else + { + // TODO: Break infinite loop + actor.SetLayoutNegotiated( true, dimension ); + } + } +} + +void Actor::Relayouter::NegotiateDimensions(Actor& actor, const Vector2& allocatedSize) +{ + // Negotiate all dimensions that require it + ActorDimensionStack recursionStack; + + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i ); + + // Negotiate + NegotiateDimension(actor, dimension, allocatedSize, recursionStack); + } +} + +void Actor::Relayouter::NegotiateSize(Actor& actor, const Vector2& allocatedSize, RelayoutContainer& container) +{ + // Force a size negotiation for actors that has assigned size during relayout + // This is required as otherwise the flags that force a relayout will not + // necessarilly be set. This will occur if the actor has already been laid out. + // The dirty flags are then cleared. Then if the actor is added back into the + // relayout container afterwards, the dirty flags would still be clear... + // causing a relayout to be skipped. Here we force any actors added to the + // container to be relayed out. + DALI_LOG_TIMER_START( NegSizeTimer1 ); + + if( actor.GetUseAssignedSize(Dimension::WIDTH ) ) + { + actor.SetLayoutNegotiated( false, Dimension::WIDTH ); + } + if( actor.GetUseAssignedSize( Dimension::HEIGHT ) ) + { + actor.SetLayoutNegotiated( false, Dimension::HEIGHT ); + } + + // Do the negotiation + NegotiateDimensions(actor, allocatedSize); + + // Set the actor size + actor.SetNegotiatedSize( container ); + + // Negotiate down to children + for( uint32_t i = 0, count = actor.GetChildCount(); i < count; ++i ) + { + ActorPtr child = actor.GetChildAt( i ); + + // Forces children that have already been laid out to be relayed out + // if they have assigned size during relayout. + if( child->GetUseAssignedSize(Dimension::WIDTH) ) + { + child->SetLayoutNegotiated(false, Dimension::WIDTH); + child->SetLayoutDirty(true, Dimension::WIDTH); + } + + if( child->GetUseAssignedSize(Dimension::HEIGHT) ) + { + child->SetLayoutNegotiated(false, Dimension::HEIGHT); + child->SetLayoutDirty(true, Dimension::HEIGHT); + } + + // Only relayout if required + if( child->RelayoutRequired() ) + { + container.Add( Dali::Actor( child.Get() ), actor.mTargetSize.GetVectorXY() ); + } + } + DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: "); +} + } // namespace Internal } // namespace Dali diff --git a/dali/internal/event/actors/actor-relayouter.h b/dali/internal/event/actors/actor-relayouter.h index 335e519..2b4a531 100644 --- a/dali/internal/event/actors/actor-relayouter.h +++ b/dali/internal/event/actors/actor-relayouter.h @@ -94,6 +94,10 @@ struct Actor::Relayouter /// @copydoc Actor::IsLayoutDirty bool IsLayoutDirty( Dimension::Type dimension ) const; + /// @copydoc Actor::SetPreferredSize + /// @actor[in] actor The Actor whose preferred size we wish to set + void SetPreferredSize( Actor& actor, const Vector2& size ); + /** * @brief Clamp a dimension given the relayout constraints on given actor * @@ -104,6 +108,45 @@ struct Actor::Relayouter */ static float ClampDimension( const Internal::Actor& actor, float size, Dimension::Type dimension ); + /** + * Negotiate size for a specific dimension + * + * The algorithm adopts a recursive dependency checking approach. Meaning, that wherever dependencies + * are found, e.g. an actor dependent on its parent, the dependency will be calculated first with NegotiatedDimension and + * LayoutDimensionNegotiated flags being filled in on the actor. + * + * @post All actors that exist in the dependency chain connected to the given actor will have had their NegotiatedDimensions + * calculated and set as well as the LayoutDimensionNegotiated flags. + * + * @param[in] actor The actor whose dimension we are negotiating + * @param[in] dimension The dimension to negotiate on + * @param[in] allocatedSize The size constraint that the actor must respect + */ + static void NegotiateDimension(Actor& actor, Dimension::Type dimension, const Vector2& allocatedSize, Actor::ActorDimensionStack& recursionStack); + + /** + * Negotiate sizes for a control in all dimensions + * + * @param[in] actor The actor whose dimensions we are negotiating + * @param[in] allocatedSize The size constraint that the control must respect + */ + static void NegotiateDimensions(Actor& actor, const Vector2& allocatedSize); + + /** + * @brief Called by the RelayoutController to negotiate the size of an actor. + * + * The size allocated by the the algorithm is passed in which the + * actor must adhere to. A container is passed in as well which + * the actor should populate with actors it has not / or does not + * need to handle in its size negotiation. + * + * @param[in] actor The actor whose size we are negotiating + * @param[in] size The allocated size. + * @param[in,out] container The container that holds actors that are fed back into the + * RelayoutController algorithm. + */ + static void NegotiateSize(Actor& actor, const Vector2& allocatedSize, RelayoutContainer& container); + public: ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies