return control;
}
+int Impl::DummyControl::constructorCount;
+int Impl::DummyControl::destructorCount;
Impl::DummyControl::DummyControl()
: DummyControlImpl(),
keyInputFocusGained(false),
keyInputFocusLost(false)
{
+ ++constructorCount;
}
-Impl::DummyControl::~DummyControl() { }
-
+Impl::DummyControl::~DummyControl()
+{
+ ++destructorCount;
+}
void Impl::DummyControl::OnInitialize() { initializeCalled = true; }
bool Impl::DummyControl::OnAccessibilityActivated() { activatedCalled = true; return true; }
bool keyEventCalled;
bool keyInputFocusGained;
bool keyInputFocusLost;
+ static int constructorCount;
+ static int destructorCount;
Property::Map mLayouts;
RelayoutCallbackFunc mRelayoutCallback;
#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
#include <../custom-layout.h>
+#include <dummy-control.h>
#include <layout-utils.h>
END_TEST;
}
+int UtcDaliLayouting_CheckResourceLeak01(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliLayouting_CheckResourceLeak01 - Remove animating layout and add child to stage" );
+
+ Dali::Toolkit::Impl::DummyControl::constructorCount = 0;
+ Dali::Toolkit::Impl::DummyControl::destructorCount = 0;
+
+ Stage stage = Stage::GetCurrent();
+ auto container = Control::New();
+ auto linearLayout = LinearLayout::New();
+ linearLayout.SetAnimateLayout( true );
+
+ DevelControl::SetLayout( container, linearLayout );
+ container.SetName( "Container" );
+
+ stage.Add( container );
+
+ DummyControl control = DummyControl::New( true );
+ control.SetName( "DummyControl01" );
+ control.SetSize( 100, 100 );
+ container.Add( control );
+
+ control = DummyControl::New( true );
+ control.SetName( "DummyControl02" );
+ control.SetSize( 100, 100 );
+ container.Add( control );
+
+ linearLayout.SetAnimateLayout( true );
+
+ DALI_TEST_EQUALS( Dali::Toolkit::Impl::DummyControl::constructorCount, 2, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Toolkit::Impl::DummyControl::destructorCount, 0, TEST_LOCATION );
+
+ // Initial rendering done
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>( 0.5f * 1000.0f ) + 1u /*just after the end of the animation*/ );
+
+ DALI_TEST_EQUALS( Dali::Toolkit::Impl::DummyControl::constructorCount, 2, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Toolkit::Impl::DummyControl::destructorCount, 0, TEST_LOCATION );
+
+ stage.Remove( container );
+ container.Reset();
+
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>( 0.5f * 1000.0f ) + 1u /*just after the end of the animation*/ );
+
+ DALI_TEST_EQUALS( Dali::Toolkit::Impl::DummyControl::constructorCount, 2, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Toolkit::Impl::DummyControl::destructorCount, 1, TEST_LOCATION );
+
+ Stage::GetCurrent().Add( control );
+
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>( 0.5f * 1000.0f ) + 1u /*just after the end of the animation*/ );
+
+ DALI_TEST_EQUALS( Dali::Toolkit::Impl::DummyControl::constructorCount, 2, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Toolkit::Impl::DummyControl::destructorCount, 1, TEST_LOCATION );
+
+ stage.Remove( control );
+ control.Reset();
+
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>( 0.5f * 1000.0f ) + 1u /*just after the end of the animation*/ );
+
+ DALI_TEST_EQUALS( Dali::Toolkit::Impl::DummyControl::constructorCount, 2, TEST_LOCATION );
+ DALI_TEST_EQUALS( Dali::Toolkit::Impl::DummyControl::destructorCount, 2, TEST_LOCATION );
+
+ END_TEST;
+}
+
if( childLayout )
{
Remove( *childLayout.Get() );
- RequestLayout( Dali::Toolkit::LayoutTransitionData::Type::ON_CHILD_REMOVE, child, Actor() );
+ RequestLayout( Dali::Toolkit::LayoutTransitionData::Type::ON_CHILD_REMOVE, Actor(), child );
}
}
}
void LayoutItem::Initialize( Handle& owner, const std::string& containerType )
{
- mImpl->mOwner = &(owner.GetBaseObject());
+ mImpl->mOwner = owner;
RegisterChildProperties( containerType );
OnInitialize(); // Ensure direct deriving class gets initialized
}
Handle LayoutItem::GetOwner() const
{
- return Handle::DownCast(BaseHandle(mImpl->mOwner));
+ return mImpl->mOwner.GetHandle();
}
void LayoutItem::Unparent()
SetParent(nullptr);
// Last, clear owner
- mImpl->mOwner = NULL;
+ mImpl->mOwner.Reset();
}
LayoutTransitionDataPtr LayoutItem::GetDefaultTransition()
Extents LayoutItem::GetPadding() const
{
- Toolkit::Control control = Toolkit::Control::DownCast( mImpl->mOwner );
+ Toolkit::Control control = Toolkit::Control::DownCast( GetOwner() );
if( control )
{
Extents padding = control.GetProperty<Extents>( Toolkit::Control::Property::PADDING );
Extents LayoutItem::GetMargin() const
{
- Toolkit::Control control = Toolkit::Control::DownCast( mImpl->mOwner );
+ Toolkit::Control control = Toolkit::Control::DownCast( GetOwner() );
if ( control )
{
return control.GetProperty<Extents>( Toolkit::Control::Property::MARGIN );
void LayoutItem::RequestLayout()
{
- Toolkit::Control control = Toolkit::Control::DownCast( mImpl->mOwner );
+ Toolkit::Control control = Toolkit::Control::DownCast( GetOwner() );
if( control )
{
DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::RequestLayout control(%s)\n",
control.GetName().c_str() );
+
+ // @todo Enforce failure if called in Measure/Layout passes.
+ mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
+ Toolkit::LayoutController layoutController = Toolkit::LayoutController::Get();
+ layoutController.RequestLayout( Toolkit::LayoutItem( this ) );
}
- // @todo Enforce failure if called in Measure/Layout passes.
- mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
- Toolkit::LayoutController layoutController = Toolkit::LayoutController::Get();
- layoutController.RequestLayout( Toolkit::LayoutItem( this ) );
}
void LayoutItem::RequestLayout( Dali::Toolkit::LayoutTransitionData::Type layoutAnimationType )
{
- Toolkit::Control control = Toolkit::Control::DownCast( mImpl->mOwner );
+ Toolkit::Control control = Toolkit::Control::DownCast( GetOwner() );
if ( control )
{
DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::RequestLayout control(%s) layoutTranstionType(%d)\n",
control.GetName().c_str(), (int)layoutAnimationType );
+
+ // @todo Enforce failure if called in Measure/Layout passes.
+ mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
+ Toolkit::LayoutController layoutController = Toolkit::LayoutController::Get();
+ layoutController.RequestLayout( Toolkit::LayoutItem(this), layoutAnimationType );
}
- // @todo Enforce failure if called in Measure/Layout passes.
- mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
- Toolkit::LayoutController layoutController = Toolkit::LayoutController::Get();
- layoutController.RequestLayout( Toolkit::LayoutItem(this), layoutAnimationType );
}
void LayoutItem::RequestLayout( Dali::Toolkit::LayoutTransitionData::Type layoutAnimationType, Actor gainedChild, Actor lostChild )
{
- Toolkit::Control control = Toolkit::Control::DownCast( mImpl->mOwner );
+ Toolkit::Control control = Toolkit::Control::DownCast( GetOwner() );
if ( control )
{
DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::RequestLayout control(%s) layoutTranstionType(%d)\n",
control.GetName().c_str(), (int)layoutAnimationType );
+
+ // @todo Enforce failure if called in Measure/Layout passes.
+ mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
+ Toolkit::LayoutController layoutController = Toolkit::LayoutController::Get();
+ layoutController.RequestLayout( Toolkit::LayoutItem(this), layoutAnimationType, gainedChild, lostChild );
}
- // @todo Enforce failure if called in Measure/Layout passes.
- mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
- Toolkit::LayoutController layoutController = Toolkit::LayoutController::Get();
- layoutController.RequestLayout( Toolkit::LayoutItem(this), layoutAnimationType, gainedChild, lostChild );
}
bool LayoutItem::IsLayoutRequested() const
LayoutLength LayoutItem::GetSuggestedMinimumWidth() const
{
auto owner = GetOwner();
- auto actor = Actor::DownCast(owner);
+ auto actor = Actor::DownCast( owner );
auto naturalSize = actor ? actor.GetNaturalSize() : Vector3::ZERO;
return std::max( mImpl->mMinimumSize.GetWidth(), LayoutLength( naturalSize.width ) );
LayoutLength LayoutItem::GetSuggestedMinimumHeight() const
{
auto owner = GetOwner();
- auto actor = Actor::DownCast(owner);
+ auto actor = Actor::DownCast( owner );
auto naturalSize = actor ? actor.GetNaturalSize() : Vector3::ZERO;
return std::max( mImpl->mMinimumSize.GetHeight(), LayoutLength( naturalSize.height ) );
auto actor = Actor::DownCast( layoutItem.GetOwner() );
if ( actor )
{
- DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::RequestLayout owner[%s] layoutItem[%p] layoutTransitionType(%d)\n", actor.GetName().c_str(), &layoutItem, layoutTransitionType );
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::RequestLayout owner[%s] layoutItem[%p] layoutTransitionType(%d) gainedChild[%s] lostChild[%s]\n",
+ actor.GetName().c_str(), &layoutItem, layoutTransitionType,
+ gainedChild ? gainedChild.GetName().c_str() : "",
+ lostChild ? lostChild.GetName().c_str() : "");
}
else
{
continue;
}
- Actor actor = Actor::DownCast( layoutDataElement.handle );
- LayoutDataAnimator animator = layoutData.layoutAnimatorArray[ layoutDataElement.animatorIndex ];
- float width = actor.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
- float height = actor.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
-
- if( layoutDataElement.AdjustMeasuredSize( width, height, animator.animatorType ) )
+ Actor actor = layoutDataElement.handle.GetHandle();
+ if( actor )
{
- mActorSizeSpecs.push_back( ActorSizeSpec( actor ) );
- actor.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, static_cast<int>( width ) );
- actor.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, static_cast<int>( height ) );
+ LayoutDataAnimator animator = layoutData.layoutAnimatorArray[ layoutDataElement.animatorIndex ];
+ float width = actor.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
+ float height = actor.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
+
+ if( layoutDataElement.AdjustMeasuredSize( width, height, animator.animatorType ) )
+ {
+ mActorSizeSpecs.push_back( ActorSizeSpec( actor ) );
+ actor.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, static_cast<int>( width ) );
+ actor.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, static_cast<int>( height ) );
+ }
}
}
{
for( auto& actorSizeSpec : mActorSizeSpecs )
{
- Actor actor = actorSizeSpec.actor;
- actor.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, actorSizeSpec.widthSpec );
- actor.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, actorSizeSpec.heightSpec );
+ Actor actor = actorSizeSpec.actor.GetHandle();
+ if( actor )
+ {
+ actor.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, actorSizeSpec.widthSpec );
+ actor.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, actorSizeSpec.heightSpec );
+ }
}
}
for( auto layoutPositionData : layoutPositionDataArray )
{
- Actor actor = Actor::DownCast( layoutPositionData.handle );
+ Actor actor = layoutPositionData.handle.GetHandle();
if( actor && ( !layoutPositionData.animated || all ) )
{
- if ( !layoutPositionData.animated )
+ if( !layoutPositionData.animated )
{
actor.SetPosition( layoutPositionData.left, layoutPositionData.top );
actor.SetSize( layoutPositionData.right - layoutPositionData.left, layoutPositionData.bottom - layoutPositionData.top );
{
if( layoutDataElement.animatorIndex >= 0 )
{
- Actor actor = Actor::DownCast( layoutDataElement.handle );
+ Actor actor = layoutDataElement.handle.GetHandle();
if ( actor )
{
LayoutDataAnimator animator = layoutAnimatorArray[ layoutDataElement.animatorIndex ];
{
}
- Actor actor;
+ WeakHandle<Actor> actor;
int widthSpec;
int heightSpec;
};
{
layoutController.PerformLayoutPositioning( layoutDataPositionArray, true );
layoutController.mAnimationFinishedFunctors.pop_front();
- if (layoutTransitionType != -1)
+ if( layoutTransitionType != -1 )
{
LayoutTransitionDataPtr layoutTransitionDataPtr = layoutItem->GetTransitionData( layoutTransitionType );
layoutTransitionDataPtr->EmitSignalFinish( layoutTransitionType );
LayoutData* LayoutItem::Impl::sLayoutData = nullptr;
LayoutItem::Impl::Impl()
-: mOwner( nullptr ),
+: mOwner(),
mLayoutParent( nullptr ),
mOldWidthMeasureSpec( 0 ),
mOldHeightMeasureSpec( 0 ),
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+#include <dali/public-api/object/weak-handle.h>
#include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
#include <dali-toolkit/devel-api/layouting/layout-controller.h>
#include <dali-toolkit/devel-api/layouting/layout-size.h>
Impl();
public:
- BaseObject* mOwner; ///< Control or Visual that owns this layout. Raw pointer to prevent cyclic references
+ WeakHandle<Handle> mOwner; ///< Control or Visual that owns this layout. Weak pointer to prevent cyclic references
LayoutParent* mLayoutParent; ///< The containing layout parent.
MeasureSpec mOldWidthMeasureSpec;
return false;
}
- Actor actor = Actor::DownCast( handle );
+ Actor actor = handle.GetHandle();
float animateByMultiplier = ( animatorType == Toolkit::LayoutTransitionData::Animator::Type::ANIMATE_BY ) ? 1.0f : 0.0f;
Vector3 size = actor.GetCurrentSize();
void LayoutDataElement::UpdatePropertyIndex()
{
- if( propertyIndex == -1 && handle && !propertyName.empty() )
+ if( propertyIndex == -1 && !propertyName.empty() )
{
- Actor actor = Actor::DownCast( handle );
- propertyIndex = DevelHandle::GetPropertyIndex( actor, Property::Key( propertyName ) );
+ Actor actor = handle.GetHandle();
+ if( actor )
+ {
+ propertyIndex = DevelHandle::GetPropertyIndex( actor, Property::Key( propertyName ) );
+ }
}
}
}
LayoutTransitionData::PropertyAnimator::PropertyAnimator( )
- : handle( Actor( ) )
+ : handle()
, map()
, interpolation( Animation::Linear )
{
// Add the children animators
for( const LayoutDataElement& iter : layoutData.childrenLayoutDataArray )
{
- if( iter.handle != nullptr && iter.handle != child )
+ Actor actor = iter.handle.GetHandle();
+ if( actor && actor != child )
{
continue;
}
LayoutDataElement layoutDataElement = iter;
+ Actor gainedChild = layoutData.layoutTransition.gainedChild.GetHandle();
+ Actor lostChild = layoutData.layoutTransition.lostChild.GetHandle();
switch ( layoutDataElement.condition )
{
case Dali::Toolkit::LayoutTransitionData::Condition::ON_ADD:
if ( layoutData.layoutTransition.layoutTransitionType != Dali::Toolkit::LayoutTransitionData::ON_CHILD_ADD
- || layoutData.layoutTransition.gainedChild != child )
+ || gainedChild != child )
{
continue;
}
break;
case Dali::Toolkit::LayoutTransitionData::Condition::ON_REMOVE:
if( layoutData.layoutTransition.layoutTransitionType != Dali::Toolkit::LayoutTransitionData::ON_CHILD_REMOVE
- || layoutData.layoutTransition.lostChild != child )
+ || lostChild != child )
{
continue;
}
break;
case Dali::Toolkit::LayoutTransitionData::Condition::ON_FOCUS_GAINED:
if( layoutData.layoutTransition.layoutTransitionType != Dali::Toolkit::LayoutTransitionData::ON_CHILD_FOCUS
- || layoutData.layoutTransition.gainedChild != child )
+ || gainedChild != child )
{
continue;
}
break;
case Dali::Toolkit::LayoutTransitionData::Condition::ON_FOCUS_LOST:
if( layoutData.layoutTransition.layoutTransitionType != Dali::Toolkit::LayoutTransitionData::ON_CHILD_FOCUS
- || layoutData.layoutTransition.lostChild != child )
+ || lostChild != child )
{
continue;
}
// Collect the transition animators
for( const LayoutDataElement& iter : mLayoutDataElements )
{
- if( iter.handle == nullptr || iter.handle != owner )
+ Actor actor = iter.handle.GetHandle();
+ if( !actor || actor != owner )
{
layoutData.childrenLayoutDataArray.push_back( iter );
continue;
#include <dali/public-api/object/base-object.h>
#include <dali/public-api/object/property-map.h>
#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/object/weak-handle.h>
#include <dali/public-api/actors/actor-enumerations.h>
#include <dali/public-api/animation/animation.h>
LayoutItemPtr layoutItem;
int layoutTransitionType;
- Actor gainedChild;
- Actor lostChild;
+ WeakHandle<Actor> gainedChild;
+ WeakHandle<Actor> lostChild;
};
const float DEFAULT_TRANSITION_DURATION( 0.5f );
struct LayoutPositionData
{
- LayoutPositionData( Handle handle, float left, float top, float right, float bottom, bool animated ) :
+ LayoutPositionData( Actor handle, float left, float top, float right, float bottom, bool animated ) :
handle( handle ), left( left ), top( top ), right( right ), bottom( bottom ), animated( animated ), updateWithCurrentSize(false)
{
};
- BaseHandle handle;
+ WeakHandle<Actor> handle;
float left;
float top;
float right;
void UpdateAnimatorIndex( const LayoutAnimatorArray& animators );
void UpdatePositionDataIndex( LayoutData& layoutData );
- BaseHandle handle;
+ WeakHandle<Actor> handle;
std::string propertyName;
Property::Index propertyIndex;
Property::Value initialValue;
PropertyAnimator( Actor actor, Property::Map map, Path path, Vector3 forward );
PropertyAnimator( Actor actor, Property::Map map, KeyFrames keyFrames, Animation::Interpolation interpolation );
- BaseHandle handle;
+ WeakHandle<Actor> handle;
Property::Map map;