• 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_ng/base/view_stack_processor.h"
30 #include "core/components_ng/property/layout_constraint.h"
31 #include "core/components_v2/inspector/inspector_constants.h"
32 #include "core/pipeline/base/element_register.h"
33 #include "core/pipeline_ng/pipeline_context.h"
34 
35 namespace OHOS::Ace::NG {
36 
37 thread_local int64_t UINode::currentAccessibilityId_ = 0;
38 
UINode(const std::string & tag,int32_t nodeId,bool isRoot)39 UINode::UINode(const std::string& tag, int32_t nodeId, bool isRoot)
40     : tag_(tag), nodeId_(nodeId), accessibilityId_(currentAccessibilityId_++), isRoot_(isRoot)
41 {
42     if (AceChecker::IsPerformanceCheckEnabled()) {
43         auto pos = EngineHelper::GetPositionOnJsCode();
44         nodeInfo_ = std::make_unique<PerformanceCheckNode>();
45         nodeInfo_->codeRow = pos.first;
46         nodeInfo_->codeCol = pos.second;
47     }
48 #ifdef UICAST_COMPONENT_SUPPORTED
49     do {
50         auto container = Container::Current();
51         CHECK_NULL_BREAK(container);
52         auto distributedUI = container->GetDistributedUI();
53         CHECK_NULL_BREAK(distributedUI);
54         distributedUI->AddNewNode(nodeId_);
55     } while (false);
56 #endif
57     nodeStatus_ = ViewStackProcessor::GetInstance()->IsBuilderNode() ? NodeStatus::BUILDER_NODE_OFF_MAINTREE
58                                                                      : NodeStatus::NORMAL_NODE;
59 }
60 
~UINode()61 UINode::~UINode()
62 {
63 #ifdef UICAST_COMPONENT_SUPPORTED
64     do {
65         auto container = Container::Current();
66         CHECK_NULL_BREAK(container);
67         auto distributedUI = container->GetDistributedUI();
68         CHECK_NULL_BREAK(distributedUI);
69         if (hostPageId_ == distributedUI->GetCurrentPageId()) {
70             distributedUI->AddDeletedNode(nodeId_);
71         }
72     } while (false);
73 #endif
74 
75     if (!removeSilently_) {
76         ElementRegister::GetInstance()->RemoveItem(nodeId_, tag_);
77     } else {
78         ElementRegister::GetInstance()->RemoveItemSilently(nodeId_);
79     }
80     if (!onMainTree_) {
81         return;
82     }
83     onMainTree_ = false;
84     if (nodeStatus_ == NodeStatus::BUILDER_NODE_ON_MAINTREE) {
85         nodeStatus_ = NodeStatus::BUILDER_NODE_OFF_MAINTREE;
86     }
87 }
88 
AddChild(const RefPtr<UINode> & child,int32_t slot,bool silently,bool addDefaultTransition)89 void UINode::AddChild(const RefPtr<UINode>& child, int32_t slot, bool silently, bool addDefaultTransition)
90 {
91     CHECK_NULL_VOID(child);
92     auto it = std::find(children_.begin(), children_.end(), child);
93     if (it != children_.end()) {
94         return;
95     }
96 
97     // remove from disappearing children
98     RemoveDisappearingChild(child);
99     it = children_.begin();
100     std::advance(it, slot);
101     DoAddChild(it, child, silently, addDefaultTransition);
102 }
103 
AddChildAfter(const RefPtr<UINode> & child,const RefPtr<UINode> & siblingNode)104 void UINode::AddChildAfter(const RefPtr<UINode>& child, const RefPtr<UINode>& siblingNode)
105 {
106     CHECK_NULL_VOID(child);
107     CHECK_NULL_VOID(siblingNode);
108     auto it = std::find(children_.begin(), children_.end(), child);
109     if (it != children_.end()) {
110         LOGW("Child node already exists. Existing child nodeId %{public}d, add %{public}s child nodeId nodeId "
111              "%{public}d",
112             (*it)->GetId(), child->GetTag().c_str(), child->GetId());
113         return;
114     }
115     // remove from disappearing children
116     RemoveDisappearingChild(child);
117     auto siblingNodeIter = std::find(children_.begin(), children_.end(), siblingNode);
118     if (siblingNodeIter != children_.end()) {
119         DoAddChild(++siblingNodeIter, child, false);
120         return;
121     }
122     it = children_.begin();
123     std::advance(it, -1);
124     DoAddChild(it, child, false);
125 }
126 
RemoveChild(const RefPtr<UINode> & child,bool allowTransition)127 std::list<RefPtr<UINode>>::iterator UINode::RemoveChild(const RefPtr<UINode>& child, bool allowTransition)
128 {
129     CHECK_NULL_RETURN(child, children_.end());
130 
131     auto iter = std::find(children_.begin(), children_.end(), child);
132     if (iter == children_.end()) {
133         return children_.end();
134     }
135     // If the child is undergoing a disappearing transition, rather than simply removing it, we should move it to the
136     // disappearing children. This ensures that the child remains alive and the tree hierarchy is preserved until the
137     // transition has finished. We can then perform the necessary cleanup after the transition is complete.
138     if ((*iter)->OnRemoveFromParent(allowTransition)) {
139         // OnRemoveFromParent returns true means the child can be removed from tree immediately.
140         RemoveDisappearingChild(child);
141     } else {
142         // else move child into disappearing children, skip syncing render tree
143         AddDisappearingChild(child, std::distance(children_.begin(), iter));
144     }
145     MarkNeedSyncRenderTree(true);
146     auto result = children_.erase(iter);
147     return result;
148 }
149 
RemoveChildAndReturnIndex(const RefPtr<UINode> & child)150 int32_t UINode::RemoveChildAndReturnIndex(const RefPtr<UINode>& child)
151 {
152     auto result = RemoveChild(child);
153     return std::distance(children_.begin(), result);
154 }
155 
RemoveChildAtIndex(int32_t index)156 void UINode::RemoveChildAtIndex(int32_t index)
157 {
158     auto children = GetChildren();
159     if ((index < 0) || (index >= static_cast<int32_t>(children.size()))) {
160         return;
161     }
162     auto iter = children.begin();
163     std::advance(iter, index);
164     RemoveChild(*iter);
165 }
166 
GetChildAtIndex(int32_t index) const167 RefPtr<UINode> UINode::GetChildAtIndex(int32_t index) const
168 {
169     auto children = GetChildren();
170     if ((index < 0) || (index >= static_cast<int32_t>(children.size()))) {
171         return nullptr;
172     }
173     auto iter = children.begin();
174     std::advance(iter, index);
175     if (iter != children.end()) {
176         return *iter;
177     }
178     return nullptr;
179 }
180 
GetChildIndex(const RefPtr<UINode> & child) const181 int32_t UINode::GetChildIndex(const RefPtr<UINode>& child) const
182 {
183     int32_t index = 0;
184     for (const auto& iter : GetChildren()) {
185         if (iter == child) {
186             return index;
187         }
188         index++;
189     }
190     return -1;
191 }
192 
ReplaceChild(const RefPtr<UINode> & oldNode,const RefPtr<UINode> & newNode)193 void UINode::ReplaceChild(const RefPtr<UINode>& oldNode, const RefPtr<UINode>& newNode)
194 {
195     if (!oldNode) {
196         if (newNode) {
197             AddChild(newNode);
198         }
199         return;
200     }
201 
202     auto iter = RemoveChild(oldNode);
203     DoAddChild(iter, newNode, false, false);
204 }
205 
Clean(bool cleanDirectly,bool allowTransition)206 void UINode::Clean(bool cleanDirectly, bool allowTransition)
207 {
208     bool needSyncRenderTree = false;
209     int32_t index = 0;
210     for (const auto& child : children_) {
211         // traverse down the child subtree to mark removing and find needs to hold subtree, if found add it to pending
212         if (!cleanDirectly && child->MarkRemoving()) {
213             ElementRegister::GetInstance()->AddPendingRemoveNode(child);
214         }
215         // If the child is undergoing a disappearing transition, rather than simply removing it, we should move it to
216         // the disappearing children. This ensures that the child remains alive and the tree hierarchy is preserved
217         // until the transition has finished. We can then perform the necessary cleanup after the transition is
218         // complete.
219         if (child->OnRemoveFromParent(allowTransition)) {
220             // OnRemoveFromParent returns true means the child can be removed from tree immediately.
221             RemoveDisappearingChild(child);
222             needSyncRenderTree = true;
223         } else {
224             // else move child into disappearing children, skip syncing render tree
225             AddDisappearingChild(child, index);
226         }
227         ++index;
228     }
229     children_.clear();
230     MarkNeedSyncRenderTree(true);
231 }
232 
MountToParent(const RefPtr<UINode> & parent,int32_t slot,bool silently,bool addDefaultTransition)233 void UINode::MountToParent(const RefPtr<UINode>& parent, int32_t slot, bool silently, bool addDefaultTransition)
234 {
235     CHECK_NULL_VOID(parent);
236     parent->AddChild(AceType::Claim(this), slot, silently, addDefaultTransition);
237     if (parent->IsInDestroying()) {
238         parent->SetChildrenInDestroying();
239     }
240     if (parent->GetPageId() != 0) {
241         SetHostPageId(parent->GetPageId());
242     }
243 }
244 
UpdateConfigurationUpdate(const ConfigurationChange & configurationChange)245 void UINode::UpdateConfigurationUpdate(const ConfigurationChange& configurationChange)
246 {
247     OnConfigurationUpdate(configurationChange);
248     if (needCallChildrenUpdate_) {
249         auto children = GetChildren();
250         for (const auto& child : children) {
251             if (!child) {
252                 continue;
253             }
254             child->UpdateConfigurationUpdate(configurationChange);
255         }
256     }
257 }
258 
OnRemoveFromParent(bool allowTransition)259 bool UINode::OnRemoveFromParent(bool allowTransition)
260 {
261     // The recursive flag will used by RenderContext, if recursive flag is false,
262     // it may trigger transition
263     DetachFromMainTree(!allowTransition);
264     if (allowTransition && !RemoveImmediately()) {
265         return false;
266     }
267     ResetParent();
268     return true;
269 }
270 
ResetParent()271 void UINode::ResetParent()
272 {
273     parent_.Reset();
274     depth_ = -1;
275 }
276 
DoAddChild(std::list<RefPtr<UINode>>::iterator & it,const RefPtr<UINode> & child,bool silently,bool addDefaultTransition)277 void UINode::DoAddChild(
278     std::list<RefPtr<UINode>>::iterator& it, const RefPtr<UINode>& child, bool silently, bool addDefaultTransition)
279 {
280     children_.insert(it, child);
281 
282     child->SetParent(Claim(this));
283     child->SetDepth(GetDepth() + 1);
284     if (nodeStatus_ != NodeStatus::NORMAL_NODE) {
285         child->UpdateNodeStatus(nodeStatus_);
286     }
287 
288     if (!silently && onMainTree_) {
289         child->AttachToMainTree(!addDefaultTransition);
290     }
291     MarkNeedSyncRenderTree(true);
292 }
293 
GetFocusParent() const294 RefPtr<FrameNode> UINode::GetFocusParent() const
295 {
296     auto parentUi = GetParent();
297     while (parentUi) {
298         auto parentFrame = AceType::DynamicCast<FrameNode>(parentUi);
299         if (!parentFrame) {
300             parentUi = parentUi->GetParent();
301             continue;
302         }
303         auto type = parentFrame->GetFocusType();
304         if (type == FocusType::SCOPE) {
305             return parentFrame;
306         }
307         if (type == FocusType::NODE) {
308             return nullptr;
309         }
310         parentUi = parentUi->GetParent();
311     }
312     return nullptr;
313 }
314 
GetFirstFocusHubChild() const315 RefPtr<FocusHub> UINode::GetFirstFocusHubChild() const
316 {
317     const auto* frameNode = AceType::DynamicCast<FrameNode>(this);
318     if (frameNode) {
319         auto focusHub = frameNode->GetFocusHub();
320         if (focusHub && focusHub->GetFocusType() != FocusType::DISABLE) {
321             return focusHub;
322         }
323     }
324     for (const auto& child : GetChildren()) {
325         auto focusHub = child->GetFirstFocusHubChild();
326         if (focusHub) {
327             return focusHub;
328         }
329     }
330     return nullptr;
331 }
332 
GetFocusChildren(std::list<RefPtr<FrameNode>> & children) const333 void UINode::GetFocusChildren(std::list<RefPtr<FrameNode>>& children) const
334 {
335     auto uiChildren = GetChildren();
336     for (const auto& uiChild : uiChildren) {
337         auto frameChild = AceType::DynamicCast<FrameNode>(uiChild);
338         if (frameChild && frameChild->GetFocusType() != FocusType::DISABLE) {
339             children.emplace_back(frameChild);
340         } else {
341             uiChild->GetFocusChildren(children);
342         }
343     }
344 }
345 
AttachToMainTree(bool recursive)346 void UINode::AttachToMainTree(bool recursive)
347 {
348     if (onMainTree_) {
349         return;
350     }
351     onMainTree_ = true;
352     if (nodeStatus_ == NodeStatus::BUILDER_NODE_OFF_MAINTREE) {
353         nodeStatus_ = NodeStatus::BUILDER_NODE_ON_MAINTREE;
354     }
355     isRemoving_ = false;
356     OnAttachToMainTree(recursive);
357     // if recursive = false, recursively call AttachToMainTree(false), until we reach the first FrameNode.
358     bool isRecursive = recursive || AceType::InstanceOf<FrameNode>(this);
359     for (const auto& child : GetChildren()) {
360         child->AttachToMainTree(isRecursive);
361     }
362 }
363 
DetachFromMainTree(bool recursive)364 void UINode::DetachFromMainTree(bool recursive)
365 {
366     if (!onMainTree_) {
367         return;
368     }
369     onMainTree_ = false;
370     if (nodeStatus_ == NodeStatus::BUILDER_NODE_ON_MAINTREE) {
371         nodeStatus_ = NodeStatus::BUILDER_NODE_OFF_MAINTREE;
372     }
373     isRemoving_ = true;
374     OnDetachFromMainTree(recursive);
375     // if recursive = false, recursively call DetachFromMainTree(false), until we reach the first FrameNode.
376     bool isRecursive = recursive || AceType::InstanceOf<FrameNode>(this);
377     for (const auto& child : GetChildren()) {
378         child->DetachFromMainTree(isRecursive);
379     }
380 }
381 
ProcessOffscreenTask(bool recursive)382 void UINode::ProcessOffscreenTask(bool recursive)
383 {
384     if (useOffscreenProcess_) {
385         return;
386     }
387     useOffscreenProcess_ = true;
388     OnOffscreenProcess(recursive);
389     // if recursive = false, recursively call AttachToMainTree(false), until we reach the first FrameNode.
390     bool isRecursive = recursive || AceType::InstanceOf<FrameNode>(this);
391     for (const auto& child : GetChildren()) {
392         child->ProcessOffscreenTask(isRecursive);
393     }
394 }
395 
MovePosition(int32_t slot)396 void UINode::MovePosition(int32_t slot)
397 {
398     auto parentNode = parent_.Upgrade();
399     CHECK_NULL_VOID(parentNode);
400 
401     auto self = AceType::Claim(this);
402     auto& children = parentNode->children_;
403     auto it = children.end();
404     if (slot >= 0 && static_cast<size_t>(slot) < children.size()) {
405         it = children.begin();
406         std::advance(it, slot);
407         if ((it != children.end()) && (*it == this)) {
408             // Already at the right place
409             return;
410         }
411 
412         auto itSelf = std::find(it, children.end(), self);
413         if (itSelf != children.end()) {
414             children.erase(itSelf);
415         } else {
416             children.remove(self);
417             ++it;
418         }
419     } else {
420         children.remove(self);
421     }
422     children.insert(it, self);
423     parentNode->MarkNeedSyncRenderTree(true);
424 }
425 
UpdateLayoutPropertyFlag()426 void UINode::UpdateLayoutPropertyFlag()
427 {
428     for (const auto& child : GetChildren()) {
429         child->UpdateLayoutPropertyFlag();
430     }
431 }
432 
AdjustParentLayoutFlag(PropertyChangeFlag & flag)433 void UINode::AdjustParentLayoutFlag(PropertyChangeFlag& flag)
434 {
435     for (const auto& child : GetChildren()) {
436         child->AdjustParentLayoutFlag(flag);
437     }
438 }
439 
MarkDirtyNode(PropertyChangeFlag extraFlag,bool childExpansiveAndMark)440 void UINode::MarkDirtyNode(PropertyChangeFlag extraFlag, bool childExpansiveAndMark)
441 {
442     for (const auto& child : GetChildren()) {
443         child->MarkDirtyNode(extraFlag, childExpansiveAndMark);
444     }
445 }
446 
MarkNeedFrameFlushDirty(PropertyChangeFlag extraFlag)447 void UINode::MarkNeedFrameFlushDirty(PropertyChangeFlag extraFlag)
448 {
449     auto parent = parent_.Upgrade();
450     if (parent) {
451         parent->MarkNeedFrameFlushDirty(extraFlag);
452     }
453 }
454 
MarkNeedSyncRenderTree(bool needRebuild)455 void UINode::MarkNeedSyncRenderTree(bool needRebuild)
456 {
457     auto parent = parent_.Upgrade();
458     if (parent) {
459         parent->MarkNeedSyncRenderTree(needRebuild);
460     }
461 }
462 
RebuildRenderContextTree()463 void UINode::RebuildRenderContextTree()
464 {
465     auto parent = parent_.Upgrade();
466     if (parent) {
467         parent->RebuildRenderContextTree();
468     }
469 }
OnDetachFromMainTree(bool)470 void UINode::OnDetachFromMainTree(bool) {}
471 
OnAttachToMainTree(bool)472 void UINode::OnAttachToMainTree(bool)
473 {
474     useOffscreenProcess_ = false;
475     decltype(attachToMainTreeTasks_) tasks(std::move(attachToMainTreeTasks_));
476     for (const auto& task : tasks) {
477         if (task) {
478             task();
479         }
480     }
481 }
482 
DumpViewDataPageNodes(RefPtr<ViewDataWrap> viewDataWrap)483 void UINode::DumpViewDataPageNodes(RefPtr<ViewDataWrap> viewDataWrap)
484 {
485     DumpViewDataPageNode(viewDataWrap);
486     for (const auto& item : GetChildren()) {
487         item->DumpViewDataPageNodes(viewDataWrap);
488     }
489 }
490 
NeedRequestAutoSave()491 bool UINode::NeedRequestAutoSave()
492 {
493     if (CheckAutoSave()) {
494         return true;
495     }
496     for (const auto& item : GetChildren()) {
497         if (item->NeedRequestAutoSave()) {
498             return true;
499         }
500     }
501     return false;
502 }
503 
DumpTree(int32_t depth)504 void UINode::DumpTree(int32_t depth)
505 {
506     if (DumpLog::GetInstance().GetDumpFile()) {
507         DumpLog::GetInstance().AddDesc("ID: " + std::to_string(nodeId_));
508         DumpLog::GetInstance().AddDesc(std::string("Depth: ").append(std::to_string(GetDepth())));
509         DumpLog::GetInstance().AddDesc("AccessibilityId: " + std::to_string(accessibilityId_));
510         if (IsDisappearing()) {
511             DumpLog::GetInstance().AddDesc(std::string("IsDisappearing: ").append(std::to_string(IsDisappearing())));
512         }
513         DumpInfo();
514         DumpLog::GetInstance().Append(depth, tag_, static_cast<int32_t>(GetChildren().size()));
515     }
516     for (const auto& item : GetChildren()) {
517         item->DumpTree(depth + 1);
518     }
519     for (const auto& [item, index] : disappearingChildren_) {
520         item->DumpTree(depth + 1);
521     }
522     auto frameNode = AceType::DynamicCast<FrameNode>(this);
523     if (frameNode && frameNode->GetOverlayNode()) {
524         frameNode->GetOverlayNode()->DumpTree(depth + 1);
525     }
526 }
527 
DumpTreeById(int32_t depth,const std::string & id)528 bool UINode::DumpTreeById(int32_t depth, const std::string& id)
529 {
530     if (DumpLog::GetInstance().GetDumpFile() &&
531         (id == propInspectorId_.value_or("") || id == std::to_string(nodeId_))) {
532         DumpLog::GetInstance().AddDesc("ID: " + std::to_string(nodeId_));
533         DumpLog::GetInstance().AddDesc(std::string("Depth: ").append(std::to_string(GetDepth())));
534         DumpLog::GetInstance().AddDesc(std::string("IsDisappearing: ").append(std::to_string(IsDisappearing())));
535         DumpAdvanceInfo();
536         DumpLog::GetInstance().Print(depth, tag_, static_cast<int32_t>(GetChildren().size()));
537         return true;
538     }
539     for (const auto& item : GetChildren()) {
540         if (item->DumpTreeById(depth + 1, id)) {
541             return true;
542         }
543     }
544     for (const auto& [item, index] : disappearingChildren_) {
545         if (item->DumpTreeById(depth + 1, id)) {
546             return true;
547         }
548     }
549     return false;
550 }
551 
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode> & parent,bool forceMeasure,bool forceLayout)552 void UINode::AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout)
553 {
554     for (const auto& child : children_) {
555         if (!child->IsInDestroying()) {
556             child->AdjustLayoutWrapperTree(parent, forceMeasure, forceLayout);
557         }
558     }
559 }
560 
GenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & visibleList)561 void UINode::GenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& visibleList)
562 {
563     for (const auto& child : GetChildren()) {
564         child->OnGenerateOneDepthVisibleFrame(visibleList);
565     }
566 }
567 
GenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)568 void UINode::GenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList)
569 {
570     if (disappearingChildren_.empty()) {
571         // normal child
572         for (const auto& child : GetChildren()) {
573             child->OnGenerateOneDepthVisibleFrameWithTransition(visibleList);
574         }
575         return;
576     }
577     // generate the merged list of children_ and disappearingChildren_
578     auto allChildren = GetChildren();
579     for (auto iter = disappearingChildren_.rbegin(); iter != disappearingChildren_.rend(); ++iter) {
580         auto& [disappearingChild, index] = *iter;
581         if (index >= allChildren.size()) {
582             allChildren.emplace_back(disappearingChild);
583         } else {
584             auto insertIter = allChildren.begin();
585             std::advance(insertIter, index);
586             allChildren.insert(insertIter, disappearingChild);
587         }
588     }
589     for (const auto& child : allChildren) {
590         child->OnGenerateOneDepthVisibleFrameWithTransition(visibleList);
591     }
592 }
593 
GenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>> & visibleList)594 void UINode::GenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>>& visibleList)
595 {
596     for (const auto& child : GetChildren()) {
597         child->OnGenerateOneDepthAllFrame(visibleList);
598     }
599 }
600 
GetContext()601 RefPtr<PipelineContext> UINode::GetContext()
602 {
603     return PipelineContext::GetCurrentContext();
604 }
605 
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId,bool isDispatch)606 HitTestResult UINode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
607     const PointF& parentRevertPoint, TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId,
608     bool isDispatch)
609 {
610     auto children = GetChildren();
611     HitTestResult hitTestResult = HitTestResult::OUT_OF_REGION;
612     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
613         auto& child = *iter;
614         auto hitResult =
615             child->TouchTest(globalPoint, parentLocalPoint, parentRevertPoint, touchRestrict, result, touchId);
616         if (hitResult == HitTestResult::STOP_BUBBLING) {
617             return HitTestResult::STOP_BUBBLING;
618         }
619         if (hitResult == HitTestResult::BUBBLING) {
620             hitTestResult = HitTestResult::BUBBLING;
621         }
622     }
623     return hitTestResult;
624 }
625 
MouseTest(const PointF & globalPoint,const PointF & parentLocalPoint,MouseTestResult & onMouseResult,MouseTestResult & onHoverResult,RefPtr<FrameNode> & hoverNode)626 HitTestResult UINode::MouseTest(const PointF& globalPoint, const PointF& parentLocalPoint,
627     MouseTestResult& onMouseResult, MouseTestResult& onHoverResult, RefPtr<FrameNode>& hoverNode)
628 {
629     auto children = GetChildren();
630     HitTestResult hitTestResult = HitTestResult::OUT_OF_REGION;
631     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
632         auto& child = *iter;
633         auto hitResult = child->MouseTest(globalPoint, parentLocalPoint, onMouseResult, onHoverResult, hoverNode);
634         if (hitResult == HitTestResult::STOP_BUBBLING) {
635             return HitTestResult::STOP_BUBBLING;
636         }
637         if (hitResult == HitTestResult::BUBBLING) {
638             hitTestResult = HitTestResult::BUBBLING;
639         }
640     }
641     return hitTestResult;
642 }
643 
AxisTest(const PointF & globalPoint,const PointF & parentLocalPoint,AxisTestResult & onAxisResult)644 HitTestResult UINode::AxisTest(const PointF& globalPoint, const PointF& parentLocalPoint, AxisTestResult& onAxisResult)
645 {
646     auto children = GetChildren();
647     HitTestResult hitTestResult = HitTestResult::OUT_OF_REGION;
648     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
649         auto& child = *iter;
650         auto hitResult = child->AxisTest(globalPoint, parentLocalPoint, onAxisResult);
651         if (hitResult == HitTestResult::STOP_BUBBLING) {
652             return HitTestResult::STOP_BUBBLING;
653         }
654         if (hitResult == HitTestResult::BUBBLING) {
655             hitTestResult = HitTestResult::BUBBLING;
656         }
657     }
658     return hitTestResult;
659 }
660 
FrameCount() const661 int32_t UINode::FrameCount() const
662 {
663     return TotalChildCount();
664 }
665 
TotalChildCount() const666 int32_t UINode::TotalChildCount() const
667 {
668     int32_t count = 0;
669     for (const auto& child : GetChildren()) {
670         count += child->FrameCount();
671     }
672     return count;
673 }
674 
GetChildIndexById(int32_t id)675 int32_t UINode::GetChildIndexById(int32_t id)
676 {
677     int32_t pos = 0;
678     auto children = GetChildren();
679     auto iter = children.begin();
680     while (iter != children.end()) {
681         if (id == (*iter)->GetId()) {
682             return pos;
683         }
684         pos++;
685         iter++;
686     }
687     return -1;
688 }
689 
CreateLayoutWrapper(bool forceMeasure,bool forceLayout)690 RefPtr<LayoutWrapperNode> UINode::CreateLayoutWrapper(bool forceMeasure, bool forceLayout)
691 {
692     if (GetChildren().empty()) {
693         return nullptr;
694     }
695 
696     auto child = GetChildren().front();
697     while (!InstanceOf<FrameNode>(child)) {
698         auto children = child->GetChildren();
699         if (children.empty()) {
700             return nullptr;
701         }
702 
703         child = children.front();
704     }
705 
706     auto frameChild = DynamicCast<FrameNode>(child);
707     return frameChild ? frameChild->CreateLayoutWrapper(forceMeasure, forceLayout) : nullptr;
708 }
709 
RenderCustomChild(int64_t deadline)710 bool UINode::RenderCustomChild(int64_t deadline)
711 {
712     for (const auto& child : GetChildren()) {
713         if (child && !child->RenderCustomChild(deadline)) {
714             return false;
715         }
716     }
717     return true;
718 }
719 
Build(std::shared_ptr<std::list<ExtraInfo>> extraInfos)720 void UINode::Build(std::shared_ptr<std::list<ExtraInfo>> extraInfos)
721 {
722     for (const auto& child : GetChildren()) {
723         if (InstanceOf<CustomNode>(child)) {
724             auto custom = DynamicCast<CustomNode>(child);
725             if (custom->HasExtraInfo()) {
726                 if (!extraInfos) {
727                     extraInfos = std::make_shared<std::list<ExtraInfo>>();
728                 }
729                 extraInfos->emplace_front(custom->GetExtraInfo());
730                 custom->Build(extraInfos);
731                 extraInfos->pop_front();
732             } else {
733                 custom->Build(extraInfos);
734             }
735         } else {
736             child->Build(extraInfos);
737         }
738     }
739 }
740 
CreateExportTextureInfoIfNeeded()741 void UINode::CreateExportTextureInfoIfNeeded()
742 {
743     if (!exportTextureInfo_) {
744         exportTextureInfo_ = MakeRefPtr<ExportTextureInfo>();
745     }
746 }
747 
IsNeedExportTexture() const748 bool UINode::IsNeedExportTexture() const
749 {
750     return exportTextureInfo_ && exportTextureInfo_->GetCurrentRenderType() == NodeRenderType::RENDER_TYPE_TEXTURE;
751 }
752 
SetActive(bool active)753 void UINode::SetActive(bool active)
754 {
755     for (const auto& child : GetChildren()) {
756         child->SetActive(active);
757     }
758 }
759 
SetJSViewActive(bool active)760 void UINode::SetJSViewActive(bool active)
761 {
762     for (const auto& child : GetChildren()) {
763         auto frameNodeChild = AceType::DynamicCast<FrameNode>(child);
764         // if child is framenode and its state is inactive, and the new state is active, then
765         // do not inform the state recursively
766         // List (active)
767         //   |--ListItem(inActive)
768         //     |--CustomComponent(fellow ListItem)
769         // if the List setActive(true) when doing some measuring or layout, ListItem is inActive, then
770         // the customComponent only follow the ListItem state changes
771         if (frameNodeChild && !frameNodeChild->IsActive() && active) {
772             return;
773         }
774         child->SetJSViewActive(active);
775     }
776 }
777 
OnVisibleChange(bool isVisible)778 void UINode::OnVisibleChange(bool isVisible)
779 {
780     UpdateChildrenVisible(isVisible);
781 }
782 
UpdateChildrenVisible(bool isVisible) const783 void UINode::UpdateChildrenVisible(bool isVisible) const
784 {
785     for (const auto& child : GetChildren()) {
786         if (InstanceOf<FrameNode>(child)) {
787             auto childLayoutProperty = DynamicCast<FrameNode>(child)->GetLayoutProperty();
788             if (childLayoutProperty &&
789                 childLayoutProperty->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
790                 // child is invisible, no need to update visible state.
791                 continue;
792             }
793         }
794         child->OnVisibleChange(isVisible);
795     }
796 }
797 
GetChildFlatIndex(int32_t id)798 std::pair<bool, int32_t> UINode::GetChildFlatIndex(int32_t id)
799 {
800     if (GetId() == id) {
801         return { true, 0 };
802     }
803 
804     const auto& node = ElementRegister::GetInstance()->GetUINodeById(id);
805     if (!node) {
806         return { false, 0 };
807     }
808 
809     if (node && (node->GetTag() == GetTag())) {
810         return { false, 1 };
811     }
812 
813     int32_t count = 0;
814     for (const auto& child : GetChildren()) {
815         auto res = child->GetChildFlatIndex(id);
816         if (res.first) {
817             return { true, count + res.second };
818         }
819         count += res.second;
820     }
821     return { false, count };
822 }
823 
824 // for Grid refresh GridItems
ChildrenUpdatedFrom(int32_t index)825 void UINode::ChildrenUpdatedFrom(int32_t index)
826 {
827     childrenUpdatedFrom_ = childrenUpdatedFrom_ >= 0 ? std::min(index, childrenUpdatedFrom_) : index;
828 }
829 
MarkRemoving()830 bool UINode::MarkRemoving()
831 {
832     bool pendingRemove = false;
833     isRemoving_ = true;
834     const auto& children = GetChildren();
835     for (const auto& child : children) {
836         pendingRemove = child->MarkRemoving() || pendingRemove;
837     }
838     return pendingRemove;
839 }
840 
SetChildrenInDestroying()841 void UINode::SetChildrenInDestroying()
842 {
843     auto children = GetChildren();
844     if (children.empty()) {
845         return;
846     }
847 
848     for (const auto& child : children) {
849         if (!child) {
850             continue;
851         }
852         child->SetChildrenInDestroying();
853         child->SetInDestroying();
854     }
855 }
856 
AddDisappearingChild(const RefPtr<UINode> & child,uint32_t index)857 void UINode::AddDisappearingChild(const RefPtr<UINode>& child, uint32_t index)
858 {
859     if (child->isDisappearing_) {
860         // if child is already disappearing, remove it from disappearingChildren_ first
861         auto it = std::find_if(disappearingChildren_.begin(), disappearingChildren_.end(),
862             [child](const auto& pair) { return pair.first == child; });
863         if (it != disappearingChildren_.end()) {
864             disappearingChildren_.erase(it);
865         }
866     } else {
867         // mark child as disappearing before adding to disappearingChildren_
868         child->isDisappearing_ = true;
869     }
870     disappearingChildren_.emplace_back(child, index);
871 }
872 
RemoveDisappearingChild(const RefPtr<UINode> & child)873 bool UINode::RemoveDisappearingChild(const RefPtr<UINode>& child)
874 {
875     // quick reject
876     if (!child->isDisappearing_) {
877         return false;
878     }
879     auto it = std::find_if(disappearingChildren_.begin(), disappearingChildren_.end(),
880         [child](const auto& pair) { return pair.first == child; });
881     if (it == disappearingChildren_.end()) {
882         return false;
883     }
884     disappearingChildren_.erase(it);
885     child->isDisappearing_ = false;
886     return true;
887 }
888 
OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)889 void UINode::OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList)
890 {
891     GenerateOneDepthVisibleFrameWithTransition(visibleList);
892 }
893 
RemoveImmediately() const894 bool UINode::RemoveImmediately() const
895 {
896     auto children = GetChildren();
897     return std::all_of(
898                children.begin(), children.end(), [](const auto& child) { return child->RemoveImmediately(); }) &&
899            std::all_of(disappearingChildren_.begin(), disappearingChildren_.end(),
900                [](const auto& pair) { return pair.first->RemoveImmediately(); });
901 }
902 
GetPerformanceCheckData(PerformanceCheckNodeMap & nodeMap)903 void UINode::GetPerformanceCheckData(PerformanceCheckNodeMap& nodeMap)
904 {
905     auto parent = GetParent();
906     auto children = GetChildren();
907     if (parent && parent->GetTag() == V2::JS_FOR_EACH_ETS_TAG) {
908         // At this point, all of the children_
909         // belong to the child nodes of syntaxItem
910         for (const auto& child : children) {
911             if (child->GetTag() == V2::COMMON_VIEW_ETS_TAG) {
912                 auto grandChildren = child->GetChildren();
913                 if (!grandChildren.empty()) {
914                     auto begin = grandChildren.begin();
915                     (*begin)->SetForeachItem();
916                 }
917             } else {
918                 child->SetForeachItem();
919             }
920         }
921     }
922 
923     if (tag_ == V2::COMMON_VIEW_ETS_TAG) {
924         if (!children.empty()) {
925             auto begin = children.begin();
926             nodeInfo_->nodeTag = (*begin)->GetCustomTag();
927         }
928     } else {
929         nodeInfo_->nodeTag = GetCustomTag();
930     }
931 
932     nodeInfo_->pageDepth = depth_;
933     nodeInfo_->childrenSize = children.size();
934     if (isBuildByJS_) {
935         nodeMap.insert({ GetId(), *(nodeInfo_) });
936     }
937     for (const auto& child : children) {
938         // Recursively traverse the child nodes of each node
939         child->GetPerformanceCheckData(nodeMap);
940     }
941 }
942 
GetDisappearingChildById(const std::string & id) const943 RefPtr<UINode> UINode::GetDisappearingChildById(const std::string& id) const
944 {
945     if (id.empty()) {
946         return nullptr;
947     }
948     for (auto& [node, index] : disappearingChildren_) {
949         if (node->GetInspectorIdValue("") == id) {
950             return node;
951         }
952     }
953     return nullptr;
954 }
955 
GetFrameChildByIndex(uint32_t index,bool needBuild)956 RefPtr<UINode> UINode::GetFrameChildByIndex(uint32_t index, bool needBuild)
957 {
958     for (const auto& child : GetChildren()) {
959         uint32_t count = static_cast<uint32_t>(child->FrameCount());
960         if (count > index) {
961             return child->GetFrameChildByIndex(index, needBuild);
962         }
963         index -= count;
964     }
965     return nullptr;
966 }
967 
DoRemoveChildInRenderTree(uint32_t index,bool isAll)968 void UINode::DoRemoveChildInRenderTree(uint32_t index, bool isAll)
969 {
970     if (isAll) {
971         for (const auto& child : children_) {
972             child->DoRemoveChildInRenderTree(index, isAll);
973         }
974         return;
975     }
976     for (const auto& child : children_) {
977         uint32_t count = static_cast<uint32_t>(child->FrameCount());
978         if (count > index) {
979             return child->DoRemoveChildInRenderTree(index);
980         }
981         index -= count;
982     }
983 }
984 
DoSetActiveChildRange(int32_t start,int32_t end)985 void UINode::DoSetActiveChildRange(int32_t start, int32_t end)
986 {
987     for (const auto& child : children_) {
988         uint32_t count = static_cast<uint32_t>(child->FrameCount());
989         child->DoSetActiveChildRange(start, end);
990         start -= static_cast<int32_t>(count);
991         end -= static_cast<int32_t>(count);
992     }
993 }
994 
OnSetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)995 void UINode::OnSetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
996 {
997     for (const auto& child : GetChildren()) {
998         child->OnSetCacheCount(cacheCount, itemConstraint);
999     }
1000 }
1001 
GetCurrentCustomNodeInfo()1002 std::string UINode::GetCurrentCustomNodeInfo()
1003 {
1004     auto parent = AceType::Claim(this);
1005     std::string extraInfo;
1006     while (parent) {
1007         if (InstanceOf<CustomNode>(parent)) {
1008             auto custom = DynamicCast<CustomNode>(parent);
1009             auto list = custom->GetExtraInfos();
1010             for (const auto& child : list) {
1011                 extraInfo.append("    ").append("at (").append(child.page).append(":")
1012                     .append(std::to_string(child.line)).append(")\n");
1013             }
1014             break;
1015         }
1016         parent = parent->GetParent();
1017 
1018     }
1019     return extraInfo;
1020 }
1021 
GenerateAccessibilityId()1022 int64_t UINode::GenerateAccessibilityId()
1023 {
1024     return currentAccessibilityId_++;
1025 }
1026 
GetNodeStatus() const1027 NodeStatus UINode::GetNodeStatus() const
1028 {
1029     return nodeStatus_;
1030 }
1031 
SetParentLayoutConstraint(const SizeF & size) const1032 bool UINode::SetParentLayoutConstraint(const SizeF& size) const
1033 {
1034     auto children = GetChildren();
1035     return std::any_of(children.begin(), children.end(),
1036         [size](const RefPtr<UINode>& child) { return child->SetParentLayoutConstraint(size); });
1037 }
1038 
UpdateNodeStatus(NodeStatus nodeStatus)1039 void UINode::UpdateNodeStatus(NodeStatus nodeStatus)
1040 {
1041     nodeStatus_ = nodeStatus;
1042     for (const auto& child : children_) {
1043         if (child->GetNodeStatus() == nodeStatus_) {
1044             continue;
1045         }
1046         child->OnAttachToBuilderNode(nodeStatus_);
1047         child->UpdateNodeStatus(nodeStatus_);
1048     }
1049 }
1050 } // namespace OHOS::Ace::NG
1051