41a6e2ce8192a95672dd03f036403a35327057b8
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-parent-impl.cpp
1 /*
2  * Copyright (c) 2021 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/internal/event/actors/actor-impl.h>
22 #include <dali/internal/event/common/scene-impl.h>
23 #include <dali/public-api/common/vector-wrapper.h>
24
25 // EXTERNAL INCLUDES
26 #include <algorithm>
27
28 namespace Dali
29 {
30 namespace Internal
31 {
32 namespace
33 {
34 /// Helper for emitting signals with multiple parameters
35 template<typename Signal, typename... Param>
36 void EmitSignal(Actor& actor, Signal& signal, Param... params)
37 {
38   if(!signal.Empty())
39   {
40     Dali::Actor handle(&actor);
41     signal.Emit(handle, params...);
42   }
43 }
44
45 } //anonymous namespace
46
47 ActorParentImpl::ActorParentImpl(Actor& owner)
48 : mOwner(owner),
49   mChildAddedSignal(),
50   mChildRemovedSignal(),
51   mChildOrderChangedSignal()
52 {
53 }
54
55 ActorParentImpl::~ActorParentImpl()
56 {
57   delete mChildren;
58 }
59
60 void ActorParentImpl::Add(Actor& child, bool notify)
61 {
62   DALI_ASSERT_ALWAYS(&mOwner != &child && "Cannot add actor to itself");
63   DALI_ASSERT_ALWAYS(!child.IsRoot() && "Cannot add root actor");
64
65   if(!mChildren)
66   {
67     mChildren = new ActorContainer;
68   }
69
70   Actor* oldParent = child.GetParent();
71
72   // child might already be ours
73   if(&mOwner != oldParent)
74   {
75     // if we already have parent, unparent us first
76     if(oldParent)
77     {
78       oldParent->Remove(child, notify); // This causes OnChildRemove callback & ChildRemoved signal
79
80       // Old parent may need to readjust to missing child
81       if(oldParent->RelayoutDependentOnChildren())
82       {
83         oldParent->RelayoutRequest();
84       }
85     }
86
87     // Guard against Add() during previous OnChildRemove callback
88     if(!child.GetParent())
89     {
90       // Do this first, since user callbacks from within SetParent() may need to remove child
91       mChildren->push_back(ActorPtr(&child));
92
93       // SetParent asserts that child can be added
94       child.SetParent(&mOwner, notify);
95
96       if(notify)
97       {
98         // Notification for derived classes
99         mOwner.OnChildAdd(child);
100         EmitChildAddedSignal(child);
101       }
102
103       child.InheritLayoutDirectionRecursively(mOwner.GetLayoutDirection());
104
105       // Only put in a relayout request if there is a suitable dependency
106       if(mOwner.RelayoutDependentOnChildren())
107       {
108         mOwner.RelayoutRequest();
109       }
110     }
111   }
112 }
113
114 void ActorParentImpl::Remove(Actor& child, bool notify)
115 {
116   if((&mOwner == &child) || (!mChildren))
117   {
118     // no children or removing itself
119     return;
120   }
121
122   ActorPtr removed;
123
124   // Find the child in mChildren, and unparent it
125   ActorIter end = mChildren->end();
126   for(ActorIter iter = mChildren->begin(); iter != end; ++iter)
127   {
128     ActorPtr actor = (*iter);
129
130     if(actor.Get() == &child)
131     {
132       // Keep handle for OnChildRemove notification
133       removed = actor;
134
135       // Do this first, since user callbacks from within SetParent() may need to add the child
136       mChildren->erase(iter);
137
138       DALI_ASSERT_DEBUG(actor->GetParent() == &mOwner);
139       actor->SetParent(nullptr, notify);
140
141       break;
142     }
143   }
144
145   if(removed)
146   {
147     // Only put in a relayout request if there is a suitable dependency
148     if(mOwner.RelayoutDependentOnChildren())
149     {
150       mOwner.RelayoutRequest();
151     }
152   }
153
154   if(notify)
155   {
156     // Notification for derived classes
157     mOwner.OnChildRemove(child);
158     EmitChildRemovedSignal(child);
159   }
160 }
161
162 uint32_t ActorParentImpl::GetChildCount() const
163 {
164   return (nullptr != mChildren) ? static_cast<uint32_t>(mChildren->size()) : 0; // only 4,294,967,295 children per actor
165 }
166
167 ActorPtr ActorParentImpl::GetChildAt(uint32_t index) const
168 {
169   DALI_ASSERT_ALWAYS(index < GetChildCount());
170
171   return ((mChildren) ? (*mChildren)[index] : ActorPtr());
172 }
173
174 ActorPtr ActorParentImpl::FindChildByName(ConstString actorName)
175 {
176   ActorPtr child = nullptr;
177   if(actorName.GetStringView() == mOwner.GetName())
178   {
179     child = &mOwner;
180   }
181   else if(mChildren)
182   {
183     for(const auto& actor : *mChildren)
184     {
185       child = actor->FindChildByName(actorName);
186
187       if(child)
188       {
189         break;
190       }
191     }
192   }
193   return child;
194 }
195
196 ActorPtr ActorParentImpl::FindChildById(const uint32_t id)
197 {
198   ActorPtr child = nullptr;
199   if(id == mOwner.GetId())
200   {
201     child = &mOwner;
202   }
203   else if(mChildren)
204   {
205     for(const auto& actor : *mChildren)
206     {
207       child = actor->FindChildById(id);
208
209       if(child)
210       {
211         break;
212       }
213     }
214   }
215   return child;
216 }
217
218 void ActorParentImpl::UnparentChildren()
219 {
220   if(mChildren)
221   {
222     for(const auto& child : *mChildren)
223     {
224       child->SetParent(nullptr);
225     }
226   }
227 }
228
229 void ActorParentImpl::SetSiblingOrderOfChild(
230   Actor&   child,
231   uint32_t order)
232 {
233   if(mChildren)
234   {
235     uint32_t currentOrder = GetSiblingOrderOfChild(child);
236     if(order != currentOrder)
237     {
238       if(order == 0)
239       {
240         LowerChildToBottom(child);
241       }
242       else if(order < mChildren->size() - 1)
243       {
244         if(order > currentOrder)
245         {
246           RaiseChildAbove(child, *((*mChildren)[order]));
247         }
248         else
249         {
250           LowerChildBelow(child, *((*mChildren)[order]));
251         }
252       }
253       else
254       {
255         RaiseChildToTop(child);
256       }
257     }
258   }
259 }
260
261 uint32_t ActorParentImpl::GetSiblingOrderOfChild(const Actor& child) const
262 {
263   uint32_t order = 0;
264   if(mChildren)
265   {
266     for(std::size_t i = 0; i < mChildren->size(); ++i)
267     {
268       if((*mChildren)[i] == &child)
269       {
270         order = static_cast<uint32_t>(i);
271         break;
272       }
273     }
274   }
275   return order;
276 }
277
278 void ActorParentImpl::RaiseChild(Actor& child)
279 {
280   bool changed = false;
281   if(mChildren && mChildren->back() != &child) // If not already at end
282   {
283     for(std::size_t i = 0; i < mChildren->size(); ++i)
284     {
285       if((*mChildren)[i] == &child)
286       {
287         // Swap with next
288         ActorPtr next       = (*mChildren)[i + 1];
289         (*mChildren)[i + 1] = &child;
290         (*mChildren)[i]     = next;
291         changed             = true;
292         break;
293       }
294     }
295   }
296   if(changed)
297   {
298     EmitOrderChangedAndRebuild(child);
299   }
300 }
301
302 void ActorParentImpl::LowerChild(Actor& child)
303 {
304   bool changed = false;
305   if(mChildren && mChildren->front() != &child) // If not already at beginning
306   {
307     for(std::size_t i = 1; i < mChildren->size(); ++i)
308     {
309       if((*mChildren)[i] == &child)
310       {
311         // Swap with previous
312         ActorPtr previous   = (*mChildren)[i - 1];
313         (*mChildren)[i - 1] = &child;
314         (*mChildren)[i]     = previous;
315         changed             = true;
316         break;
317       }
318     }
319   }
320   if(changed)
321   {
322     EmitOrderChangedAndRebuild(child);
323   }
324 }
325
326 void ActorParentImpl::RaiseChildToTop(Actor& child)
327 {
328   bool changed = false;
329   if(mChildren && mChildren->back() != &child) // If not already at end
330   {
331     auto iter = std::find(mChildren->begin(), mChildren->end(), &child);
332     if(iter != mChildren->end())
333     {
334       mChildren->erase(iter);
335       mChildren->push_back(ActorPtr(&child));
336       changed = true;
337     }
338   }
339   if(changed)
340   {
341     EmitOrderChangedAndRebuild(child);
342   }
343 }
344
345 void ActorParentImpl::LowerChildToBottom(Actor& child)
346 {
347   bool changed = false;
348   if(mChildren && mChildren->front() != &child) // If not already at bottom,
349   {
350     ActorPtr childPtr(&child); // ensure actor remains referenced.
351
352     auto iter = std::find(mChildren->begin(), mChildren->end(), &child);
353     if(iter != mChildren->end())
354     {
355       mChildren->erase(iter);
356       mChildren->insert(mChildren->begin(), childPtr);
357       changed = true;
358     }
359   }
360   if(changed)
361   {
362     EmitOrderChangedAndRebuild(child);
363   }
364 }
365
366 void ActorParentImpl::RaiseChildAbove(Actor& child, Actor& target)
367 {
368   bool raised = false;
369   if(mChildren && mChildren->back() != &child && target.GetParent() == child.GetParent()) // If not already at top
370   {
371     ActorPtr childPtr(&child); // ensure actor actor remains referenced.
372
373     auto targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
374     auto childIter  = std::find(mChildren->begin(), mChildren->end(), &child);
375     if(childIter < targetIter)
376     {
377       mChildren->erase(childIter);
378       // Erasing early invalidates the targetIter. (Conversely, inserting first may also
379       // invalidate actorIter)
380       targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
381       ++targetIter;
382       mChildren->insert(targetIter, childPtr);
383     }
384     raised = true;
385   }
386   if(raised)
387   {
388     EmitOrderChangedAndRebuild(child);
389   }
390 }
391
392 void ActorParentImpl::LowerChildBelow(Actor& child, Actor& target)
393 {
394   bool lowered = false;
395
396   // If not already at bottom
397   if(mChildren && mChildren->front() != &child && target.GetParent() == child.GetParent())
398   {
399     ActorPtr childPtr(&child); // ensure actor actor remains referenced.
400
401     auto targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
402     auto childIter  = std::find(mChildren->begin(), mChildren->end(), &child);
403
404     if(childIter > targetIter)
405     {
406       mChildren->erase(childIter); // actor only invalidates iterators at or after actor point.
407       mChildren->insert(targetIter, childPtr);
408     }
409     lowered = true;
410   }
411   if(lowered)
412   {
413     EmitOrderChangedAndRebuild(child);
414   }
415 }
416
417 void ActorParentImpl::EmitChildAddedSignal(Actor& child)
418 {
419   EmitSignal(child, mChildAddedSignal);
420 }
421
422 void ActorParentImpl::EmitChildRemovedSignal(Actor& child)
423 {
424   EmitSignal(child, mChildRemovedSignal);
425 }
426
427 void ActorParentImpl::EmitOrderChangedAndRebuild(Actor& child)
428 {
429   EmitSignal(child, mChildOrderChangedSignal);
430
431   if(mOwner.OnScene())
432   {
433     mOwner.GetScene().RequestRebuildDepthTree();
434   }
435 }
436
437 } // namespace Internal
438
439 } // namespace Dali