END_TEST;
}
+int UtcDaliActorRaiseAbove2(void)
+{
+ tet_infoline("UtcDaliActor RaiseToAbove test using SIBLING_ORDER property\n");
+
+ TestApplication application;
+
+ Integration::Scene stage(application.GetScene());
+
+ Actor actorA = Actor::New();
+ Actor actorB = Actor::New();
+ Actor actorC = Actor::New();
+
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ stage.Add(actorA);
+ stage.Add(actorB);
+ stage.Add(actorC);
+
+ ResetTouchCallbacks();
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ tet_printf("Raise actor B Above Actor C\n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ int newOrder = actorC[DevelActor::Property::SIBLING_ORDER];
+ actorB[DevelActor::Property::SIBLING_ORDER] = newOrder;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ tet_printf("Raise actor A Above Actor B\n");
+
+ orderChangedSignal = false;
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ newOrder = actorB[DevelActor::Property::SIBLING_ORDER];
+ actorA[DevelActor::Property::SIBLING_ORDER] = newOrder;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+
+ application.ProcessEvent(touchEvent); // process a touch event on ordered actors.
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ END_TEST;
+}
+
int UtcDaliActorLowerBelow(void)
{
tet_infoline("UtcDaliActor LowerBelow test \n");
END_TEST;
}
+
+int UtcDaliActorLowerBelow2(void)
+{
+ tet_infoline("UtcDaliActor LowerBelow test using SIBLING_ORDER property\n");
+
+ TestApplication application;
+
+ Integration::Scene stage(application.GetScene());
+
+ // Set up renderers to add to Actors, float value 1, 2, 3 assigned to each
+ // enables checking of which actor the uniform is assigned too
+ Shader shaderA = CreateShader();
+ shaderA.RegisterProperty("uRendererColor", 1.f);
+
+ Shader shaderB = CreateShader();
+ shaderB.RegisterProperty("uRendererColor", 2.f);
+
+ Shader shaderC = CreateShader();
+ shaderC.RegisterProperty("uRendererColor", 3.f);
+
+ Actor actorA = Actor::New();
+ Actor actorB = Actor::New();
+ Actor actorC = Actor::New();
+
+ // Add renderers to Actors so ( uRendererColor, 1 ) is A, ( uRendererColor, 2 ) is B, and ( uRendererColor, 3 ) is C,
+ Geometry geometry = CreateQuadGeometry();
+
+ Renderer rendererA = Renderer::New(geometry, shaderA);
+ actorA.AddRenderer(rendererA);
+
+ Renderer rendererB = Renderer::New(geometry, shaderB);
+ actorB.AddRenderer(rendererB);
+
+ Renderer rendererC = Renderer::New(geometry, shaderC);
+ actorC.AddRenderer(rendererC);
+
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ Actor container = Actor::New();
+ container.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ container.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+ stage.Add(container);
+
+ container.Add(actorA);
+ container.Add(actorB);
+ container.Add(actorC);
+
+ ResetTouchCallbacks();
+
+ // Connect ChildOrderChangedSignal
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(container).Connect(&application, f);
+
+ // Set up gl abstraction trace so can query the set uniform order
+ TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+ glAbstraction.EnableSetUniformCallTrace(true);
+ glAbstraction.ResetSetUniformCallStack();
+ TraceCallStack& glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+ glAbstraction.ResetSetUniformCallStack();
+
+ application.SendNotification();
+ application.Render();
+
+ glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ int indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3");
+ int indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2");
+ int indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1");
+
+ tet_infoline("Testing C above B and A at bottom\n");
+ bool CBA = (indexC > indexB) && (indexB > indexA);
+
+ DALI_TEST_EQUALS(CBA, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
+ tet_infoline("UtcDaliActor Test Set up completed \n");
+
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ tet_printf("Lower actor C below Actor B ( actor B and A on same level due to insertion order) so C is below both \n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorC[DevelActor::Property::SIBLING_ORDER] = 1;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent); // touch event
+
+ glAbstraction.ResetSetUniformCallStack();
+ glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+ application.SendNotification();
+ application.Render();
+
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1");
+
+ tet_infoline("Testing render order is A, C, B");
+ DALI_TEST_EQUALS(indexC > indexA, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(indexB > indexC, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ tet_printf("Lower actor C below Actor A leaving B on top\n");
+
+ orderChangedSignal = false;
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorC[DevelActor::Property::SIBLING_ORDER] = 0;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ glAbstraction.ResetSetUniformCallStack();
+ glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+ application.Render();
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1");
+
+ DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(indexB > indexA, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ tet_printf("Lower actor B below Actor C leaving A on top\n");
+
+ orderChangedSignal = false;
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorB[DevelActor::Property::SIBLING_ORDER] = 0;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ glAbstraction.ResetSetUniformCallStack();
+ glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+ application.Render();
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1");
+
+ DALI_TEST_EQUALS(indexC > indexB, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliActorRaiseAboveDifferentParentsN(void)
{
tet_infoline("UtcDaliActor RaiseToAbove test with actor and target actor having different parents \n");
using CustomActorPtr = IntrusivePtr<CustomActor>;
using LayerPtr = IntrusivePtr<Layer>;
+using ActorContainer = std::vector<ActorPtr>;
+using ActorIter = ActorContainer::iterator;
+using ActorConstIter = ActorContainer::const_iterator;
+
} // namespace Internal
} // namespace Dali
#include <dali/public-api/object/type-registry.h>
#include <dali/devel-api/common/capabilities.h>
#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/internal/event/events/actor-gesture-data.h>
#include <dali/internal/event/actors/actor-property-handler.h>
#include <dali/internal/event/actors/actor-relayouter.h>
-#include <dali/internal/event/common/event-thread-services.h>
-#include <dali/internal/event/render-tasks/render-task-impl.h>
+#include <dali/internal/event/actors/actor-siblings.h>
#include <dali/internal/event/actors/camera-actor-impl.h>
-#include <dali/internal/event/render-tasks/render-task-list-impl.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/projection.h>
#include <dali/internal/event/common/property-helper.h>
-#include <dali/internal/event/common/stage-impl.h>
-#include <dali/internal/event/common/type-info-impl.h>
#include <dali/internal/event/common/scene-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
#include <dali/internal/event/common/thread-local-storage.h>
-#include <dali/internal/event/common/projection.h>
+#include <dali/internal/event/common/type-info-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+#include <dali/internal/event/render-tasks/render-task-list-impl.h>
#include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
#include <dali/internal/update/nodes/node-messages.h>
-#include <dali/internal/event/events/actor-gesture-data.h>
#include <dali/integration-api/debug.h>
using Dali::Internal::SceneGraph::Node;
}
}
-void Actor::SetSiblingOrder( uint32_t order )
+void Actor::EmitOrderChangedAndRebuild()
{
- if ( mParent )
+ Dali::Actor handle( this );
+ mParent->mChildOrderChangedSignal.Emit( handle );
+ if( mIsOnScene && mScene )
{
- ActorContainer& siblings = *(mParent->mChildren);
- uint32_t currentOrder = GetSiblingOrder();
-
- if( order != currentOrder )
- {
- if( order == 0 )
- {
- LowerToBottom();
- }
- else if( order < siblings.size() -1 )
- {
- if( order > currentOrder )
- {
- RaiseAbove( *siblings[order] );
- }
- else
- {
- LowerBelow( *siblings[order] );
- }
- }
- else
- {
- RaiseToTop();
- }
- }
+ mScene->RequestRebuildDepthTree();
}
}
-uint32_t Actor::GetSiblingOrder() const
+void Actor::SetSiblingOrder( uint32_t order )
{
- uint32_t order = 0;
-
- if ( mParent )
+ if( mParent && SiblingHandler::SetSiblingOrder(*(mParent->mChildren), *this, order))
{
- ActorContainer& siblings = *(mParent->mChildren);
- for( std::size_t i = 0; i < siblings.size(); ++i )
- {
- if( siblings[i] == this )
- {
- order = static_cast<uint32_t>( i );
- break;
- }
- }
+ EmitOrderChangedAndRebuild();
}
-
- return order;
}
-void Actor::RequestRebuildDepthTree()
+uint32_t Actor::GetSiblingOrder() const
{
- if( mIsOnScene )
+ uint32_t order = 0;
+ if( mParent )
{
- if( mScene )
- {
- mScene->RequestRebuildDepthTree();
- }
+ order = SiblingHandler::GetSiblingOrder(*(mParent->mChildren), *this);
}
+ return order;
}
void Actor::Raise()
{
- if ( mParent )
+ if( mParent && SiblingHandler::Raise(*(mParent->mChildren), *this) )
{
- ActorContainer& siblings = *(mParent->mChildren);
- if( siblings.back() != this ) // If not already at end
- {
- for( std::size_t i=0; i<siblings.size(); ++i )
- {
- if( siblings[i] == this )
- {
- // Swap with next
- ActorPtr next = siblings[i+1];
- siblings[i+1] = this;
- siblings[i] = next;
- break;
- }
- }
- }
-
- Dali::Actor handle( this );
- mParent->mChildOrderChangedSignal.Emit( handle );
-
- RequestRebuildDepthTree();
+ EmitOrderChangedAndRebuild();
}
else
{
void Actor::Lower()
{
- if ( mParent )
+ if( mParent && SiblingHandler::Lower(*(mParent->mChildren), *this) )
{
- ActorContainer& siblings = *(mParent->mChildren);
- if( siblings.front() != this ) // If not already at beginning
- {
- for( std::size_t i=1; i<siblings.size(); ++i )
- {
- if( siblings[i] == this )
- {
- // Swap with previous
- ActorPtr previous = siblings[i-1];
- siblings[i-1] = this;
- siblings[i] = previous;
- break;
- }
- }
- }
-
- Dali::Actor handle( this );
- mParent->mChildOrderChangedSignal.Emit( handle );
-
- RequestRebuildDepthTree();
+ EmitOrderChangedAndRebuild();
}
else
{
void Actor::RaiseToTop()
{
- if ( mParent )
+ if( mParent && SiblingHandler::RaiseToTop(*(mParent->mChildren), *this) )
{
- ActorContainer& siblings = *(mParent->mChildren);
- if( siblings.back() != this ) // If not already at end
- {
- auto iter = std::find( siblings.begin(), siblings.end(), this );
- if( iter != siblings.end() )
- {
- siblings.erase(iter);
- siblings.push_back(ActorPtr(this));
- }
- }
-
- Dali::Actor handle( this );
- mParent->mChildOrderChangedSignal.Emit( handle );
-
- RequestRebuildDepthTree();
+ EmitOrderChangedAndRebuild();
}
else
{
void Actor::LowerToBottom()
{
- if ( mParent )
+ if( mParent && SiblingHandler::LowerToBottom(*(mParent->mChildren), *this) )
{
- ActorContainer& siblings = *(mParent->mChildren);
- if( siblings.front() != this ) // If not already at bottom,
- {
- ActorPtr thisPtr(this); // ensure this actor remains referenced.
-
- auto iter = std::find( siblings.begin(), siblings.end(), this );
- if( iter != siblings.end() )
- {
- siblings.erase(iter);
- siblings.insert(siblings.begin(), thisPtr);
- }
- }
-
- Dali::Actor handle( this );
- mParent->mChildOrderChangedSignal.Emit( handle );
-
- RequestRebuildDepthTree();
+ EmitOrderChangedAndRebuild();
}
else
{
void Actor::RaiseAbove( Internal::Actor& target )
{
- if ( mParent )
+ if( mParent && SiblingHandler::RaiseAbove( *(mParent->mChildren), *this, target ))
{
- ActorContainer& siblings = *(mParent->mChildren);
- if( siblings.back() != this && target.mParent == mParent ) // If not already at top
- {
- ActorPtr thisPtr(this); // ensure this actor remains referenced.
-
- auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
- auto thisIter = std::find( siblings.begin(), siblings.end(), this );
- if( thisIter < targetIter )
- {
- siblings.erase(thisIter);
- // Erasing early invalidates the targetIter. (Conversely, inserting first may also
- // invalidate thisIter)
- targetIter = std::find( siblings.begin(), siblings.end(), &target );
- ++targetIter;
- siblings.insert(targetIter, thisPtr);
- }
-
- Dali::Actor handle( this );
- mParent->mChildOrderChangedSignal.Emit( handle );
-
- RequestRebuildDepthTree();
- }
+ EmitOrderChangedAndRebuild();
}
else
{
void Actor::LowerBelow( Internal::Actor& target )
{
- if ( mParent )
+ if( mParent && SiblingHandler::LowerBelow(*(mParent->mChildren), *this, target ) )
{
- ActorContainer& siblings = *(mParent->mChildren);
- if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
- {
- ActorPtr thisPtr(this); // ensure this actor remains referenced.
-
- auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
- auto thisIter = std::find( siblings.begin(), siblings.end(), this );
-
- if( thisIter > targetIter )
- {
- siblings.erase(thisIter); // this only invalidates iterators at or after this point.
- siblings.insert(targetIter, thisPtr);
- }
-
- Dali::Actor handle( this );
- mParent->mChildOrderChangedSignal.Emit( handle );
-
- RequestRebuildDepthTree();
- }
+ EmitOrderChangedAndRebuild();
}
else
{
class Renderer;
class Scene;
-using ActorContainer = std::vector<ActorPtr>;
-using ActorIter = ActorContainer::iterator;
-using ActorConstIter = ActorContainer::const_iterator;
-
using RendererContainer = std::vector<RendererPtr>;
using RendererIter = RendererContainer::iterator;
uint32_t GetSiblingOrder() const;
/**
- * Request that the stage rebuilds the actor depth indices.
+ * Emit ChildOrderChanged signal, and request that the scene
+ * rebuilds the actor depth indices.
*/
- void RequestRebuildDepthTree();
+ void EmitOrderChangedAndRebuild();
/**
* @brief Get the current position of the actor in screen coordinates.
static ActorContainer mNullChildren; ///< Empty container (shared by all actors, returned by GetChildren() const)
struct PropertyHandler;
+ struct SiblingHandler;
};
} // namespace Internal
--- /dev/null
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/actor-siblings.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+namespace Dali
+{
+namespace Internal
+{
+
+bool Actor::SiblingHandler::SetSiblingOrder(
+ ActorContainer& siblings,
+ Actor& actor,
+ uint32_t order )
+{
+ bool changed = false;
+
+ uint32_t currentOrder = GetSiblingOrder(siblings, actor);
+ if( order != currentOrder )
+ {
+ if( order == 0 )
+ {
+ changed = LowerToBottom(siblings, actor);
+ }
+ else if( order < siblings.size() -1 )
+ {
+ if( order > currentOrder )
+ {
+ changed = RaiseAbove( siblings, actor, *siblings[order] );
+ }
+ else
+ {
+ changed = LowerBelow( siblings, actor, *siblings[order] );
+ }
+ }
+ else
+ {
+ changed = RaiseToTop(siblings, actor);
+ }
+ }
+ return changed;
+}
+
+uint32_t Actor::SiblingHandler::GetSiblingOrder(const ActorContainer& siblings, const Actor& actor)
+{
+ uint32_t order=0;
+ for( std::size_t i = 0; i < siblings.size(); ++i )
+ {
+ if( siblings[i] == &actor )
+ {
+ order = static_cast<uint32_t>( i );
+ break;
+ }
+ }
+ return order;
+}
+
+bool Actor::SiblingHandler::Raise(ActorContainer& siblings, Actor& actor)
+{
+ bool changed = false;
+ if( siblings.back() != &actor ) // If not already at end
+ {
+ for( std::size_t i=0; i<siblings.size(); ++i )
+ {
+ if( siblings[i] == &actor )
+ {
+ // Swap with next
+ ActorPtr next = siblings[i+1];
+ siblings[i+1] = &actor;
+ siblings[i] = next;
+ changed = true;
+ break;
+ }
+ }
+ }
+ return changed;
+}
+
+bool Actor::SiblingHandler::Lower(ActorContainer& siblings, Actor& actor)
+{
+ bool changed = false;
+ if( siblings.front() != &actor ) // If not already at beginning
+ {
+ for( std::size_t i=1; i<siblings.size(); ++i )
+ {
+ if( siblings[i] == &actor )
+ {
+ // Swap with previous
+ ActorPtr previous = siblings[i-1];
+ siblings[i-1] = &actor;
+ siblings[i] = previous;
+ changed = true;
+ break;
+ }
+ }
+ }
+ return changed;
+}
+
+bool Actor::SiblingHandler::RaiseToTop(ActorContainer& siblings, Actor& actor)
+{
+ bool changed = false;
+ if( siblings.back() != &actor ) // If not already at end
+ {
+ auto iter = std::find( siblings.begin(), siblings.end(), &actor );
+ if( iter != siblings.end() )
+ {
+ siblings.erase(iter);
+ siblings.push_back(ActorPtr(&actor));
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+bool Actor::SiblingHandler::LowerToBottom(ActorContainer& siblings, Actor& actor)
+{
+ bool changed = false;
+ if( siblings.front() != &actor ) // If not already at bottom,
+ {
+ ActorPtr actorPtr(&actor); // ensure actor actor remains referenced.
+
+ auto iter = std::find( siblings.begin(), siblings.end(), &actor );
+ if( iter != siblings.end() )
+ {
+ siblings.erase(iter);
+ siblings.insert(siblings.begin(), actorPtr);
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+bool Actor::SiblingHandler::RaiseAbove(ActorContainer& siblings, Actor& actor, Actor& target)
+{
+ bool raised = false;
+ if( siblings.back() != &actor && target.GetParent() == actor.GetParent() ) // If not already at top
+ {
+ ActorPtr actorPtr(&actor); // ensure actor actor remains referenced.
+
+ auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
+ auto actorIter = std::find( siblings.begin(), siblings.end(), &actor );
+ if( actorIter < targetIter )
+ {
+ siblings.erase(actorIter);
+ // Erasing early invalidates the targetIter. (Conversely, inserting first may also
+ // invalidate actorIter)
+ targetIter = std::find( siblings.begin(), siblings.end(), &target );
+ ++targetIter;
+ siblings.insert(targetIter, actorPtr);
+ }
+ raised = true;
+ }
+ return raised;
+}
+
+bool Actor::SiblingHandler::LowerBelow(ActorContainer& siblings, Actor& actor, Actor& target)
+{
+ bool lowered = false;
+
+ // If not already at bottom
+ if( siblings.front() != &actor && target.GetParent() == actor.GetParent() )
+ {
+ ActorPtr actorPtr(&actor); // ensure actor actor remains referenced.
+
+ auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
+ auto actorIter = std::find( siblings.begin(), siblings.end(), &actor );
+
+ if( actorIter > targetIter )
+ {
+ siblings.erase(actorIter); // actor only invalidates iterators at or after actor point.
+ siblings.insert(targetIter, actorPtr);
+ }
+ lowered = true;
+ }
+ return lowered;
+}
+
+
+} // namespace Internal
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_INTERNAL_ACTOR_SIBLINGS_H
+#define DALI_INTERNAL_ACTOR_SIBLINGS_H
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use actor file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actors/actor-impl.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+struct Actor::SiblingHandler
+{
+ /**
+ * @brief Change the sibling order of the given actor.
+ *
+ * @param[in,out] siblings The container of siblings
+ * @param[in] actor The actor to change
+ * @param[in] order The new order for the actor
+ * @return true if order has been modified
+ */
+ static bool SetSiblingOrder( ActorContainer& siblings, Actor& actor, uint32_t order );
+
+ /**
+ * @brief Get the sibling order of the given actor.
+ *
+ * @param[in] siblings The container of siblings
+ * @param[in] actor The actor to query
+ * @return the order in the sibling array of the actor
+ */
+ static uint32_t GetSiblingOrder(const ActorContainer& siblings, const Actor& actor);
+
+ /**
+ * @brief Raise the actor within the siblings list by one
+ * @param[in,out] siblings The container of siblings
+ * @param[in] actor The actor to move
+ * @return true if order has been modified
+ */
+ static bool Raise(ActorContainer& siblings, Actor& actor);
+
+ /**
+ * @brief Lower the actor within the siblings list by one
+ * @param[in,out] siblings The container of siblings
+ * @param[in] actor The actor to move
+ * @return true if order has been modified
+ */
+ static bool Lower(ActorContainer& siblings, Actor& actor);
+
+ /**
+ * @brief Raise the actor to the top of the siblings list.
+ *
+ * @param[in,out] siblings The container of siblings
+ * @param[in] actor The actor to move
+ * @return true if order has been modified
+ */
+ static bool RaiseToTop(ActorContainer& siblings, Actor& actor);
+
+ /**
+ * @brief Lower the actor to the bottom of the siblings list.
+ *
+ * @param[in,out] siblings The container of siblings
+ * @param[in] actor The actor to move
+ * @return true if order has been modified
+ */
+ static bool LowerToBottom(ActorContainer& siblings, Actor& actor);
+
+ /**
+ * @brief Raise the actor above the target actor within the siblings list.
+ *
+ * @param[in,out] siblings The container of siblings
+ * @param[in] actor The actor to move
+ * @param[in] target The target actor
+ * @return true if order has been modified
+ */
+ static bool RaiseAbove(ActorContainer& siblings, Actor& actor, Actor& target);
+
+ /**
+ * @brief Lower the actor below the target actor within the siblings list.
+ *
+ * @param[in,out] siblings The container of siblings
+ * @param[in] actor The actor to move
+ * @param[in] target The target actor
+ * @return true if order has been modified
+ */
+ static bool LowerBelow(ActorContainer& siblings, Actor& actor, Actor& target);
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+
+#endif
${internal_src_dir}/common/fixed-size-memory-pool.cpp
${internal_src_dir}/common/const-string.cpp
-
${internal_src_dir}/event/actors/actor-impl.cpp
${internal_src_dir}/event/actors/actor-property-handler.cpp
${internal_src_dir}/event/actors/actor-relayouter.cpp
+ ${internal_src_dir}/event/actors/actor-siblings.cpp
${internal_src_dir}/event/actors/custom-actor-internal.cpp
${internal_src_dir}/event/actors/layer-impl.cpp
${internal_src_dir}/event/actors/layer-list.cpp