Merge "Updated patch coverage script." into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-parent-impl.cpp
1 /*
2  * Copyright (c) 2020 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)
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); // 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);
95
96       // Notification for derived classes
97       mOwner.OnChildAdd(child);
98       EmitChildAddedSignal(child);
99
100       child.InheritLayoutDirectionRecursively(mOwner.GetLayoutDirection());
101
102       // Only put in a relayout request if there is a suitable dependency
103       if(mOwner.RelayoutDependentOnChildren())
104       {
105         mOwner.RelayoutRequest();
106       }
107     }
108   }
109 }
110
111 void ActorParentImpl::Remove(Actor& child)
112 {
113   if((&mOwner == &child) || (!mChildren))
114   {
115     // no children or removing itself
116     return;
117   }
118
119   ActorPtr removed;
120
121   // Find the child in mChildren, and unparent it
122   ActorIter end = mChildren->end();
123   for(ActorIter iter = mChildren->begin(); iter != end; ++iter)
124   {
125     ActorPtr actor = (*iter);
126
127     if(actor.Get() == &child)
128     {
129       // Keep handle for OnChildRemove notification
130       removed = actor;
131
132       // Do this first, since user callbacks from within SetParent() may need to add the child
133       mChildren->erase(iter);
134
135       DALI_ASSERT_DEBUG(actor->GetParent() == &mOwner);
136       actor->SetParent(nullptr);
137
138       break;
139     }
140   }
141
142   if(removed)
143   {
144     // Only put in a relayout request if there is a suitable dependency
145     if(mOwner.RelayoutDependentOnChildren())
146     {
147       mOwner.RelayoutRequest();
148     }
149   }
150
151   // Notification for derived classes
152   mOwner.OnChildRemove(child);
153   EmitChildRemovedSignal(child);
154 }
155
156 uint32_t ActorParentImpl::GetChildCount() const
157 {
158   return (nullptr != mChildren) ? static_cast<uint32_t>(mChildren->size()) : 0; // only 4,294,967,295 children per actor
159 }
160
161 ActorPtr ActorParentImpl::GetChildAt(uint32_t index) const
162 {
163   DALI_ASSERT_ALWAYS(index < GetChildCount());
164
165   return ((mChildren) ? (*mChildren)[index] : ActorPtr());
166 }
167
168 ActorPtr ActorParentImpl::FindChildByName(const std::string& actorName)
169 {
170   ActorPtr child = nullptr;
171   if(actorName == mOwner.GetName())
172   {
173     child = &mOwner;
174   }
175   else if(mChildren)
176   {
177     for(const auto& actor : *mChildren)
178     {
179       child = actor->FindChildByName(actorName);
180
181       if(child)
182       {
183         break;
184       }
185     }
186   }
187   return child;
188 }
189
190 ActorPtr ActorParentImpl::FindChildById(const uint32_t id)
191 {
192   ActorPtr child = nullptr;
193   if(id == mOwner.GetId())
194   {
195     child = &mOwner;
196   }
197   else if(mChildren)
198   {
199     for(const auto& actor : *mChildren)
200     {
201       child = actor->FindChildById(id);
202
203       if(child)
204       {
205         break;
206       }
207     }
208   }
209   return child;
210 }
211
212 void ActorParentImpl::UnparentChildren()
213 {
214   if(mChildren)
215   {
216     for(const auto& child : *mChildren)
217     {
218       child->SetParent(nullptr);
219     }
220   }
221 }
222
223 void ActorParentImpl::SetSiblingOrderOfChild(
224   Actor&   child,
225   uint32_t order)
226 {
227   if(mChildren)
228   {
229     uint32_t currentOrder = GetSiblingOrderOfChild(child);
230     if(order != currentOrder)
231     {
232       if(order == 0)
233       {
234         LowerChildToBottom(child);
235       }
236       else if(order < mChildren->size() - 1)
237       {
238         if(order > currentOrder)
239         {
240           RaiseChildAbove(child, *((*mChildren)[order]));
241         }
242         else
243         {
244           LowerChildBelow(child, *((*mChildren)[order]));
245         }
246       }
247       else
248       {
249         RaiseChildToTop(child);
250       }
251     }
252   }
253 }
254
255 uint32_t ActorParentImpl::GetSiblingOrderOfChild(const Actor& child) const
256 {
257   uint32_t order = 0;
258   if(mChildren)
259   {
260     for(std::size_t i = 0; i < mChildren->size(); ++i)
261     {
262       if((*mChildren)[i] == &child)
263       {
264         order = static_cast<uint32_t>(i);
265         break;
266       }
267     }
268   }
269   return order;
270 }
271
272 void ActorParentImpl::RaiseChild(Actor& child)
273 {
274   bool changed = false;
275   if(mChildren && mChildren->back() != &child) // If not already at end
276   {
277     for(std::size_t i = 0; i < mChildren->size(); ++i)
278     {
279       if((*mChildren)[i] == &child)
280       {
281         // Swap with next
282         ActorPtr next       = (*mChildren)[i + 1];
283         (*mChildren)[i + 1] = &child;
284         (*mChildren)[i]     = next;
285         changed             = true;
286         break;
287       }
288     }
289   }
290   if(changed)
291   {
292     EmitOrderChangedAndRebuild(child);
293   }
294 }
295
296 void ActorParentImpl::LowerChild(Actor& child)
297 {
298   bool changed = false;
299   if(mChildren && mChildren->front() != &child) // If not already at beginning
300   {
301     for(std::size_t i = 1; i < mChildren->size(); ++i)
302     {
303       if((*mChildren)[i] == &child)
304       {
305         // Swap with previous
306         ActorPtr previous   = (*mChildren)[i - 1];
307         (*mChildren)[i - 1] = &child;
308         (*mChildren)[i]     = previous;
309         changed             = true;
310         break;
311       }
312     }
313   }
314   if(changed)
315   {
316     EmitOrderChangedAndRebuild(child);
317   }
318 }
319
320 void ActorParentImpl::RaiseChildToTop(Actor& child)
321 {
322   bool changed = false;
323   if(mChildren && mChildren->back() != &child) // If not already at end
324   {
325     auto iter = std::find(mChildren->begin(), mChildren->end(), &child);
326     if(iter != mChildren->end())
327     {
328       mChildren->erase(iter);
329       mChildren->push_back(ActorPtr(&child));
330       changed = true;
331     }
332   }
333   if(changed)
334   {
335     EmitOrderChangedAndRebuild(child);
336   }
337 }
338
339 void ActorParentImpl::LowerChildToBottom(Actor& child)
340 {
341   bool changed = false;
342   if(mChildren && mChildren->front() != &child) // If not already at bottom,
343   {
344     ActorPtr childPtr(&child); // ensure actor remains referenced.
345
346     auto iter = std::find(mChildren->begin(), mChildren->end(), &child);
347     if(iter != mChildren->end())
348     {
349       mChildren->erase(iter);
350       mChildren->insert(mChildren->begin(), childPtr);
351       changed = true;
352     }
353   }
354   if(changed)
355   {
356     EmitOrderChangedAndRebuild(child);
357   }
358 }
359
360 void ActorParentImpl::RaiseChildAbove(Actor& child, Actor& target)
361 {
362   bool raised = false;
363   if(mChildren && mChildren->back() != &child && target.GetParent() == child.GetParent()) // If not already at top
364   {
365     ActorPtr childPtr(&child); // ensure actor actor remains referenced.
366
367     auto targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
368     auto childIter  = std::find(mChildren->begin(), mChildren->end(), &child);
369     if(childIter < targetIter)
370     {
371       mChildren->erase(childIter);
372       // Erasing early invalidates the targetIter. (Conversely, inserting first may also
373       // invalidate actorIter)
374       targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
375       ++targetIter;
376       mChildren->insert(targetIter, childPtr);
377     }
378     raised = true;
379   }
380   if(raised)
381   {
382     EmitOrderChangedAndRebuild(child);
383   }
384 }
385
386 void ActorParentImpl::LowerChildBelow(Actor& child, Actor& target)
387 {
388   bool lowered = false;
389
390   // If not already at bottom
391   if(mChildren && mChildren->front() != &child && target.GetParent() == child.GetParent())
392   {
393     ActorPtr childPtr(&child); // ensure actor actor remains referenced.
394
395     auto targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
396     auto childIter  = std::find(mChildren->begin(), mChildren->end(), &child);
397
398     if(childIter > targetIter)
399     {
400       mChildren->erase(childIter); // actor only invalidates iterators at or after actor point.
401       mChildren->insert(targetIter, childPtr);
402     }
403     lowered = true;
404   }
405   if(lowered)
406   {
407     EmitOrderChangedAndRebuild(child);
408   }
409 }
410
411 void ActorParentImpl::EmitChildAddedSignal(Actor& child)
412 {
413   EmitSignal(child, mChildAddedSignal);
414 }
415
416 void ActorParentImpl::EmitChildRemovedSignal(Actor& child)
417 {
418   EmitSignal(child, mChildRemovedSignal);
419 }
420
421 void ActorParentImpl::EmitOrderChangedAndRebuild(Actor& child)
422 {
423   EmitSignal(child, mChildOrderChangedSignal);
424
425   if(mOwner.OnScene())
426   {
427     mOwner.GetScene().RequestRebuildDepthTree();
428   }
429 }
430
431 } // namespace Internal
432
433 } // namespace Dali