• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "core/components_ng/base/ui_node.h"
16 
17 #include <memory>
18 
19 #include "base/geometry/ng/point_t.h"
20 #include "base/log/ace_checker.h"
21 #include "base/log/ace_performance_check.h"
22 #include "base/log/ace_trace.h"
23 #include "base/log/dump_log.h"
24 #include "base/memory/referenced.h"
25 #include "base/utils/system_properties.h"
26 #include "base/utils/utils.h"
27 #include "bridge/common/utils/engine_helper.h"
28 #include "core/common/container.h"
29 #include "core/components_v2/inspector/inspector_constants.h"
30 #include "core/pipeline/base/element_register.h"
31 #include "core/pipeline_ng/pipeline_context.h"
32 
33 namespace OHOS::Ace::NG {
34 
35 thread_local int32_t UINode::currentAccessibilityId_ = 0;
36 
UINode(const std::string & tag,int32_t nodeId,bool isRoot)37 UINode::UINode(const std::string& tag, int32_t nodeId, bool isRoot)
38     : tag_(tag), nodeId_(nodeId), accessibilityId_(currentAccessibilityId_++), isRoot_(isRoot)
39 {
40     if (AceChecker::IsPerformanceCheckEnabled()) {
41         auto pos = EngineHelper::GetPositionOnJsCode();
42         nodeInfo_ = std::make_unique<PerformanceCheckNode>();
43         nodeInfo_->codeRow = pos.first;
44         nodeInfo_->codeCol = pos.second;
45     }
46 #ifdef UICAST_COMPONENT_SUPPORTED
47     do {
48         auto container = Container::Current();
49         CHECK_NULL_BREAK(container);
50         auto distributedUI = container->GetDistributedUI();
51         CHECK_NULL_BREAK(distributedUI);
52         distributedUI->AddNewNode(nodeId_);
53     } while (false);
54 #endif
55 }
56 
~UINode()57 UINode::~UINode()
58 {
59 #ifdef UICAST_COMPONENT_SUPPORTED
60     do {
61         auto container = Container::Current();
62         CHECK_NULL_BREAK(container);
63         auto distributedUI = container->GetDistributedUI();
64         CHECK_NULL_BREAK(distributedUI);
65         if (hostPageId_ == distributedUI->GetCurrentPageId()) {
66             distributedUI->AddDeletedNode(nodeId_);
67         }
68     } while (false);
69 #endif
70 
71     if (!removeSilently_) {
72         ElementRegister::GetInstance()->RemoveItem(nodeId_, tag_);
73     } else {
74         ElementRegister::GetInstance()->RemoveItemSilently(nodeId_);
75     }
76     if (!onMainTree_) {
77         return;
78     }
79     onMainTree_ = false;
80 }
81 
AddChild(const RefPtr<UINode> & child,int32_t slot,bool silently)82 void UINode::AddChild(const RefPtr<UINode>& child, int32_t slot, bool silently)
83 {
84     CHECK_NULL_VOID(child);
85     auto it = std::find(children_.begin(), children_.end(), child);
86     if (it != children_.end()) {
87         LOGW("Child node already exists. Existing child nodeId %{public}d, add %{public}s child nodeId nodeId "
88              "%{public}d",
89             (*it)->GetId(), child->GetTag().c_str(), child->GetId());
90         return;
91     }
92 
93     // remove from disappearing children
94     RemoveDisappearingChild(child);
95     it = children_.begin();
96     std::advance(it, slot);
97     DoAddChild(it, child, silently);
98 }
99 
RemoveChild(const RefPtr<UINode> & child,bool allowTransition)100 std::list<RefPtr<UINode>>::iterator UINode::RemoveChild(const RefPtr<UINode>& child, bool allowTransition)
101 {
102     CHECK_NULL_RETURN(child, children_.end());
103 
104     auto iter = std::find(children_.begin(), children_.end(), child);
105     if (iter == children_.end()) {
106         LOGE("child is not exist.");
107         return children_.end();
108     }
109     // If the child is undergoing a disappearing transition, rather than simply removing it, we should move it to the
110     // disappearing children. This ensures that the child remains alive and the tree hierarchy is preserved until the
111     // transition has finished. We can then perform the necessary cleanup after the transition is complete.
112     if ((*iter)->OnRemoveFromParent(allowTransition)) {
113         // OnRemoveFromParent returns true means the child can be removed from tree immediately.
114         RemoveDisappearingChild(child);
115     } else {
116         // else move child into disappearing children, skip syncing render tree
117         AddDisappearingChild(child, std::distance(children_.begin(), iter));
118     }
119     MarkNeedSyncRenderTree(true);
120     auto result = children_.erase(iter);
121     return result;
122 }
123 
RemoveChildAndReturnIndex(const RefPtr<UINode> & child)124 int32_t UINode::RemoveChildAndReturnIndex(const RefPtr<UINode>& child)
125 {
126     auto result = RemoveChild(child);
127     return std::distance(children_.begin(), result);
128 }
129 
RemoveChildAtIndex(int32_t index)130 void UINode::RemoveChildAtIndex(int32_t index)
131 {
132     if ((index < 0) || (index >= static_cast<int32_t>(children_.size()))) {
133         return;
134     }
135     auto iter = children_.begin();
136     std::advance(iter, index);
137     RemoveChild(*iter);
138 }
139 
GetChildAtIndex(int32_t index) const140 RefPtr<UINode> UINode::GetChildAtIndex(int32_t index) const
141 {
142     if ((index < 0) || (index >= static_cast<int32_t>(children_.size()))) {
143         return nullptr;
144     }
145     auto iter = children_.begin();
146     std::advance(iter, index);
147     if (iter != children_.end()) {
148         return *iter;
149     }
150     return nullptr;
151 }
152 
GetChildIndex(const RefPtr<UINode> & child) const153 int32_t UINode::GetChildIndex(const RefPtr<UINode>& child) const
154 {
155     int32_t index = 0;
156     for (const auto& iter : children_) {
157         if (iter == child) {
158             return index;
159         }
160         index++;
161     }
162     return -1;
163 }
164 
ReplaceChild(const RefPtr<UINode> & oldNode,const RefPtr<UINode> & newNode)165 void UINode::ReplaceChild(const RefPtr<UINode>& oldNode, const RefPtr<UINode>& newNode)
166 {
167     if (!oldNode) {
168         if (newNode) {
169             AddChild(newNode);
170         }
171         return;
172     }
173 
174     auto iter = RemoveChild(oldNode);
175     DoAddChild(iter, newNode, false, false);
176 }
177 
Clean(bool cleanDirectly,bool allowTransition)178 void UINode::Clean(bool cleanDirectly, bool allowTransition)
179 {
180     bool needSyncRenderTree = false;
181     int32_t index = 0;
182     for (const auto& child : children_) {
183         // traverse down the child subtree to mark removing and find needs to hold subtree, if found add it to pending
184         if (!cleanDirectly && child->MarkRemoving()) {
185             ElementRegister::GetInstance()->AddPendingRemoveNode(child);
186         }
187         // If the child is undergoing a disappearing transition, rather than simply removing it, we should move it to
188         // the disappearing children. This ensures that the child remains alive and the tree hierarchy is preserved
189         // until the transition has finished. We can then perform the necessary cleanup after the transition is
190         // complete.
191         if (child->OnRemoveFromParent(allowTransition)) {
192             // OnRemoveFromParent returns true means the child can be removed from tree immediately.
193             RemoveDisappearingChild(child);
194             needSyncRenderTree = true;
195         } else {
196             // else move child into disappearing children, skip syncing render tree
197             AddDisappearingChild(child, index);
198         }
199         ++index;
200     }
201     children_.clear();
202     MarkNeedSyncRenderTree(true);
203 }
204 
MountToParent(const RefPtr<UINode> & parent,int32_t slot,bool silently)205 void UINode::MountToParent(const RefPtr<UINode>& parent, int32_t slot, bool silently)
206 {
207     CHECK_NULL_VOID(parent);
208     parent->AddChild(AceType::Claim(this), slot, silently);
209     if (parent->IsInDestroying()) {
210         parent->SetChildrenInDestroying();
211     }
212     if (parent->GetPageId() != 0) {
213         SetHostPageId(parent->GetPageId());
214     }
215 }
216 
UpdateConfigurationUpdate(const OnConfigurationChange & configurationChange)217 void UINode::UpdateConfigurationUpdate(const OnConfigurationChange& configurationChange)
218 {
219     OnConfigurationUpdate(configurationChange);
220     if (needCallChildrenUpdate_) {
221         auto children = GetChildren();
222         for (const auto& child : children) {
223             if (!child) {
224                 continue;
225             }
226             child->UpdateConfigurationUpdate(configurationChange);
227         }
228     }
229 }
230 
OnRemoveFromParent(bool allowTransition)231 bool UINode::OnRemoveFromParent(bool allowTransition)
232 {
233     // The recursive flag will used by RenderContext, if recursive flag is false,
234     // it may trigger transition
235     DetachFromMainTree(!allowTransition);
236     if (allowTransition && !RemoveImmediately()) {
237         return false;
238     }
239     ResetParent();
240     return true;
241 }
242 
ResetParent()243 void UINode::ResetParent()
244 {
245     parent_.Reset();
246     depth_ = -1;
247 }
248 
DoAddChild(std::list<RefPtr<UINode>>::iterator & it,const RefPtr<UINode> & child,bool silently,bool allowTransition)249 void UINode::DoAddChild(
250     std::list<RefPtr<UINode>>::iterator& it, const RefPtr<UINode>& child, bool silently, bool allowTransition)
251 {
252     children_.insert(it, child);
253 
254     child->SetParent(Claim(this));
255     child->SetDepth(GetDepth() + 1);
256     if (!silently && onMainTree_) {
257         child->AttachToMainTree(!allowTransition);
258     }
259     MarkNeedSyncRenderTree(true);
260 }
261 
GetFocusParent() const262 RefPtr<FrameNode> UINode::GetFocusParent() const
263 {
264     auto parentUi = GetParent();
265     while (parentUi) {
266         auto parentFrame = AceType::DynamicCast<FrameNode>(parentUi);
267         if (!parentFrame) {
268             parentUi = parentUi->GetParent();
269             continue;
270         }
271         auto type = parentFrame->GetFocusType();
272         if (type == FocusType::SCOPE) {
273             return parentFrame;
274         }
275         if (type == FocusType::NODE) {
276             return nullptr;
277         }
278         parentUi = parentUi->GetParent();
279     }
280     return nullptr;
281 }
282 
GetFirstFocusHubChild() const283 RefPtr<FocusHub> UINode::GetFirstFocusHubChild() const
284 {
285     const auto* frameNode = AceType::DynamicCast<FrameNode>(this);
286     if (frameNode) {
287         auto focusHub = frameNode->GetFocusHub();
288         if (focusHub && focusHub->GetFocusType() != FocusType::DISABLE) {
289             return focusHub;
290         }
291     }
292     for (const auto& child : GetChildren()) {
293         auto focusHub = child->GetFirstFocusHubChild();
294         if (focusHub) {
295             return focusHub;
296         }
297     }
298     return nullptr;
299 }
300 
GetFocusChildren(std::list<RefPtr<FrameNode>> & children) const301 void UINode::GetFocusChildren(std::list<RefPtr<FrameNode>>& children) const
302 {
303     auto uiChildren = GetChildren();
304     for (const auto& uiChild : uiChildren) {
305         auto frameChild = AceType::DynamicCast<FrameNode>(uiChild);
306         if (frameChild && frameChild->GetFocusType() != FocusType::DISABLE) {
307             children.emplace_back(frameChild);
308         } else {
309             uiChild->GetFocusChildren(children);
310         }
311     }
312 }
313 
AttachToMainTree(bool recursive)314 void UINode::AttachToMainTree(bool recursive)
315 {
316     if (onMainTree_) {
317         return;
318     }
319     onMainTree_ = true;
320     isRemoving_ = false;
321     OnAttachToMainTree(recursive);
322     // if recursive = false, recursively call AttachToMainTree(false), until we reach the first FrameNode.
323     bool isRecursive = recursive || AceType::InstanceOf<FrameNode>(this);
324     for (const auto& child : children_) {
325         child->AttachToMainTree(isRecursive);
326     }
327 }
328 
DetachFromMainTree(bool recursive)329 void UINode::DetachFromMainTree(bool recursive)
330 {
331     if (!onMainTree_) {
332         return;
333     }
334     onMainTree_ = false;
335     isRemoving_ = true;
336     OnDetachFromMainTree(recursive);
337     // if recursive = false, recursively call DetachFromMainTree(false), until we reach the first FrameNode.
338     bool isRecursive = recursive || AceType::InstanceOf<FrameNode>(this);
339     for (const auto& child : children_) {
340         child->DetachFromMainTree(isRecursive);
341     }
342 }
343 
ProcessOffscreenTask(bool recursive)344 void UINode::ProcessOffscreenTask(bool recursive)
345 {
346     if (useOffscreenProcess_) {
347         return;
348     }
349     useOffscreenProcess_ = true;
350     OnOffscreenProcess(recursive);
351     // if recursive = false, recursively call AttachToMainTree(false), until we reach the first FrameNode.
352     bool isRecursive = recursive || AceType::InstanceOf<FrameNode>(this);
353     for (const auto& child : children_) {
354         child->ProcessOffscreenTask(isRecursive);
355     }
356 }
357 
MovePosition(int32_t slot)358 void UINode::MovePosition(int32_t slot)
359 {
360     auto parentNode = parent_.Upgrade();
361     CHECK_NULL_VOID(parentNode);
362 
363     auto self = AceType::Claim(this);
364     auto& children = parentNode->children_;
365     auto it = children.end();
366     if (slot >= 0 && static_cast<size_t>(slot) < children.size()) {
367         it = children.begin();
368         std::advance(it, slot);
369         if ((it != children.end()) && (*it == this)) {
370             // Already at the right place
371             LOGD("Already at the right place");
372             return;
373         }
374 
375         auto itSelf = std::find(it, children.end(), self);
376         if (itSelf != children.end()) {
377             children.erase(itSelf);
378         } else {
379             children.remove(self);
380             ++it;
381         }
382     } else {
383         children.remove(self);
384     }
385     children.insert(it, self);
386     parentNode->MarkNeedSyncRenderTree(true);
387 }
388 
UpdateLayoutPropertyFlag()389 void UINode::UpdateLayoutPropertyFlag()
390 {
391     for (const auto& child : children_) {
392         child->UpdateLayoutPropertyFlag();
393     }
394 }
395 
AdjustParentLayoutFlag(PropertyChangeFlag & flag)396 void UINode::AdjustParentLayoutFlag(PropertyChangeFlag& flag)
397 {
398     for (const auto& child : children_) {
399         child->AdjustParentLayoutFlag(flag);
400     }
401 }
402 
MarkDirtyNode(PropertyChangeFlag extraFlag)403 void UINode::MarkDirtyNode(PropertyChangeFlag extraFlag)
404 {
405     for (const auto& child : children_) {
406         child->MarkDirtyNode(extraFlag);
407     }
408 }
409 
MarkNeedFrameFlushDirty(PropertyChangeFlag extraFlag)410 void UINode::MarkNeedFrameFlushDirty(PropertyChangeFlag extraFlag)
411 {
412     auto parent = parent_.Upgrade();
413     if (parent) {
414         parent->MarkNeedFrameFlushDirty(extraFlag);
415     }
416 }
417 
MarkNeedSyncRenderTree(bool needRebuild)418 void UINode::MarkNeedSyncRenderTree(bool needRebuild)
419 {
420     auto parent = parent_.Upgrade();
421     if (parent) {
422         parent->MarkNeedSyncRenderTree(needRebuild);
423     }
424 }
425 
RebuildRenderContextTree()426 void UINode::RebuildRenderContextTree()
427 {
428     auto parent = parent_.Upgrade();
429     if (parent) {
430         parent->RebuildRenderContextTree();
431     }
432 }
OnDetachFromMainTree(bool)433 void UINode::OnDetachFromMainTree(bool) {}
434 
OnAttachToMainTree(bool)435 void UINode::OnAttachToMainTree(bool)
436 {
437     useOffscreenProcess_ = false;
438     decltype(attachToMainTreeTasks_) tasks(std::move(attachToMainTreeTasks_));
439     for (const auto& task : tasks) {
440         if (task) {
441             task();
442         }
443     }
444 }
445 
DumpTree(int32_t depth)446 void UINode::DumpTree(int32_t depth)
447 {
448     if (DumpLog::GetInstance().GetDumpFile()) {
449         DumpLog::GetInstance().AddDesc("ID: " + std::to_string(nodeId_));
450         DumpLog::GetInstance().AddDesc(std::string("Depth: ").append(std::to_string(GetDepth())));
451         DumpLog::GetInstance().AddDesc(std::string("IsDisappearing: ").append(std::to_string(IsDisappearing())));
452         DumpInfo();
453         DumpLog::GetInstance().Print(depth, tag_, static_cast<int32_t>(children_.size()));
454     }
455 
456     for (const auto& item : GetChildren()) {
457         item->DumpTree(depth + 1);
458     }
459     for (const auto& [item, index] : disappearingChildren_) {
460         item->DumpTree(depth + 1);
461     }
462 }
463 
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode> & parent,bool forceMeasure,bool forceLayout)464 void UINode::AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout)
465 {
466     for (const auto& child : children_) {
467         if (!child->IsInDestroying()) {
468             child->AdjustLayoutWrapperTree(parent, forceMeasure, forceLayout);
469         }
470     }
471 }
472 
GenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & visibleList)473 void UINode::GenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& visibleList)
474 {
475     for (const auto& child : GetChildren()) {
476         child->OnGenerateOneDepthVisibleFrame(visibleList);
477     }
478 }
479 
GenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)480 void UINode::GenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList)
481 {
482     if (disappearingChildren_.empty()) {
483         // normal child
484         for (const auto& child : GetChildren()) {
485             child->OnGenerateOneDepthVisibleFrameWithTransition(visibleList);
486         }
487         return;
488     }
489     // generate the merged list of children_ and disappearingChildren_
490     auto allChildren = GetChildren();
491     for (auto iter = disappearingChildren_.rbegin(); iter != disappearingChildren_.rend(); ++iter) {
492         auto& [disappearingChild, index] = *iter;
493         if (index >= allChildren.size()) {
494             allChildren.emplace_back(disappearingChild);
495         } else {
496             auto insertIter = allChildren.begin();
497             std::advance(insertIter, index);
498             allChildren.insert(insertIter, disappearingChild);
499         }
500     }
501     for (const auto& child : allChildren) {
502         child->OnGenerateOneDepthVisibleFrameWithTransition(visibleList);
503     }
504 }
505 
GenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>> & visibleList)506 void UINode::GenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>>& visibleList)
507 {
508     for (const auto& child : GetChildren()) {
509         child->OnGenerateOneDepthAllFrame(visibleList);
510     }
511 }
512 
GetContext()513 RefPtr<PipelineContext> UINode::GetContext()
514 {
515     return PipelineContext::GetCurrentContext();
516 }
517 
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,const TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId)518 HitTestResult UINode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
519     const PointF& parentRevertPoint, const TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId)
520 {
521     HitTestResult hitTestResult = HitTestResult::OUT_OF_REGION;
522     for (auto iter = children_.rbegin(); iter != children_.rend(); ++iter) {
523         auto& child = *iter;
524         auto hitResult = child->TouchTest(globalPoint, parentLocalPoint, parentRevertPoint,
525             touchRestrict, result, touchId);
526         if (hitResult == HitTestResult::STOP_BUBBLING) {
527             return HitTestResult::STOP_BUBBLING;
528         }
529         if (hitResult == HitTestResult::BUBBLING) {
530             hitTestResult = HitTestResult::BUBBLING;
531         }
532     }
533     return hitTestResult;
534 }
535 
MouseTest(const PointF & globalPoint,const PointF & parentLocalPoint,MouseTestResult & onMouseResult,MouseTestResult & onHoverResult,RefPtr<FrameNode> & hoverNode)536 HitTestResult UINode::MouseTest(const PointF& globalPoint, const PointF& parentLocalPoint,
537     MouseTestResult& onMouseResult, MouseTestResult& onHoverResult, RefPtr<FrameNode>& hoverNode)
538 {
539     HitTestResult hitTestResult = HitTestResult::OUT_OF_REGION;
540     for (auto iter = children_.rbegin(); iter != children_.rend(); ++iter) {
541         auto& child = *iter;
542         auto hitResult = child->MouseTest(globalPoint, parentLocalPoint, onMouseResult, onHoverResult, hoverNode);
543         if (hitResult == HitTestResult::STOP_BUBBLING) {
544             return HitTestResult::STOP_BUBBLING;
545         }
546         if (hitResult == HitTestResult::BUBBLING) {
547             hitTestResult = HitTestResult::BUBBLING;
548         }
549     }
550     return hitTestResult;
551 }
552 
AxisTest(const PointF & globalPoint,const PointF & parentLocalPoint,AxisTestResult & onAxisResult)553 HitTestResult UINode::AxisTest(const PointF& globalPoint, const PointF& parentLocalPoint, AxisTestResult& onAxisResult)
554 {
555     HitTestResult hitTestResult = HitTestResult::OUT_OF_REGION;
556     for (auto iter = children_.rbegin(); iter != children_.rend(); ++iter) {
557         auto& child = *iter;
558         auto hitResult = child->AxisTest(globalPoint, parentLocalPoint, onAxisResult);
559         if (hitResult == HitTestResult::STOP_BUBBLING) {
560             return HitTestResult::STOP_BUBBLING;
561         }
562         if (hitResult == HitTestResult::BUBBLING) {
563             hitTestResult = HitTestResult::BUBBLING;
564         }
565     }
566     return hitTestResult;
567 }
568 
FrameCount() const569 int32_t UINode::FrameCount() const
570 {
571     return TotalChildCount();
572 }
573 
TotalChildCount() const574 int32_t UINode::TotalChildCount() const
575 {
576     int32_t count = 0;
577     for (const auto& child : GetChildren()) {
578         count += child->FrameCount();
579     }
580     return count;
581 }
582 
GetChildIndexById(int32_t id)583 int32_t UINode::GetChildIndexById(int32_t id)
584 {
585     int32_t pos = 0;
586     auto iter = children_.begin();
587     while (iter != GetChildren().end()) {
588         if (id == (*iter)->GetId()) {
589             return pos;
590         }
591         pos++;
592         iter++;
593     }
594     return -1;
595 }
596 
CreateLayoutWrapper(bool forceMeasure,bool forceLayout)597 RefPtr<LayoutWrapperNode> UINode::CreateLayoutWrapper(bool forceMeasure, bool forceLayout)
598 {
599     if (GetChildren().empty()) {
600         return nullptr;
601     }
602 
603     auto child = GetChildren().front();
604     while (!InstanceOf<FrameNode>(child)) {
605         auto children = child->GetChildren();
606         if (children.empty()) {
607             return nullptr;
608         }
609 
610         child = children.front();
611     }
612 
613     auto frameChild = DynamicCast<FrameNode>(child);
614     return frameChild ? frameChild->CreateLayoutWrapper(forceMeasure, forceLayout) : nullptr;
615 }
616 
Build()617 void UINode::Build()
618 {
619     for (const auto& child : children_) {
620         child->Build();
621     }
622 }
623 
SetActive(bool active)624 void UINode::SetActive(bool active)
625 {
626     for (const auto& child : children_) {
627         child->SetActive(active);
628     }
629 }
630 
SetJSViewActive(bool active)631 void UINode::SetJSViewActive(bool active)
632 {
633     for (const auto& child : children_) {
634         child->SetJSViewActive(active);
635     }
636 }
637 
OnVisibleChange(bool isVisible)638 void UINode::OnVisibleChange(bool isVisible)
639 {
640     UpdateChildrenVisible(isVisible);
641 }
642 
UpdateChildrenVisible(bool isVisible) const643 void UINode::UpdateChildrenVisible(bool isVisible) const
644 {
645     for (const auto& child : GetChildren()) {
646         if (InstanceOf<FrameNode>(child)) {
647             auto childLayoutProperty = DynamicCast<FrameNode>(child)->GetLayoutProperty();
648             if (childLayoutProperty &&
649                 childLayoutProperty->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
650                 // child is invisible, no need to update visible state.
651                 continue;
652             }
653         }
654         child->OnVisibleChange(isVisible);
655     }
656 }
657 
GetChildFlatIndex(int32_t id)658 std::pair<bool, int32_t> UINode::GetChildFlatIndex(int32_t id)
659 {
660     if (GetId() == id) {
661         return { true, 0 };
662     }
663 
664     const auto& node = ElementRegister::GetInstance()->GetUINodeById(id);
665     if (!node) {
666         return { false, 0 };
667     }
668 
669     if (node && (node->GetTag() == GetTag())) {
670         return { false, 1 };
671     }
672 
673     int32_t count = 0;
674     for (const auto& child : GetChildren()) {
675         auto res = child->GetChildFlatIndex(id);
676         if (res.first) {
677             return { true, count + res.second };
678         }
679         count += res.second;
680     }
681     return { false, count };
682 }
683 
684 // for Grid refresh GridItems
ChildrenUpdatedFrom(int32_t index)685 void UINode::ChildrenUpdatedFrom(int32_t index)
686 {
687     childrenUpdatedFrom_ = childrenUpdatedFrom_ >= 0 ? std::min(index, childrenUpdatedFrom_) : index;
688 }
689 
MarkRemoving()690 bool UINode::MarkRemoving()
691 {
692     bool pendingRemove = false;
693     isRemoving_ = true;
694     const auto& children = GetChildren();
695     for (const auto& child : children) {
696         pendingRemove = child->MarkRemoving() || pendingRemove;
697     }
698     return pendingRemove;
699 }
700 
SetChildrenInDestroying()701 void UINode::SetChildrenInDestroying()
702 {
703     if (children_.empty()) {
704         return;
705     }
706 
707     for (const auto& child : children_) {
708         if (!child) {
709             continue;
710         }
711         child->SetChildrenInDestroying();
712         child->SetInDestroying();
713     }
714 }
715 
AddDisappearingChild(const RefPtr<UINode> & child,uint32_t index)716 void UINode::AddDisappearingChild(const RefPtr<UINode>& child, uint32_t index)
717 {
718     if (child->isDisappearing_) {
719         // if child is already disappearing, remove it from disappearingChildren_ first
720         auto it = std::find_if(disappearingChildren_.begin(), disappearingChildren_.end(),
721             [child](const auto& pair) { return pair.first == child; });
722         if (it != disappearingChildren_.end()) {
723             disappearingChildren_.erase(it);
724         }
725     } else {
726         // mark child as disappearing before adding to disappearingChildren_
727         child->isDisappearing_ = true;
728     }
729     disappearingChildren_.emplace_back(child, index);
730 }
731 
RemoveDisappearingChild(const RefPtr<UINode> & child)732 bool UINode::RemoveDisappearingChild(const RefPtr<UINode>& child)
733 {
734     // quick reject
735     if (child->isDisappearing_ == false) {
736         return false;
737     }
738     auto it = std::find_if(disappearingChildren_.begin(), disappearingChildren_.end(),
739         [child](const auto& pair) { return pair.first == child; });
740     if (it == disappearingChildren_.end()) {
741         return false;
742     }
743     disappearingChildren_.erase(it);
744     child->isDisappearing_ = false;
745     return true;
746 }
747 
OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)748 void UINode::OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList)
749 {
750     GenerateOneDepthVisibleFrameWithTransition(visibleList);
751 }
752 
RemoveImmediately() const753 bool UINode::RemoveImmediately() const
754 {
755     return std::all_of(
756         children_.begin(), children_.end(), [](const auto& child) { return child->RemoveImmediately(); });
757 }
758 
GetPerformanceCheckData(PerformanceCheckNodeMap & nodeMap)759 void UINode::GetPerformanceCheckData(PerformanceCheckNodeMap& nodeMap)
760 {
761     auto parent = GetParent();
762     if (parent && parent->GetTag() == V2::JS_FOR_EACH_ETS_TAG) {
763         // At this point, all of the children_
764         // belong to the child nodes of syntaxItem
765         for (const auto& child : GetChildren()) {
766             if (child->GetTag() == V2::COMMON_VIEW_ETS_TAG) {
767                 auto children = child->GetChildren();
768                 if (!children.empty()) {
769                     auto begin = children.begin();
770                     (*begin)->SetForeachItem();
771                 }
772             } else {
773                 child->SetForeachItem();
774             }
775         }
776     }
777 
778     if (tag_ == V2::COMMON_VIEW_ETS_TAG) {
779         if (!children_.empty()) {
780             auto begin = children_.begin();
781             nodeInfo_->nodeTag = (*begin)->GetCustomTag();
782         }
783     } else {
784         nodeInfo_->nodeTag = GetCustomTag();
785     }
786 
787     nodeInfo_->pageDepth = depth_;
788     nodeInfo_->childrenSize = children_.size();
789     if (isBuildByJS_) {
790         nodeMap.insert({ GetId(), *(nodeInfo_) });
791     }
792     for (const auto& child : children_) {
793         // Recursively traverse the child nodes of each node
794         child->GetPerformanceCheckData(nodeMap);
795     }
796 }
797 
GetDisappearingChildById(const std::string & id) const798 RefPtr<UINode> UINode::GetDisappearingChildById(const std::string& id) const
799 {
800     if (id.empty()) {
801         return nullptr;
802     }
803     for (auto& [node, index] : disappearingChildren_) {
804         if (node->GetInspectorIdValue("") == id) {
805             return node;
806         }
807     }
808     return nullptr;
809 }
810 
GetFrameChildByIndex(uint32_t index,bool needBuild)811 RefPtr<UINode> UINode::GetFrameChildByIndex(uint32_t index, bool needBuild)
812 {
813     for (const auto& child : children_) {
814         uint32_t count = static_cast<uint32_t>(child->FrameCount());
815         if (count > index) {
816             return child->GetFrameChildByIndex(index, needBuild);
817         }
818         index -= count;
819     }
820     return nullptr;
821 }
822 
DoRemoveChildInRenderTree(uint32_t index,bool isAll)823 void UINode::DoRemoveChildInRenderTree(uint32_t index, bool isAll)
824 {
825     if (isAll) {
826         for (const auto& child : children_) {
827             child->DoRemoveChildInRenderTree(index, isAll);
828         }
829         return;
830     }
831     for (const auto& child : children_) {
832         uint32_t count = static_cast<uint32_t>(child->FrameCount());
833         if (count > index) {
834             return child->DoRemoveChildInRenderTree(index);
835         }
836         index -= count;
837     }
838 }
839 
OnSetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)840 void UINode::OnSetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
841 {
842     for (const auto& child : GetChildren()) {
843         child->OnSetCacheCount(cacheCount, itemConstraint);
844     }
845 }
846 
847 } // namespace OHOS::Ace::NG
848