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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_SYNTAX_LAZY_FOR_EACH_NODE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_SYNTAX_LAZY_FOR_EACH_NODE_H
18 
19 #include <list>
20 #include <optional>
21 #include <string>
22 
23 #include "base/utils/utils.h"
24 #include "core/common/resource/resource_configuration.h"
25 #include "core/components_ng/base/frame_node.h"
26 #include "core/components_ng/base/ui_node.h"
27 #include "core/components_ng/syntax/for_each_base_node.h"
28 #include "core/components_ng/syntax/lazy_for_each_builder.h"
29 #include "core/components_v2/inspector/inspector_constants.h"
30 
31 namespace OHOS::Ace::NG {
32 
33 class ACE_EXPORT LazyForEachNode : public ForEachBaseNode, public V2::DataChangeListener {
34     DECLARE_ACE_TYPE(LazyForEachNode, ForEachBaseNode, DataChangeListener);
35 
36 public:
37     static RefPtr<LazyForEachNode> GetOrCreateLazyForEachNode(
38         int32_t nodeId, const RefPtr<LazyForEachBuilder>& forEachBuilder);
39 
40     static RefPtr<LazyForEachNode> CreateLazyForEachNode(
41         int32_t nodeId, const RefPtr<LazyForEachBuilder>& forEachBuilder);
42 
LazyForEachNode(int32_t nodeId,const RefPtr<LazyForEachBuilder> & forEachBuilder)43     LazyForEachNode(int32_t nodeId, const RefPtr<LazyForEachBuilder>& forEachBuilder)
44         : ForEachBaseNode(V2::JS_LAZY_FOR_EACH_ETS_TAG, nodeId, false), builder_(forEachBuilder)
45     {}
46 
~LazyForEachNode()47     ~LazyForEachNode() {
48         CHECK_NULL_VOID(builder_);
49         builder_->UnregisterDataChangeListener(this);
50         builder_->ClearAllOffscreenNode();
51         isRegisterListener_ = false;
52     }
53 
IsAtomicNode()54     bool IsAtomicNode() const override
55     {
56         return false;
57     }
58 
FrameCount()59     int32_t FrameCount() const override
60     {
61         return builder_ ? builder_->GetTotalCount() : 0;
62     }
63 
64     void AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout) override;
65 
66     void UpdateLazyForEachItems(int32_t newStartIndex, int32_t newEndIndex,
67         std::list<std::optional<std::string>>&& nodeIds,
68         std::unordered_map<int32_t, std::optional<std::string>>&& cachedItems);
69 
70     void OnDataReloaded() override;
71     void OnDataAdded(size_t index) override;
72     void OnDataBulkAdded(size_t index, size_t count) override;
73     void OnDataDeleted(size_t index) override;
74     void OnDataBulkDeleted(size_t index, size_t count) override;
75     void OnDataChanged(size_t index) override;
76     void OnDataMoved(size_t from, size_t to) override;
77     void OnDatasetChange(const std::list<V2::Operation>& DataOperations) override;
78 
79     void OnDataBulkChanged(size_t index, size_t count) override;
80     void OnDataMoveToNewPlace(size_t from, size_t to) override;
81 
82     void PostIdleTask(std::list<int32_t>&& items, const std::optional<LayoutConstraintF>& itemConstraint = std::nullopt,
83         bool longPredictTask = false);
84 
SetRequestLongPredict(bool requestLongPredict)85     void SetRequestLongPredict(bool requestLongPredict)
86     {
87         requestLongPredict_ = requestLongPredict;
88     }
89 
SetFlagForGeneratedItem(PropertyChangeFlag propertyChangeFlag)90     void SetFlagForGeneratedItem(PropertyChangeFlag propertyChangeFlag)
91     {
92         builder_->SetFlagForGeneratedItem(propertyChangeFlag);
93     }
94 
SetIsLoop(bool isLoop)95     void SetIsLoop(bool isLoop)
96     {
97         isLoop_ = isLoop;
98         if (builder_) {
99             builder_->SetIsLoop(isLoop);
100         }
101     }
102 
GetIsLoop()103     bool GetIsLoop() const
104     {
105         return isLoop_;
106     }
107     void PostIdleTask();
108     void OnConfigurationUpdate(const ConfigurationChange& configurationChange) override;
109     void MarkNeedSyncRenderTree(bool needRebuild = false) override;
110 
111     void BuildAllChildren();
112     RefPtr<UINode> GetFrameChildByIndex(uint32_t index, bool needBuild, bool isCache = false,
113         bool addToRenderTree = false) override;
114     void DoRemoveChildInRenderTree(uint32_t index, bool isAll) override;
115     void DoSetActiveChildRange(
116         int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCache = false) override;
117 
118     const std::list<RefPtr<UINode>>& GetChildren(bool notDetach = false) const override;
119     void LoadChildren(bool notDetach) const;
120 
OnSetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)121     void OnSetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint) override
122     {
123         itemConstraint_ = itemConstraint;
124         if (builder_) {
125             builder_->SetCacheCount(cacheCount);
126         }
127     }
128     void SetJSViewActive(bool active = true, bool isLazyForEachNode = false) override
129     {
130         if (builder_) {
131             builder_->SetJSViewActive(active);
132             isActive_ = active;
133         }
134     }
PaintDebugBoundaryTreeAll(bool flag)135     void PaintDebugBoundaryTreeAll(bool flag) override
136     {
137         if (builder_) {
138             builder_->PaintDebugBoundaryTreeAll(flag);
139         }
140     }
141     int32_t GetIndexByUINode(const RefPtr<UINode>& uiNode) const;
SetNodeIndexOffset(int32_t start,int32_t count)142     void SetNodeIndexOffset(int32_t start, int32_t count) override
143     {
144         startIndex_ = start;
145         count_ = count;
146     }
147     void RecycleItems(int32_t from, int32_t to) override;
148 
GetBuilder()149     const RefPtr<LazyForEachBuilder>& GetBuilder() const
150     {
151         return builder_;
152     }
153 
RegisterBuilderListener()154     void RegisterBuilderListener() {
155         CHECK_NULL_VOID(builder_);
156         if (!isRegisterListener_) {
157             builder_->RegisterDataChangeListener(Claim(this));
158             isRegisterListener_ = true;
159         }
160     }
161 
162     void SetOnMove(std::function<void(int32_t, int32_t)>&& onMove);
163     void MoveData(int32_t from, int32_t to) override;
164     void FireOnMove(int32_t from, int32_t to) override;
165     RefPtr<FrameNode> GetFrameNode(int32_t index) override;
166     int32_t GetFrameNodeIndex(const RefPtr<FrameNode>& node, bool isExpanded = true) override;
167     void InitDragManager(const RefPtr<FrameNode>& childNode);
168     void InitAllChilrenDragManager(bool init);
169 
170     /**
171      * @brief Notify the change of dataSource to parent.
172      *
173      * @param index the position of change.
174      * @param count the count of change in [index].
175      * @param notificationType the type of notification.
176      */
177     void NotifyChangeWithCount(int32_t index, int32_t count, NotificationType notificationType) const;
178 
179     /**
180      * @brief Parse OnDatasetChange for NotifyCountChange.
181      *
182      * @param dataOperations bulk change operations.
183      */
184     void ParseOperations(const std::list<V2::Operation>& dataOperations);
185 protected:
186     void UpdateChildrenFreezeState(bool isFreeze) override;
187 private:
OnAttachToMainTree(bool recursive)188     void OnAttachToMainTree(bool recursive) override
189     {
190         UINode::OnAttachToMainTree(recursive);
191         RegisterBuilderListener();
192         if (builder_) {
193             for (const auto& item : builder_->GetCachedUINodeMap()) {
194                 if (item.second.second != nullptr) {
195                     builder_->ProcessOffscreenNode(item.second.second, false);
196                 }
197             }
198         }
199     }
200 
201     void OnDetachFromMainTree(bool recursive, PipelineContext* context = nullptr) override
202     {
203         UINode::OnDetachFromMainTree(recursive, context);
204         if (builder_) {
205             auto tempExpiringItem = builder_->GetCachedUINodeMap();
206             for (const auto& [key, child] : tempExpiringItem) {
207                 if (child.second != nullptr) {
208                     child.second->DetachFromMainTree(recursive);
209                     builder_->ProcessOffscreenNode(child.second, true);
210                 }
211             }
212         }
213     }
214 
OnOffscreenProcess(bool recursive)215     void OnOffscreenProcess(bool recursive) override
216     {
217         UINode::OnOffscreenProcess(recursive);
218         RegisterBuilderListener();
219     }
220 
OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)221     void OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList) override
222     {
223         // LazyForEachNode::GetChildren() may add some children to disappearingChildren_, execute earlier to ensure
224         // disappearingChildren_ is correct before calling GenerateOneDepthVisibleFrameWithTransition.
225         GetChildren();
226         UINode::GenerateOneDepthVisibleFrameWithTransition(visibleList);
227     }
228 
229     // The index values of the start and end of the current children nodes and the corresponding keys.
230     std::list<std::optional<std::string>> ids_;
231     std::list<int32_t> predictItems_;
232     std::optional<LayoutConstraintF> itemConstraint_;
233     bool requestLongPredict_ = true;
234     bool isRegisterListener_ = false;
235     bool isLoop_ = false;
236 
237     mutable std::list<RefPtr<UINode>> tempChildren_;
238     mutable std::list<RefPtr<UINode>> children_;
239     mutable bool needPredict_ = false;
240     bool needMarkParent_ = true;
241     bool isActive_ = true;
242     int32_t startIndex_ = 0;
243     int32_t count_ = 0;
244 
245     RefPtr<LazyForEachBuilder> builder_;
246 
247     ACE_DISALLOW_COPY_AND_MOVE(LazyForEachNode);
248 };
249 
250 } // namespace OHOS::Ace::NG
251 
252 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_SYNTAX_LAZY_FOR_EACH_NODE_H