• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
16 #include "core/components_ng/syntax/lazy_for_each_node.h"
17 
18 #include "base/log/ace_trace.h"
19 #include "base/log/dump_log.h"
20 #include "base/memory/referenced.h"
21 #include "base/utils/time_util.h"
22 #include "base/utils/utils.h"
23 #include "core/components_ng/base/view_stack_processor.h"
24 #include "core/components_ng/property/property.h"
25 #include "core/components_ng/syntax/lazy_layout_wrapper_builder.h"
26 #include "core/components_v2/inspector/inspector_constants.h"
27 #include "core/pipeline/base/element_register.h"
28 #include "core/pipeline_ng/pipeline_context.h"
29 
30 namespace OHOS::Ace::NG {
31 
GetOrCreateLazyForEachNode(int32_t nodeId,const RefPtr<LazyForEachBuilder> & forEachBuilder)32 RefPtr<LazyForEachNode> LazyForEachNode::GetOrCreateLazyForEachNode(
33     int32_t nodeId, const RefPtr<LazyForEachBuilder>& forEachBuilder)
34 {
35     auto node = ElementRegister::GetInstance()->GetSpecificItemById<LazyForEachNode>(nodeId);
36     if (node) {
37         if (node->builder_ != forEachBuilder) {
38             LOGW("replace old lazy for each builder");
39             node->builder_ = forEachBuilder;
40         }
41         return node;
42     }
43     node = MakeRefPtr<LazyForEachNode>(nodeId, forEachBuilder);
44     ElementRegister::GetInstance()->AddUINode(node);
45     return node;
46 }
47 
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode> & parent,bool forceMeasure,bool forceLayout)48 void LazyForEachNode::AdjustLayoutWrapperTree(
49     const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout)
50 {
51     CHECK_NULL_VOID(builder_);
52     auto lazyLayoutWrapperBuilder = MakeRefPtr<LazyLayoutWrapperBuilder>(builder_, WeakClaim(this));
53     if (parent->GetHostTag() == V2::SWIPER_ETS_TAG) {
54         lazyLayoutWrapperBuilder->SetLazySwiper();
55     }
56     lazyLayoutWrapperBuilder->UpdateForceFlag(forceMeasure, forceLayout);
57     parent->SetLayoutWrapperBuilder(lazyLayoutWrapperBuilder);
58 }
59 
BuildAllChildren()60 void LazyForEachNode::BuildAllChildren()
61 {
62     for (int i = 0; i < FrameCount(); i++) {
63         GetFrameChildByIndex(i, true);
64     }
65     children_.clear();
66     auto items = builder_->GetAllChildren();
67     for (auto& [index, item] : items) {
68         if (item.second) {
69             children_.push_back(item.second);
70         }
71     }
72 }
73 
PostIdleTask()74 void LazyForEachNode::PostIdleTask()
75 {
76     if (needPredict_) {
77         return;
78     }
79     needPredict_ = true;
80     auto context = GetContext();
81     CHECK_NULL_VOID(context);
82     context->AddPredictTask([weak = AceType::WeakClaim(this)](int64_t deadline, bool canUseLongPredictTask) {
83         auto node = weak.Upgrade();
84         CHECK_NULL_VOID(node);
85         node->needPredict_ = false;
86         auto canRunLongPredictTask = node->requestLongPredict_ && canUseLongPredictTask;
87         if (node->builder_) {
88             auto preBuildResult = node->builder_->PreBuild(deadline, node->itemConstraint_, canRunLongPredictTask);
89             if (!preBuildResult) {
90                 node->PostIdleTask();
91             }
92         }
93         node->requestLongPredict_ = false;
94         node->itemConstraint_.reset();
95     });
96 }
97 
OnDataReloaded()98 void LazyForEachNode::OnDataReloaded()
99 {
100     ACE_SCOPED_TRACE("OnDataReloaded");
101     children_.clear();
102     if (builder_) {
103         builder_->OnDataReloaded();
104     }
105     NotifyDataCountChanged(0);
106     MarkNeedSyncRenderTree(true);
107     MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
108 }
109 
OnDataAdded(size_t index)110 void LazyForEachNode::OnDataAdded(size_t index)
111 {
112     ACE_SCOPED_TRACE("OnDataAdded");
113     auto insertIndex = static_cast<int32_t>(index);
114     if (builder_) {
115         builder_->OnDataAdded(index);
116     }
117     children_.clear();
118     NotifyDataCountChanged(insertIndex);
119     MarkNeedSyncRenderTree(true);
120     MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
121 }
122 
OnDataDeleted(size_t index)123 void LazyForEachNode::OnDataDeleted(size_t index)
124 {
125     ACE_SCOPED_TRACE("OnDataDeleted");
126     auto deletedIndex = static_cast<int32_t>(index);
127     if (builder_) {
128         auto node = builder_->OnDataDeleted(index);
129 
130         if (node) {
131             if (!node->OnRemoveFromParent(true)) {
132                 const_cast<LazyForEachNode*>(this)->AddDisappearingChild(node);
133             } else {
134                 node->DetachFromMainTree();
135             }
136         }
137     }
138     children_.clear();
139     NotifyDataCountChanged(deletedIndex);
140     MarkNeedSyncRenderTree(true);
141     MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
142 }
143 
OnDataChanged(size_t index)144 void LazyForEachNode::OnDataChanged(size_t index)
145 {
146     if (builder_) {
147         builder_->OnDataChanged(index);
148     }
149     children_.clear();
150     MarkNeedSyncRenderTree(true);
151     MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
152 }
153 
OnDataMoved(size_t from,size_t to)154 void LazyForEachNode::OnDataMoved(size_t from, size_t to)
155 {
156     // TODO: data move
157 }
158 
NotifyDataCountChanged(int32_t index)159 void LazyForEachNode::NotifyDataCountChanged(int32_t index)
160 {
161     auto parent = GetParent();
162     if (parent) {
163         parent->ChildrenUpdatedFrom(index);
164     }
165 }
166 
MarkNeedSyncRenderTree(bool needRebuild)167 void LazyForEachNode::MarkNeedSyncRenderTree(bool needRebuild)
168 {
169     if (needMarkParent_) {
170         UINode::MarkNeedSyncRenderTree(needRebuild);
171     }
172 }
173 
GetFrameChildByIndex(uint32_t index,bool needBuild)174 RefPtr<UINode> LazyForEachNode::GetFrameChildByIndex(uint32_t index, bool needBuild)
175 {
176     if (index < static_cast<uint32_t>(FrameCount())) {
177         auto child = builder_->GetChildByIndex(index, needBuild);
178         if (child.second) {
179             child.second->SetJSViewActive(true);
180             if (child.second->GetDepth() != GetDepth() + 1) {
181                 child.second->SetDepth(GetDepth() + 1);
182             }
183             MarkNeedSyncRenderTree();
184             children_.clear();
185             child.second->SetParent(WeakClaim(this));
186             if (IsOnMainTree()) {
187                 child.second->AttachToMainTree();
188             }
189             PostIdleTask();
190             return child.second->GetFrameChildByIndex(0, needBuild);
191         }
192     }
193     return nullptr;
194 }
195 
GetIndexByUINode(const RefPtr<UINode> & uiNode) const196 int32_t LazyForEachNode::GetIndexByUINode(const RefPtr<UINode>& uiNode) const
197 {
198     if (!builder_) {
199         return -1;
200     }
201     auto items = builder_->GetAllChildren();
202     for (auto& [index, item] : items) {
203         if (item.second == uiNode) {
204             return index;
205         }
206     }
207     return -1;
208 }
209 
DoRemoveChildInRenderTree(uint32_t index,bool isAll)210 void LazyForEachNode::DoRemoveChildInRenderTree(uint32_t index, bool isAll)
211 {
212     if (!builder_) {
213         return;
214     }
215     children_.clear();
216     if (isAll) {
217         builder_->RemoveAllChild();
218         MarkNeedSyncRenderTree();
219         PostIdleTask();
220     }
221     return;
222 }
223 
GetChildren() const224 const std::list<RefPtr<UINode>>& LazyForEachNode::GetChildren() const
225 {
226     if (children_.empty()) {
227         std::list<RefPtr<UINode>> childList;
228         auto items = builder_->GetItems(childList);
229 
230         for (auto& node : childList) {
231             if (!node->OnRemoveFromParent(true)) {
232                 const_cast<LazyForEachNode*>(this)->AddDisappearingChild(node);
233             } else {
234                 node->DetachFromMainTree();
235             }
236         }
237         for (auto& [index, item] : items) {
238             if (item.second) {
239                 children_.push_back(item.second);
240             }
241         }
242     }
243     return children_;
244 }
245 
246 } // namespace OHOS::Ace::NG