#include <dali/public-api/object/type-registry.h>
#include <dali/devel-api/actors/actor-devel.h>
-#include <dali/devel-api/actors/layer-devel.h>
#include <dali/devel-api/common/capabilities.h>
#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/actor-coords.h>
#include <dali/internal/event/actors/actor-parent.h>
#include <dali/internal/event/actors/actor-property-handler.h>
#include <dali/internal/event/actors/actor-relayouter.h>
#include <dali/internal/event/actors/camera-actor-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/scene-impl.h>
#include <dali/internal/event/common/stage-impl.h>
DALI_PROPERTY("touchAreaOffset", RECTANGLE, true, false, false, Dali::DevelActor::Property::TOUCH_AREA_OFFSET)
DALI_PROPERTY("blendEquation", INTEGER, true, false, false, Dali::DevelActor::Property::BLEND_EQUATION)
DALI_PROPERTY("touchFocusable", BOOLEAN, true, false, false, Dali::DevelActor::Property::TOUCH_FOCUSABLE)
+DALI_PROPERTY("keyboardFocusableChildren", BOOLEAN, true, false, false, Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN)
DALI_PROPERTY_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties)
// Signals
return Dali::Actor::New();
}
+/**
+ * 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.
+ */
+static bool DoConnectSignal(BaseObject* object,
+ ConnectionTrackerInterface* tracker,
+ const std::string& signalName,
+ FunctorDelegate* functor)
+{
+ bool connected(true);
+ Actor* actor = static_cast<Actor*>(object); // TypeRegistry guarantees that this is the correct type.
+
+ std::string_view name(signalName);
+
+ if(name == SIGNAL_HOVERED)
+ {
+ actor->HoveredSignal().Connect(tracker, functor);
+ }
+ else if(signalName == SIGNAL_WHEEL_EVENT)
+ {
+ actor->WheelEventSignal().Connect(tracker, functor);
+ }
+ else if(name == SIGNAL_ON_SCENE)
+ {
+ actor->OnSceneSignal().Connect(tracker, functor);
+ }
+ else if(name == SIGNAL_OFF_SCENE)
+ {
+ actor->OffSceneSignal().Connect(tracker, functor);
+ }
+ else if(name == SIGNAL_ON_RELAYOUT)
+ {
+ actor->OnRelayoutSignal().Connect(tracker, functor);
+ }
+ else if(name == SIGNAL_TOUCHED)
+ {
+ actor->TouchedSignal().Connect(tracker, functor);
+ }
+ else if(name == SIGNAL_VISIBILITY_CHANGED)
+ {
+ actor->VisibilityChangedSignal().Connect(tracker, functor);
+ }
+ else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED)
+ {
+ actor->LayoutDirectionChangedSignal().Connect(tracker, functor);
+ }
+ else if(name == SIGNAL_CHILD_ADDED)
+ {
+ actor->ChildAddedSignal().Connect(tracker, functor);
+ }
+ else if(name == SIGNAL_CHILD_REMOVED)
+ {
+ actor->ChildRemovedSignal().Connect(tracker, functor);
+ }
+ else
+ {
+ // signalName does not match any signal
+ connected = false;
+ }
+
+ return connected;
+}
+
+/**
+ * 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 the action was done.
+ */
+bool DoAction(BaseObject* object,
+ const std::string& actionName,
+ const Property::Map& attributes)
+{
+ bool done = false;
+ Actor* actor = dynamic_cast<Actor*>(object);
+
+ if(actor)
+ {
+ std::string_view name(actionName);
+ if(name == ACTION_SHOW)
+ {
+ actor->SetVisible(true);
+ done = true;
+ }
+ else if(name == ACTION_HIDE)
+ {
+ actor->SetVisible(false);
+ done = true;
+ }
+ }
+
+ return done;
+}
+
TypeRegistration mType(typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties);
-SignalConnectorType signalConnector2(mType, std::string(SIGNAL_HOVERED), &Actor::DoConnectSignal);
-SignalConnectorType signalConnector3(mType, std::string(SIGNAL_WHEEL_EVENT), &Actor::DoConnectSignal);
-SignalConnectorType signalConnector4(mType, std::string(SIGNAL_ON_SCENE), &Actor::DoConnectSignal);
-SignalConnectorType signalConnector5(mType, std::string(SIGNAL_OFF_SCENE), &Actor::DoConnectSignal);
-SignalConnectorType signalConnector6(mType, std::string(SIGNAL_ON_RELAYOUT), &Actor::DoConnectSignal);
-SignalConnectorType signalConnector7(mType, std::string(SIGNAL_TOUCHED), &Actor::DoConnectSignal);
-SignalConnectorType signalConnector8(mType, std::string(SIGNAL_VISIBILITY_CHANGED), &Actor::DoConnectSignal);
-SignalConnectorType signalConnector9(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &Actor::DoConnectSignal);
-SignalConnectorType signalConnector10(mType, std::string(SIGNAL_CHILD_ADDED), &Actor::DoConnectSignal);
-SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_REMOVED), &Actor::DoConnectSignal);
+SignalConnectorType signalConnector2(mType, std::string(SIGNAL_HOVERED), &DoConnectSignal);
+SignalConnectorType signalConnector3(mType, std::string(SIGNAL_WHEEL_EVENT), &DoConnectSignal);
+SignalConnectorType signalConnector4(mType, std::string(SIGNAL_ON_SCENE), &DoConnectSignal);
+SignalConnectorType signalConnector5(mType, std::string(SIGNAL_OFF_SCENE), &DoConnectSignal);
+SignalConnectorType signalConnector6(mType, std::string(SIGNAL_ON_RELAYOUT), &DoConnectSignal);
+SignalConnectorType signalConnector7(mType, std::string(SIGNAL_TOUCHED), &DoConnectSignal);
+SignalConnectorType signalConnector8(mType, std::string(SIGNAL_VISIBILITY_CHANGED), &DoConnectSignal);
+SignalConnectorType signalConnector9(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &DoConnectSignal);
+SignalConnectorType signalConnector10(mType, std::string(SIGNAL_CHILD_ADDED), &DoConnectSignal);
+SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_REMOVED), &DoConnectSignal);
-TypeAction a1(mType, std::string(ACTION_SHOW), &Actor::DoAction);
-TypeAction a2(mType, std::string(ACTION_HIDE), &Actor::DoAction);
+TypeAction a1(mType, std::string(ACTION_SHOW), &DoAction);
+TypeAction a2(mType, std::string(ACTION_HIDE), &DoAction);
/**
* @brief Extract a given dimension from a Vector2
}
}
-bool ScreenToLocalInternal(
- const Matrix& viewMatrix,
- const Matrix& projectionMatrix,
- const Matrix& worldMatrix,
- const Viewport& viewport,
- const Vector3& currentSize,
- float& localX,
- float& localY,
- float screenX,
- float screenY)
-{
- // Get the ModelView matrix
- Matrix modelView;
- Matrix::Multiply(modelView, worldMatrix, viewMatrix);
-
- // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
- Matrix invertedMvp(false /*don't init*/);
- Matrix::Multiply(invertedMvp, modelView, projectionMatrix);
- bool success = invertedMvp.Invert();
+using ActorParentSiblingOrderMethod = void (ActorParent::*)(Actor&);
+using ActorParentSiblingOrderMethodWithTarget = void (ActorParent::*)(Actor&, Actor&);
- // Convert to GL coordinates
- Vector4 screenPos(screenX - static_cast<float>(viewport.x), static_cast<float>(viewport.height) - screenY - static_cast<float>(viewport.y), 0.f, 1.f);
-
- Vector4 nearPos;
- if(success)
+/// Helper to check and call actor sibling methods in ActorParent
+void CheckParentAndCall(ActorParent* parent, Actor& actor, ActorParentSiblingOrderMethod memberFunction)
+{
+ if(parent)
{
- success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), nearPos);
+ (parent->*memberFunction)(actor);
}
-
- Vector4 farPos;
- if(success)
+ else
{
- screenPos.z = 1.0f;
- success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), farPos);
+ DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
}
+}
- if(success)
+/// Helper to check and call actor sibling methods with a target parameter in ActorParent
+void CheckParentAndCall(ActorParent* parent, Actor& actor, Actor& target, ActorParentSiblingOrderMethodWithTarget memberFunction)
+{
+ if(parent)
{
- Vector4 local;
- if(XyPlaneIntersect(nearPos, farPos, local))
- {
- Vector3 size = currentSize;
- localX = local.x + size.x * 0.5f;
- localY = local.y + size.y * 0.5f;
- }
- else
- {
- success = false;
- }
+ (parent->*memberFunction)(actor, target);
+ }
+ else
+ {
+ DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
}
-
- return success;
}
} // unnamed namespace
const Vector3& Actor::GetSizeModeFactor() const
{
- if(mRelayoutData)
- {
- return mRelayoutData->sizeModeFactor;
- }
-
- return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
+ return mRelayoutData ? mRelayoutData->sizeModeFactor : Relayouter::DEFAULT_SIZE_MODE_FACTOR;
}
void Actor::SetColorMode(ColorMode colorMode)
{
mTargetSize = size;
+ // Update the preferred size after relayoutting
+ // It should be used in the next relayoutting
+ if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH && mRelayoutData)
+ {
+ mRelayoutData->preferredSize.width = mAnimatedSize.width;
+ }
+
+ if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT && mRelayoutData)
+ {
+ mRelayoutData->preferredSize.height = mAnimatedSize.height;
+ }
+
// node is being used in a separate thread; queue a message to set the value & base value
SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize);
ResizePolicy::Type Actor::GetResizePolicy(Dimension::Type dimension) const
{
- if(mRelayoutData)
- {
- return mRelayoutData->GetResizePolicy(dimension);
- }
-
- return ResizePolicy::DEFAULT;
+ return mRelayoutData ? mRelayoutData->GetResizePolicy(dimension) : ResizePolicy::DEFAULT;
}
void Actor::SetSizeScalePolicy(SizeScalePolicy::Type policy)
SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
{
- if(mRelayoutData)
- {
- return mRelayoutData->sizeSetPolicy;
- }
-
- return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
+ return mRelayoutData ? mRelayoutData->sizeSetPolicy : Relayouter::DEFAULT_SIZE_SCALE_POLICY;
}
void Actor::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
Dimension::Type Actor::GetDimensionDependency(Dimension::Type dimension) const
{
- if(mRelayoutData)
- {
- return mRelayoutData->GetDimensionDependency(dimension);
- }
-
- return Dimension::ALL_DIMENSIONS; // Default
+ return mRelayoutData ? mRelayoutData->GetDimensionDependency(dimension) : Dimension::ALL_DIMENSIONS;
}
void Actor::SetRelayoutEnabled(bool relayoutEnabled)
{
if(!mRenderers)
{
- mRenderers = new RendererContainer;
+ mRenderers = new RendererContainer(GetEventThreadServices());
}
-
- if(mIsBlendEquationSet)
- {
- renderer.SetBlendEquation(static_cast<DevelBlendEquation::Type>(mBlendEquation));
- }
-
- uint32_t index = static_cast<uint32_t>(mRenderers->size()); // 4,294,967,295 renderers per actor
- RendererPtr rendererPtr = RendererPtr(&renderer);
- mRenderers->push_back(rendererPtr);
- AttachRendererMessage(GetEventThreadServices().GetUpdateManager(), GetNode(), renderer.GetRendererSceneObject());
- return index;
+ return mRenderers->Add(GetNode(), renderer, mIsBlendEquationSet, mBlendEquation);
}
uint32_t Actor::GetRendererCount() const
{
- uint32_t rendererCount(0);
- if(mRenderers)
- {
- rendererCount = static_cast<uint32_t>(mRenderers->size()); // 4,294,967,295 renderers per actor
- }
-
- return rendererCount;
+ return mRenderers ? mRenderers->GetCount() : 0u;
}
RendererPtr Actor::GetRendererAt(uint32_t index)
{
- RendererPtr renderer;
- if(index < GetRendererCount())
- {
- renderer = (*mRenderers)[index];
- }
-
- return renderer;
+ return mRenderers ? mRenderers->GetRendererAt(index) : nullptr;
}
void Actor::RemoveRenderer(Renderer& renderer)
{
if(mRenderers)
{
- RendererIter end = mRenderers->end();
- for(RendererIter iter = mRenderers->begin(); iter != end; ++iter)
- {
- if((*iter).Get() == &renderer)
- {
- mRenderers->erase(iter);
- DetachRendererMessage(GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject());
- break;
- }
- }
+ mRenderers->Remove(GetNode(), renderer);
}
}
void Actor::RemoveRenderer(uint32_t index)
{
- if(index < GetRendererCount())
+ if(mRenderers)
{
- RendererPtr renderer = (*mRenderers)[index];
- DetachRendererMessage(GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject());
- mRenderers->erase(mRenderers->begin() + index);
+ mRenderers->Remove(GetNode(), index);
}
}
{
if(mBlendEquation != blendEquation)
{
- mBlendEquation = blendEquation;
- uint32_t rendererCount = GetRendererCount();
- for(uint32_t i = 0; i < rendererCount; ++i)
+ mBlendEquation = blendEquation;
+ if(mRenderers)
{
- RendererPtr renderer = GetRendererAt(i);
- renderer->SetBlendEquation(static_cast<DevelBlendEquation::Type>(blendEquation));
+ mRenderers->SetBlending(blendEquation);
}
}
mIsBlendEquationSet = true;
return mBlendEquation;
}
+void Actor::SetTransparent(bool transparent)
+{
+ SetTransparentMessage(GetEventThreadServices(), GetNode(), transparent);
+}
+
+bool Actor::IsTransparent() const
+{
+ return GetNode().IsTransparent();
+}
+
void Actor::SetDrawMode(DrawMode::Type drawMode)
{
// this flag is not animatable so keep the value
bool Actor::ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const
{
- // only valid when on-stage
- if(mScene && OnScene())
- {
- const RenderTaskList& taskList = mScene->GetRenderTaskList();
-
- Vector2 converted(screenX, screenY);
-
- // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
- uint32_t taskCount = taskList.GetTaskCount();
- for(uint32_t i = taskCount; i > 0; --i)
- {
- RenderTaskPtr task = taskList.GetTask(i - 1);
- if(ScreenToLocal(*task, localX, localY, screenX, screenY))
- {
- // found a task where this conversion was ok so return
- return true;
- }
- }
- }
- return false;
+ return mScene && OnScene() && ConvertScreenToLocalRenderTaskList(mScene->GetRenderTaskList(), GetNode().GetWorldMatrix(0), GetCurrentSize(), localX, localY, screenX, screenY);
}
bool Actor::ScreenToLocal(const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY) const
{
- bool retval = false;
- // only valid when on-stage
- if(OnScene())
- {
- CameraActor* camera = renderTask.GetCameraActor();
- if(camera)
- {
- Viewport viewport;
- renderTask.GetViewport(viewport);
-
- // need to translate coordinates to render tasks coordinate space
- Vector2 converted(screenX, screenY);
- if(renderTask.TranslateCoordinates(converted))
- {
- retval = ScreenToLocal(camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y);
- }
- }
- }
- return retval;
+ return OnScene() && ConvertScreenToLocalRenderTask(renderTask, GetNode().GetWorldMatrix(0), GetCurrentSize(), localX, localY, screenX, screenY);
}
bool Actor::ScreenToLocal(const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY) const
{
- return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
+ return OnScene() && ConvertScreenToLocal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), GetCurrentSize(), viewport, localX, localY, screenX, screenY);
}
ActorGestureData& Actor::GetGestureData()
return mParentImpl.ChildOrderChangedSignal();
}
-bool Actor::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
-{
- bool connected(true);
- Actor* actor = static_cast<Actor*>(object); // TypeRegistry guarantees that this is the correct type.
-
- std::string_view name(signalName);
-
- if(name == SIGNAL_HOVERED)
- {
- actor->HoveredSignal().Connect(tracker, functor);
- }
- else if(signalName == SIGNAL_WHEEL_EVENT)
- {
- actor->WheelEventSignal().Connect(tracker, functor);
- }
- else if(name == SIGNAL_ON_SCENE)
- {
- actor->OnSceneSignal().Connect(tracker, functor);
- }
- else if(name == SIGNAL_OFF_SCENE)
- {
- actor->OffSceneSignal().Connect(tracker, functor);
- }
- else if(name == SIGNAL_ON_RELAYOUT)
- {
- actor->OnRelayoutSignal().Connect(tracker, functor);
- }
- else if(name == SIGNAL_TOUCHED)
- {
- actor->TouchedSignal().Connect(tracker, functor);
- }
- else if(name == SIGNAL_VISIBILITY_CHANGED)
- {
- actor->VisibilityChangedSignal().Connect(tracker, functor);
- }
- else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED)
- {
- actor->LayoutDirectionChangedSignal().Connect(tracker, functor);
- }
- else if(name == SIGNAL_CHILD_ADDED)
- {
- actor->ChildAddedSignal().Connect(tracker, functor);
- }
- else if(name == SIGNAL_CHILD_REMOVED)
- {
- actor->ChildRemovedSignal().Connect(tracker, functor);
- }
- else
- {
- // signalName does not match any signal
- connected = false;
- }
-
- return connected;
-}
-
Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
: Object(&node),
mParentImpl(*this),
mSensitive(true),
mLeaveRequired(false),
mKeyboardFocusable(false),
+ mKeyboardFocusableChildren(true),
mTouchFocusable(false),
mOnSceneSignalled(false),
mInsideOnSizeSet(false),
delete mRelayoutData;
}
-void Actor::Add(Actor& child)
+void Actor::Add(Actor& child, bool notify)
{
- mParentImpl.Add(child);
+ mParentImpl.Add(child, notify);
}
-void Actor::Remove(Actor& child)
+void Actor::Remove(Actor& child, bool notify)
{
- mParentImpl.Remove(child);
+ mParentImpl.Remove(child, notify);
+}
+
+void Actor::SwitchParent(Actor& newParent)
+{
+ if(this == &newParent)
+ {
+ DALI_LOG_ERROR("Cannot add actor to itself");
+ return;
+ }
+
+ if(!this->OnScene() || !newParent.OnScene())
+ {
+ DALI_LOG_ERROR("Both of current parent and new parent must be on Scene");
+ return;
+ }
+
+ newParent.Add(*this, false);
}
uint32_t Actor::GetChildCount() const
mParentImpl.UnparentChildren();
}
-void Actor::ConnectToScene(uint32_t parentDepth)
+void Actor::ConnectToScene(uint32_t parentDepth, bool notify)
{
// This container is used instead of walking the Actor hierarchy.
// It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
mScene->RequestRebuildDepthTree();
}
- // This stage is atomic i.e. not interrupted by user callbacks.
- RecursiveConnectToScene(connectionList, parentDepth + 1);
+ // This stage is not interrupted by user callbacks.
+ mParentImpl.RecursiveConnectToScene(connectionList, parentDepth + 1);
// Notify applications about the newly connected actors.
for(const auto& actor : connectionList)
{
- actor->NotifyStageConnection();
+ actor->NotifyStageConnection(notify);
}
RelayoutRequest();
}
-void Actor::RecursiveConnectToScene(ActorContainer& connectionList, uint32_t depth)
-{
- DALI_ASSERT_ALWAYS(!OnScene());
-
- mIsOnScene = true;
- mDepth = static_cast<uint16_t>(depth); // overflow ignored, not expected in practice
-
- ConnectToSceneGraph();
-
- // Notification for internal derived classes
- OnSceneConnectionInternal();
-
- // This stage is atomic; avoid emitting callbacks until all Actors are connected
- connectionList.push_back(ActorPtr(this));
-
- // Recursively connect children
- if(GetChildCount() > 0)
- {
- for(const auto& child : mParentImpl.GetChildrenInternal())
- {
- child->SetScene(*mScene);
- child->RecursiveConnectToScene(connectionList, depth + 1);
- }
- }
-}
-
/**
* This method is called when the Actor is connected to the Stage.
* The parent must have added its Node to the scene-graph.
OnSceneObjectAdd();
}
-void Actor::NotifyStageConnection()
+void Actor::NotifyStageConnection(bool notify)
{
// Actors can be removed (in a callback), before the on-stage stage is reported.
// The actor may also have been reparented, in which case mOnSceneSignalled will be true.
if(OnScene() && !mOnSceneSignalled)
{
- // Notification for external (CustomActor) derived classes
- OnSceneConnectionExternal(mDepth);
-
- if(!mOnSceneSignal.Empty())
+ if(notify)
{
- Dali::Actor handle(this);
- mOnSceneSignal.Emit(handle);
+ // Notification for external (CustomActor) derived classes
+ OnSceneConnectionExternal(mDepth);
+
+ if(!mOnSceneSignal.Empty())
+ {
+ Dali::Actor handle(this);
+ mOnSceneSignal.Emit(handle);
+ }
}
// Guard against Remove during callbacks
}
}
-void Actor::DisconnectFromStage()
+void Actor::DisconnectFromStage(bool notify)
{
// This container is used instead of walking the Actor hierachy.
// It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
mScene->RequestRebuildDepthTree();
}
- // This stage is atomic i.e. not interrupted by user callbacks
- RecursiveDisconnectFromStage(disconnectionList);
+ // This stage is not interrupted by user callbacks
+ mParentImpl.RecursiveDisconnectFromScene(disconnectionList);
// Notify applications about the newly disconnected actors.
for(const auto& actor : disconnectionList)
{
- actor->NotifyStageDisconnection();
+ actor->NotifyStageDisconnection(notify);
}
}
-void Actor::RecursiveDisconnectFromStage(ActorContainer& disconnectionList)
-{
- // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
- mIsOnScene = false;
-
- // Recursively disconnect children
- if(GetChildCount() > 0)
- {
- for(const auto& child : mParentImpl.GetChildrenInternal())
- {
- child->RecursiveDisconnectFromStage(disconnectionList);
- }
- }
-
- // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
- disconnectionList.push_back(ActorPtr(this));
-
- // Notification for internal derived classes
- OnSceneDisconnectionInternal();
-
- DisconnectFromSceneGraph();
-}
-
/**
* This method is called by an actor or its parent, before a node removal message is sent.
* This is recursive; the child calls DisconnectFromStage() for its children.
OnSceneObjectRemove();
}
-void Actor::NotifyStageDisconnection()
+void Actor::NotifyStageDisconnection(bool notify)
{
// Actors can be added (in a callback), before the off-stage state is reported.
// Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
// only do this step if there is a stage, i.e. Core is not being shut down
if(EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled)
{
- // Notification for external (CustomeActor) derived classes
- OnSceneDisconnectionExternal();
-
- if(!mOffSceneSignal.Empty())
+ if(notify)
{
- Dali::Actor handle(this);
- mOffSceneSignal.Emit(handle);
+ // Notification for external (CustomeActor) derived classes
+ OnSceneDisconnectionExternal();
+
+ if(!mOffSceneSignal.Empty())
+ {
+ Dali::Actor handle(this);
+ mOffSceneSignal.Emit(handle);
+ }
}
// Guard against Add during callbacks
bool Actor::IsNodeConnected() const
{
- bool connected(false);
-
- if(OnScene())
- {
- if(IsRoot() || GetNode().GetParent())
- {
- connected = true;
- }
- }
-
- return connected;
+ return OnScene() && (IsRoot() || GetNode().GetParent());
}
// This method initiates traversal of the actor tree using depth-first
OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths(new SceneGraph::NodeDepths());
int32_t depthIndex = 1;
- DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
+ mParentImpl.DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
SetDepthIndicesMessage(GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths);
DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
}
-void Actor::DepthTraverseActorTree(OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex)
-{
- mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
- sceneGraphNodeDepths->Add(const_cast<SceneGraph::Node*>(&GetNode()), mSortedDepth);
-
- // Create/add to children of this node
- if(GetChildCount() > 0)
- {
- for(const auto& child : mParentImpl.GetChildrenInternal())
- {
- Actor* childActor = child.Get();
- ++depthIndex;
- childActor->DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
- }
- }
-}
-
void Actor::SetDefaultProperty(Property::Index index, const Property::Value& property)
{
PropertyHandler::SetDefaultProperty(*this, index, property);
void Actor::Raise()
{
- if(mParent)
- {
- mParent->RaiseChild(*this);
- }
- else
- {
- DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
- }
+ CheckParentAndCall(mParent, *this, &ActorParent::RaiseChild);
}
void Actor::Lower()
{
- if(mParent)
- {
- mParent->LowerChild(*this);
- }
- else
- {
- DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
- }
+ CheckParentAndCall(mParent, *this, &ActorParent::LowerChild);
}
void Actor::RaiseToTop()
{
- if(mParent)
- {
- mParent->RaiseChildToTop(*this);
- }
- else
- {
- DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
- }
+ CheckParentAndCall(mParent, *this, &ActorParent::RaiseChildToTop);
}
void Actor::LowerToBottom()
{
- if(mParent)
- {
- mParent->LowerChildToBottom(*this);
- }
- else
- {
- DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
- }
+ CheckParentAndCall(mParent, *this, &ActorParent::LowerChildToBottom);
}
void Actor::RaiseAbove(Internal::Actor& target)
{
- if(mParent)
- {
- mParent->RaiseChildAbove(*this, target);
- }
- else
- {
- DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
- }
+ CheckParentAndCall(mParent, *this, target, &ActorParent::RaiseChildAbove);
}
void Actor::LowerBelow(Internal::Actor& target)
{
- if(mParent)
- {
- mParent->LowerChildBelow(*this, target);
- }
- else
- {
- DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
- }
+ CheckParentAndCall(mParent, *this, target, &ActorParent::LowerChildBelow);
}
-void Actor::SetParent(ActorParent* parent)
+void Actor::SetParent(ActorParent* parent, bool notify)
{
if(parent)
{
parentActor->OnScene())
{
// Instruct each actor to create a corresponding node in the scene graph
- ConnectToScene(parentActor->GetHierarchyDepth());
+ ConnectToScene(parentActor->GetHierarchyDepth(), notify);
}
// Resolve the name and index for the child properties if any
DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
// Instruct each actor to discard pointers to the scene-graph
- DisconnectFromStage();
+ DisconnectFromStage(notify);
}
mScene = nullptr;
}
}
-bool Actor::DoAction(BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */)
-{
- bool done = false;
- Actor* actor = dynamic_cast<Actor*>(object);
-
- if(actor)
- {
- std::string_view name(actionName);
- if(name == ACTION_SHOW)
- {
- actor->SetVisible(true);
- done = true;
- }
- else if(name == ACTION_HIDE)
- {
- actor->SetVisible(false);
- done = true;
- }
- }
-
- return done;
-}
-
Rect<> Actor::CalculateScreenExtents() const
{
auto screenPosition = GetCurrentScreenPosition();
return {position.x, position.y, size.x, size.y};
}
-void Actor::SetNeedGesturePropagation(bool propagation)
-{
- mNeedGesturePropagation = propagation;
-}
-
-bool Actor::NeedGesturePropagation()
-{
- return mNeedGesturePropagation;
-}
-
bool Actor::GetCachedPropertyValue(Property::Index index, Property::Value& value) const
{
return PropertyHandler::GetCachedPropertyValue(*this, index, value);
bool Actor::RelayoutDependentOnParent(Dimension::Type dimension)
{
- // Check if actor is dependent on parent
- for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
- {
- if((dimension & (1 << i)))
- {
- const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
- if(resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT)
- {
- return true;
- }
- }
- }
-
- return false;
+ return mRelayoutData && mRelayoutData->GetRelayoutDependentOnParent(dimension);
}
bool Actor::RelayoutDependentOnChildren(Dimension::Type dimension)
{
- // Check if actor is dependent on children
- for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
- {
- if((dimension & (1 << i)))
- {
- const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
- switch(resizePolicy)
- {
- case ResizePolicy::FIT_TO_CHILDREN:
- case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
- {
- return true;
- }
-
- default:
- {
- break;
- }
- }
- }
- }
-
- return false;
+ return mRelayoutData && mRelayoutData->GetRelayoutDependentOnChildren(dimension);
}
bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
bool Actor::RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension)
{
- // Check each possible dimension and see if it is dependent on the input one
- for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
- {
- if(dimension & (1 << i))
- {
- return mRelayoutData->resizePolicies[i] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[i] == dependentDimension;
- }
- }
-
- return false;
+ return mRelayoutData && mRelayoutData->GetRelayoutDependentOnDimension(dimension, dependentDimension);
}
void Actor::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
{
- for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
+ if(mRelayoutData)
{
- if(dimension & (1 << i))
- {
- mRelayoutData->negotiatedDimensions[i] = negotiatedDimension;
- }
+ mRelayoutData->SetNegotiatedDimension(negotiatedDimension, dimension);
}
}
float Actor::GetNegotiatedDimension(Dimension::Type dimension) const
{
- // If more than one dimension is requested, just return the first one found
- for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
- {
- if((dimension & (1 << i)))
- {
- return mRelayoutData->negotiatedDimensions[i];
- }
- }
-
- return 0.0f; // Default
+ return mRelayoutData ? mRelayoutData->GetNegotiatedDimension(dimension) : 0.0f;
}
void Actor::SetPadding(const Vector2& padding, Dimension::Type dimension)
Vector2 Actor::GetPadding(Dimension::Type dimension) const
{
- if(mRelayoutData)
- {
- // If more than one dimension is requested, just return the first one found
- for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
- {
- if((dimension & (1 << i)))
- {
- return mRelayoutData->dimensionPadding[i];
- }
- }
- }
-
- return Relayouter::DEFAULT_DIMENSION_PADDING;
+ return mRelayoutData ? mRelayoutData->GetPadding(dimension) : Relayouter::DEFAULT_DIMENSION_PADDING;
}
void Actor::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
float Actor::GetHeightForWidthBase(float width)
{
- float height = 0.0f;
-
const Vector3 naturalSize = GetNaturalSize();
- if(naturalSize.width > 0.0f)
- {
- height = naturalSize.height * width / naturalSize.width;
- }
- else // we treat 0 as 1:1 aspect ratio
- {
- height = width;
- }
-
- return height;
+ return naturalSize.width > 0.0f ? naturalSize.height * width / naturalSize.width : width;
}
float Actor::GetWidthForHeightBase(float height)
{
- float width = 0.0f;
-
const Vector3 naturalSize = GetNaturalSize();
- if(naturalSize.height > 0.0f)
- {
- width = naturalSize.width * height / naturalSize.height;
- }
- else // we treat 0 as 1:1 aspect ratio
- {
- width = height;
- }
-
- return width;
+ return naturalSize.height > 0.0f ? naturalSize.width * height / naturalSize.height : height;
}
float Actor::CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension)
Dali::Actor handle(this);
mOnRelayoutSignal.Emit(handle);
}
+
+ mRelayoutData->relayoutRequested = false;
}
void Actor::NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container)
{
Dali::Actor self(this);
relayoutController->RequestRelayout(self, dimension);
+
+ if(mRelayoutData)
+ {
+ mRelayoutData->relayoutRequested = true;
+ }
}
}
Vector2 Actor::GetPreferredSize() const
{
- if(mRelayoutData)
- {
- return Vector2(mRelayoutData->preferredSize);
- }
-
- return Relayouter::DEFAULT_PREFERRED_SIZE;
+ return mRelayoutData ? Vector2(mRelayoutData->preferredSize) : Relayouter::DEFAULT_PREFERRED_SIZE;
}
void Actor::SetMinimumSize(float size, Dimension::Type dimension)
float Actor::GetMinimumSize(Dimension::Type dimension) const
{
- if(mRelayoutData)
- {
- return mRelayoutData->GetMinimumSize(dimension);
- }
-
- return 0.0f; // Default
+ return mRelayoutData ? mRelayoutData->GetMinimumSize(dimension) : 0.0f;
}
void Actor::SetMaximumSize(float size, Dimension::Type dimension)
float Actor::GetMaximumSize(Dimension::Type dimension) const
{
- if(mRelayoutData)
- {
- return mRelayoutData->GetMaximumSize(dimension);
- }
-
- return FLT_MAX; // Default
+ return mRelayoutData ? mRelayoutData->GetMaximumSize(dimension) : FLT_MAX;
}
void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage)
mVisible = visible;
// Emit the signal on this actor and all its children
- EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::SELF);
+ mParentImpl.EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::SELF);
}
}
if(inherit && mParent)
{
- InheritLayoutDirectionRecursively(GetParent()->mLayoutDirection);
- }
- }
-}
-
-void Actor::InheritLayoutDirectionRecursively(Dali::LayoutDirection::Type direction, bool set)
-{
- if(mInheritLayoutDirection || set)
- {
- if(mLayoutDirection != direction)
- {
- mLayoutDirection = direction;
- EmitLayoutDirectionChangedSignal(direction);
- RelayoutRequest();
- }
-
- if(GetChildCount() > 0)
- {
- for(const auto& child : mParentImpl.GetChildrenInternal())
- {
- child->InheritLayoutDirectionRecursively(direction);
- }
+ mParentImpl.InheritLayoutDirectionRecursively(GetParent()->mLayoutDirection);
}
}
}
SceneGraph::NodePropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f));
}
-void Actor::EmitVisibilityChangedSignalRecursively(bool visible,
- DevelActor::VisibilityChange::Type type)
-{
- EmitVisibilityChangedSignal(visible, type);
-
- if(GetChildCount() > 0)
- {
- for(auto& child : mParentImpl.GetChildrenInternal())
- {
- child->EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::PARENT);
- }
- }
-}
-
} // namespace Internal
} // namespace Dali