Minor reduce IntrusivePtr<Actor>'s meanless Reference and Unreference
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-parent-impl.cpp
1 /*
2  * Copyright (c) 2024 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 // CLASS HEADER
18 #include <dali/internal/event/actors/actor-parent.h>
19
20 // INTERNAL INCLUDES
21 #include <dali/devel-api/actors/layer-devel.h>
22 #include <dali/internal/event/actors/actor-impl.h>
23 #include <dali/internal/event/common/scene-impl.h>
24 #include <dali/public-api/common/vector-wrapper.h>
25
26 // EXTERNAL INCLUDES
27 #include <algorithm>
28
29 namespace Dali
30 {
31 namespace Internal
32 {
33 namespace
34 {
35 /// Helper for emitting signals with multiple parameters
36 template<typename Signal, typename... Param>
37 void EmitSignal(Actor& actor, Signal& signal, Param... params)
38 {
39   if(!signal.Empty())
40   {
41     Dali::Actor handle(&actor);
42     signal.Emit(handle, params...);
43   }
44 }
45
46 } //anonymous namespace
47
48 ActorParentImpl::ActorParentImpl(Actor& owner)
49 : mOwner(owner),
50   mChildAddedSignal(),
51   mChildRemovedSignal(),
52   mChildOrderChangedSignal()
53 {
54 }
55
56 ActorParentImpl::~ActorParentImpl()
57 {
58   delete mChildren;
59 }
60
61 void ActorParentImpl::Add(Actor& child, bool notify)
62 {
63   DALI_ASSERT_ALWAYS(&mOwner != &child && "Cannot add actor to itself");
64   DALI_ASSERT_ALWAYS(!child.IsRoot() && "Cannot add root actor");
65
66   if(!mChildren)
67   {
68     mChildren = new ActorContainer;
69   }
70
71   Actor* oldParent = child.GetParent();
72
73   // child might already be ours
74   if(&mOwner != oldParent)
75   {
76     // if we already have parent, unparent us first
77     if(oldParent)
78     {
79       oldParent->Remove(child, notify); // This causes OnChildRemove callback & ChildRemoved signal
80
81       // Old parent may need to readjust to missing child
82       if(oldParent->RelayoutDependentOnChildren())
83       {
84         oldParent->RelayoutRequest();
85       }
86     }
87
88     // Guard against Add() during previous OnChildRemove callback
89     if(!child.GetParent())
90     {
91       // Do this first, since user callbacks from within SetParent() may need to remove child
92       mChildren->push_back(ActorPtr(&child));
93
94       // SetParent asserts that child can be added
95       child.SetParent(&mOwner, notify);
96
97       if(notify)
98       {
99         // Notification for derived classes
100         mOwner.OnChildAdd(child);
101         EmitChildAddedSignal(child);
102       }
103
104       child.mParentImpl.InheritLayoutDirectionRecursively(mOwner.GetLayoutDirection());
105
106       // Only put in a relayout request if there is a suitable dependency
107       if(mOwner.RelayoutDependentOnChildren())
108       {
109         mOwner.RelayoutRequest();
110       }
111     }
112   }
113 }
114
115 void ActorParentImpl::Remove(Actor& child, bool notify)
116 {
117   if((&mOwner == &child) || (!mChildren))
118   {
119     // no children or removing itself
120     return;
121   }
122
123   ActorPtr removed;
124
125   // Find the child in mChildren, and unparent it
126   ActorIter end = mChildren->end();
127   for(ActorIter iter = mChildren->begin(); iter != end; ++iter)
128   {
129     if((*iter).Get() == &child)
130     {
131       // Keep handle for OnChildRemove notification
132       removed = (*iter);
133
134       // Do this first, since user callbacks from within SetParent() may need to add the child
135       mChildren->erase(iter);
136
137       DALI_ASSERT_DEBUG(removed->GetParent() == &mOwner);
138       removed->SetParent(nullptr, notify);
139
140       break;
141     }
142   }
143
144   if(removed)
145   {
146     // Only put in a relayout request if there is a suitable dependency
147     if(mOwner.RelayoutDependentOnChildren())
148     {
149       mOwner.RelayoutRequest();
150     }
151   }
152
153   if(notify)
154   {
155     // Notification for derived classes
156     mOwner.OnChildRemove(child);
157     EmitChildRemovedSignal(child);
158   }
159 }
160
161 uint32_t ActorParentImpl::GetChildCount() const
162 {
163   return (nullptr != mChildren) ? static_cast<uint32_t>(mChildren->size()) : 0; // only 4,294,967,295 children per actor
164 }
165
166 ActorPtr ActorParentImpl::GetChildAt(uint32_t index) const
167 {
168   DALI_ASSERT_ALWAYS(index < GetChildCount());
169
170   return ((mChildren) ? (*mChildren)[index] : ActorPtr());
171 }
172
173 ActorPtr ActorParentImpl::FindChildByName(ConstString actorName)
174 {
175   ActorPtr child = nullptr;
176   if(actorName.GetStringView() == mOwner.GetName())
177   {
178     child = &mOwner;
179   }
180   else if(mChildren)
181   {
182     for(const auto& actor : *mChildren)
183     {
184       child = actor->FindChildByName(actorName);
185
186       if(child)
187       {
188         break;
189       }
190     }
191   }
192   return child;
193 }
194
195 ActorPtr ActorParentImpl::FindChildById(const uint32_t id)
196 {
197   ActorPtr child = nullptr;
198   if(id == mOwner.GetId())
199   {
200     child = &mOwner;
201   }
202   else if(mChildren)
203   {
204     for(const auto& actor : *mChildren)
205     {
206       child = actor->FindChildById(id);
207
208       if(child)
209       {
210         break;
211       }
212     }
213   }
214   return child;
215 }
216
217 void ActorParentImpl::UnparentChildren()
218 {
219   if(mChildren)
220   {
221     for(const auto& child : *mChildren)
222     {
223       child->SetParent(nullptr);
224     }
225   }
226 }
227
228 void ActorParentImpl::SetSiblingOrderOfChild(
229   Actor&   child,
230   uint32_t order)
231 {
232   if(mChildren && !mChildren->empty())
233   {
234     uint32_t currentOrder = GetSiblingOrderOfChild(child);
235     if(order != currentOrder)
236     {
237       if(order == 0)
238       {
239         LowerChildToBottom(child);
240       }
241       else if(order < mChildren->size() - 1)
242       {
243         if(order > currentOrder)
244         {
245           RaiseChildAbove(child, *((*mChildren)[order]));
246         }
247         else
248         {
249           LowerChildBelow(child, *((*mChildren)[order]));
250         }
251       }
252       else
253       {
254         RaiseChildToTop(child);
255       }
256     }
257   }
258 }
259
260 uint32_t ActorParentImpl::GetSiblingOrderOfChild(const Actor& child) const
261 {
262   uint32_t order = 0;
263   if(mChildren && !mChildren->empty())
264   {
265     for(std::size_t i = 0; i < mChildren->size(); ++i)
266     {
267       if((*mChildren)[i] == &child)
268       {
269         order = static_cast<uint32_t>(i);
270         break;
271       }
272     }
273   }
274   return order;
275 }
276
277 void ActorParentImpl::RaiseChild(Actor& child)
278 {
279   bool changed = false;
280   if(mChildren && !mChildren->empty() && mChildren->back() != &child) // If not already at end
281   {
282     for(std::size_t i = 0; i + 1 < mChildren->size(); ++i)
283     {
284       if((*mChildren)[i] == &child)
285       {
286         // Swap with next
287         ActorPtr next       = std::move((*mChildren)[i + 1]);
288         (*mChildren)[i + 1] = &child;
289         (*mChildren)[i]     = std::move(next);
290         changed             = true;
291         break;
292       }
293     }
294   }
295   if(changed)
296   {
297     EmitOrderChangedAndRebuild(child);
298   }
299 }
300
301 void ActorParentImpl::LowerChild(Actor& child)
302 {
303   bool changed = false;
304   if(mChildren && !mChildren->empty() && mChildren->front() != &child) // If not already at beginning
305   {
306     for(std::size_t i = 1; i < mChildren->size(); ++i)
307     {
308       if((*mChildren)[i] == &child)
309       {
310         // Swap with previous
311         ActorPtr previous   = std::move((*mChildren)[i - 1]);
312         (*mChildren)[i - 1] = &child;
313         (*mChildren)[i]     = std::move(previous);
314         changed             = true;
315         break;
316       }
317     }
318   }
319   if(changed)
320   {
321     EmitOrderChangedAndRebuild(child);
322   }
323 }
324
325 void ActorParentImpl::RaiseChildToTop(Actor& child)
326 {
327   bool changed = false;
328   if(mChildren && !mChildren->empty() && mChildren->back() != &child) // If not already at end
329   {
330     auto iter = std::find(mChildren->begin(), mChildren->end(), &child);
331     if(iter != mChildren->end())
332     {
333       ActorPtr childPtr(&child); // ensure actor remains referenced.
334
335       mChildren->erase(iter);
336       mChildren->push_back(childPtr);
337       changed = true;
338     }
339   }
340   if(changed)
341   {
342     EmitOrderChangedAndRebuild(child);
343   }
344 }
345
346 void ActorParentImpl::LowerChildToBottom(Actor& child)
347 {
348   bool changed = false;
349   if(mChildren && !mChildren->empty() && mChildren->front() != &child) // If not already at bottom,
350   {
351     auto iter = std::find(mChildren->begin(), mChildren->end(), &child);
352     if(iter != mChildren->end())
353     {
354       ActorPtr childPtr(&child); // ensure actor remains referenced.
355
356       mChildren->erase(iter);
357       mChildren->insert(mChildren->begin(), childPtr);
358       changed = true;
359     }
360   }
361   if(changed)
362   {
363     EmitOrderChangedAndRebuild(child);
364   }
365 }
366
367 void ActorParentImpl::RaiseChildAbove(Actor& child, Actor& target)
368 {
369   bool raised = false;
370   if(mChildren && !mChildren->empty() && mChildren->back() != &child && target.GetParent() == child.GetParent()) // If not already at top
371   {
372     auto targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
373     auto childIter  = std::find(mChildren->begin(), mChildren->end(), &child);
374     if(childIter < targetIter)
375     {
376       ActorPtr childPtr(&child); // ensure actor actor remains referenced.
377
378       mChildren->erase(childIter);
379       // Erasing early invalidates the targetIter. (Conversely, inserting first may also
380       // invalidate actorIter)
381       targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
382       ++targetIter;
383       mChildren->insert(targetIter, childPtr);
384     }
385     raised = true;
386   }
387   if(raised)
388   {
389     EmitOrderChangedAndRebuild(child);
390   }
391 }
392
393 void ActorParentImpl::LowerChildBelow(Actor& child, Actor& target)
394 {
395   bool lowered = false;
396
397   // If not already at bottom
398   if(mChildren && !mChildren->empty() && mChildren->front() != &child && target.GetParent() == child.GetParent())
399   {
400     auto targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
401     auto childIter  = std::find(mChildren->begin(), mChildren->end(), &child);
402
403     if(childIter > targetIter)
404     {
405       ActorPtr childPtr(&child); // ensure actor actor remains referenced.
406
407       mChildren->erase(childIter); // actor only invalidates iterators at or after actor point.
408       mChildren->insert(targetIter, childPtr);
409     }
410     lowered = true;
411   }
412   if(lowered)
413   {
414     EmitOrderChangedAndRebuild(child);
415   }
416 }
417
418 void ActorParentImpl::DepthTraverseActorTree(OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths,
419                                              int32_t&                              depthIndex)
420 {
421   uint32_t sortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
422   mOwner.SetSortingDepth(sortedDepth);
423   sceneGraphNodeDepths->Add(const_cast<SceneGraph::Node*>(&mOwner.GetNode()), sortedDepth);
424
425   // Create/add to children of this node
426   if(mChildren)
427   {
428     for(const auto& actor : *mChildren)
429     {
430       ++depthIndex;
431       actor->mParentImpl.DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
432     }
433   }
434 }
435
436 void ActorParentImpl::RecursiveConnectToScene(ActorContainer& connectionList, uint32_t layer3DParentsCount, uint32_t depth)
437 {
438   DALI_ASSERT_ALWAYS(!mOwner.OnScene());
439
440   if(mOwner.mIsLayer)
441   {
442     if(static_cast<Dali::Internal::Layer*>(&mOwner)->GetBehavior() == Dali::Layer::Behavior::LAYER_3D)
443     {
444       // This is 3d layer. Propagate it to all children.
445       ++layer3DParentsCount;
446     }
447   }
448
449   mOwner.mIsOnScene           = true;
450   mOwner.mDepth               = static_cast<uint16_t>(depth);               // overflow ignored, not expected in practice
451   mOwner.mLayer3DParentsCount = static_cast<uint16_t>(layer3DParentsCount); // overflow ignored, not expected in practice
452   mOwner.ConnectToSceneGraph();
453
454   // Notification for internal derived classes
455   mOwner.OnSceneConnectionInternal();
456
457   // This stage is atomic; avoid emitting callbacks until all Actors are connected
458   connectionList.push_back(ActorPtr(&mOwner));
459
460   // Recursively connect children
461   if(mChildren)
462   {
463     for(const auto& actor : *mChildren)
464     {
465       actor->SetScene(*mOwner.mScene);
466       actor->mParentImpl.RecursiveConnectToScene(connectionList, layer3DParentsCount, depth + 1);
467     }
468   }
469 }
470
471 void ActorParentImpl::RecursiveDisconnectFromScene(ActorContainer& disconnectionList)
472 {
473   // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
474   mOwner.mIsOnScene           = false;
475   mOwner.mScene               = nullptr;
476   mOwner.mLayer3DParentsCount = 0;
477
478   // Recursively disconnect children
479   if(mChildren)
480   {
481     for(const auto& actor : *mChildren)
482     {
483       actor->mParentImpl.RecursiveDisconnectFromScene(disconnectionList);
484     }
485   }
486
487   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
488   disconnectionList.push_back(ActorPtr(&mOwner));
489
490   // Notification for internal derived classes
491   mOwner.OnSceneDisconnectionInternal();
492   mOwner.DisconnectFromSceneGraph();
493 }
494
495 void ActorParentImpl::RecursiveChangeLayer3dCount(int32_t layer3DParentsCountDiff)
496 {
497   mOwner.mLayer3DParentsCount += layer3DParentsCountDiff; // overflow ignored, not expected in practice
498
499   // Recursively change the value
500   if(mChildren)
501   {
502     for(const auto& actor : *mChildren)
503     {
504       actor->mParentImpl.RecursiveChangeLayer3dCount(layer3DParentsCountDiff);
505     }
506   }
507 }
508
509 void ActorParentImpl::InheritLayoutDirectionRecursively(Dali::LayoutDirection::Type direction, bool set)
510 {
511   if(mOwner.mInheritLayoutDirection || set)
512   {
513     if(mOwner.mLayoutDirection != direction)
514     {
515       mOwner.mLayoutDirection = direction;
516       mOwner.EmitLayoutDirectionChangedSignal(direction);
517       mOwner.RelayoutRequest();
518     }
519
520     if(mChildren)
521     {
522       for(const auto& child : *mChildren)
523       {
524         child->mParentImpl.InheritLayoutDirectionRecursively(direction);
525       }
526     }
527   }
528 }
529
530 void ActorParentImpl::EmitVisibilityChangedSignalRecursively(
531   bool                               visible,
532   DevelActor::VisibilityChange::Type type)
533 {
534   if(!visible && mOwner.OnScene())
535   {
536     //The actor should receive an interrupted event when it is hidden.
537     mOwner.GetScene().SendInterruptedEvents(&mOwner);
538   }
539
540   mOwner.EmitVisibilityChangedSignal(visible, type);
541
542   if(mChildren)
543   {
544     for(const auto& child : *mChildren)
545     {
546       child->mParentImpl.EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::PARENT);
547     }
548   }
549 }
550
551 void ActorParentImpl::EmitChildAddedSignal(Actor& child)
552 {
553   EmitSignal(child, mChildAddedSignal);
554 }
555
556 void ActorParentImpl::EmitChildRemovedSignal(Actor& child)
557 {
558   EmitSignal(child, mChildRemovedSignal);
559 }
560
561 void ActorParentImpl::EmitOrderChangedAndRebuild(Actor& child)
562 {
563   EmitSignal(child, mChildOrderChangedSignal);
564
565   if(mOwner.OnScene())
566   {
567     mOwner.GetScene().RequestRebuildDepthTree();
568   }
569 }
570
571 } // namespace Internal
572
573 } // namespace Dali