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