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() override; 47 48 void OnDelete() override; 49 IsAtomicNode()50 bool IsAtomicNode() const override 51 { 52 return false; 53 } 54 FrameCount()55 int32_t FrameCount() const override 56 { 57 return builder_ ? builder_->GetTotalCount() : 0; 58 } 59 60 void NotifyColorModeChange(uint32_t colorMode) override; 61 62 void AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout) override; 63 64 void UpdateLazyForEachItems(int32_t newStartIndex, int32_t newEndIndex, 65 std::list<std::optional<std::string>>&& nodeIds, 66 std::unordered_map<int32_t, std::optional<std::string>>&& cachedItems); 67 68 void OnDataReloaded() override; 69 void OnDataAdded(size_t index) override; 70 void OnDataBulkAdded(size_t index, size_t count) override; 71 void OnDataDeleted(size_t index) override; 72 void OnDataBulkDeleted(size_t index, size_t count) override; 73 void OnDataChanged(size_t index) override; 74 void OnDataMoved(size_t from, size_t to) override; 75 void OnDatasetChange(const std::list<V2::Operation>& DataOperations) override; 76 77 void OnDataBulkChanged(size_t index, size_t count) override; 78 void OnDataMoveToNewPlace(size_t from, size_t to) override; 79 80 void PostIdleTask(std::list<int32_t>&& items, const std::optional<LayoutConstraintF>& itemConstraint = std::nullopt, 81 bool longPredictTask = false); 82 SetRequestLongPredict(bool requestLongPredict)83 void SetRequestLongPredict(bool requestLongPredict) 84 { 85 requestLongPredict_ = requestLongPredict; 86 } 87 SetFlagForGeneratedItem(PropertyChangeFlag propertyChangeFlag)88 void SetFlagForGeneratedItem(PropertyChangeFlag propertyChangeFlag) 89 { 90 builder_->SetFlagForGeneratedItem(propertyChangeFlag); 91 } 92 SetIsLoop(bool isLoop)93 void SetIsLoop(bool isLoop) 94 { 95 isLoop_ = isLoop; 96 if (builder_) { 97 builder_->SetIsLoop(isLoop); 98 } 99 } 100 GetIsLoop()101 bool GetIsLoop() const 102 { 103 return isLoop_; 104 } 105 void PostIdleTask(); 106 void OnConfigurationUpdate(const ConfigurationChange& configurationChange) override; 107 void MarkNeedSyncRenderTree(bool needRebuild = false) override; 108 109 void BuildAllChildren(); 110 RefPtr<UINode> GetFrameChildByIndex(uint32_t index, bool needBuild, bool isCache = false, 111 bool addToRenderTree = false) override; 112 void DoRemoveChildInRenderTree(uint32_t index, bool isAll) override; 113 void DoSetActiveChildRange( 114 int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCache = false) override; 115 116 const std::list<RefPtr<UINode>>& GetChildren(bool notDetach = false) const override; 117 void LoadChildren(bool notDetach) const; 118 119 const std::list<RefPtr<UINode>>& GetChildrenForInspector(bool needCacheNode = false) const override; 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, bool isReuse = false) override 129 { 130 if (builder_) { 131 builder_->SetJSViewActive(active); 132 isActive_ = active; 133 } 134 } 135 void SetDestroying(bool isDestroying = true, bool cleanStatus = true) override 136 { 137 if (builder_) { 138 builder_->SetDestroying(isDestroying, cleanStatus); 139 } 140 } PaintDebugBoundaryTreeAll(bool flag)141 void PaintDebugBoundaryTreeAll(bool flag) override 142 { 143 if (builder_) { 144 builder_->PaintDebugBoundaryTreeAll(flag); 145 } 146 } 147 int32_t GetIndexByUINode(const RefPtr<UINode>& uiNode) const; SetNodeIndexOffset(int32_t start,int32_t count)148 void SetNodeIndexOffset(int32_t start, int32_t count) override 149 { 150 startIndex_ = start; 151 count_ = count; 152 } 153 void RecycleItems(int32_t from, int32_t to) override; 154 GetBuilder()155 const RefPtr<LazyForEachBuilder>& GetBuilder() const 156 { 157 return builder_; 158 } 159 RegisterBuilderListener()160 void RegisterBuilderListener() { 161 CHECK_NULL_VOID(builder_); 162 if (!isRegisterListener_) { 163 builder_->RegisterDataChangeListener(Claim(this)); 164 isRegisterListener_ = true; 165 } 166 } 167 168 void SetItemDragHandler(std::function<void(int32_t)>&& onLongPress, std::function<void(int32_t)>&& onDragStart, 169 std::function<void(int32_t, int32_t)>&& onMoveThrough, std::function<void(int32_t)>&& onDrop); 170 void SetOnMove(std::function<void(int32_t, int32_t)>&& onMove); 171 void MoveData(int32_t from, int32_t to) override; 172 void FireOnMove(int32_t from, int32_t to) override; 173 RefPtr<FrameNode> GetFrameNode(int32_t index) override; 174 int32_t GetFrameNodeIndex(const RefPtr<FrameNode>& node, bool isExpanded = true) override; 175 void InitDragManager(const RefPtr<FrameNode>& childNode); 176 void InitAllChilrenDragManager(bool init); 177 178 /** 179 * @brief Notify the change of dataSource to parent. 180 * 181 * @param index the position of change. 182 * @param count the count of change in [index]. 183 * @param notificationType the type of notification. 184 */ 185 void NotifyChangeWithCount(int32_t index, int32_t count, NotificationType notificationType) const; 186 187 /** 188 * @brief Parse OnDatasetChange for NotifyCountChange. 189 * 190 * @param dataOperations bulk change operations. 191 */ 192 void ParseOperations(const std::list<V2::Operation>& dataOperations); 193 194 void EnablePreBuild(bool enable); 195 protected: 196 void UpdateChildrenFreezeState(bool isFreeze, bool isForceUpdateFreezeVaule = false) override; 197 private: OnAttachToMainTree(bool recursive)198 void OnAttachToMainTree(bool recursive) override 199 { 200 UINode::OnAttachToMainTree(recursive); 201 RegisterBuilderListener(); 202 if (builder_) { 203 for (const auto& item : builder_->GetCachedUINodeMap()) { 204 if (item.second.second != nullptr) { 205 builder_->ProcessOffscreenNode(item.second.second, false); 206 } 207 } 208 } 209 } 210 211 void OnDetachFromMainTree(bool recursive, PipelineContext* context = nullptr) override 212 { 213 UINode::OnDetachFromMainTree(recursive, context); 214 if (builder_) { 215 auto tempExpiringItem = builder_->GetCachedUINodeMap(); 216 for (const auto& [key, child] : tempExpiringItem) { 217 if (child.second != nullptr) { 218 child.second->DetachFromMainTree(recursive); 219 builder_->ProcessOffscreenNode(child.second, true); 220 } 221 } 222 } 223 } 224 OnOffscreenProcess(bool recursive)225 void OnOffscreenProcess(bool recursive) override 226 { 227 UINode::OnOffscreenProcess(recursive); 228 RegisterBuilderListener(); 229 } 230 OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)231 void OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList) override 232 { 233 // LazyForEachNode::GetChildren() may add some children to disappearingChildren_, execute earlier to ensure 234 // disappearingChildren_ is correct before calling GenerateOneDepthVisibleFrameWithTransition. 235 GetChildren(); 236 UINode::GenerateOneDepthVisibleFrameWithTransition(visibleList); 237 } 238 239 // The index values of the start and end of the current children nodes and the corresponding keys. 240 std::list<std::optional<std::string>> ids_; 241 std::list<int32_t> predictItems_; 242 std::optional<LayoutConstraintF> itemConstraint_; 243 bool requestLongPredict_ = true; 244 bool isRegisterListener_ = false; 245 bool isLoop_ = false; 246 247 mutable std::list<RefPtr<UINode>> tempChildren_; 248 mutable std::list<RefPtr<UINode>> children_; 249 mutable bool needPredict_ = false; 250 mutable std::list<RefPtr<UINode>> childrenWithCache_; 251 bool needMarkParent_ = true; 252 bool isActive_ = true; 253 int32_t startIndex_ = 0; 254 int32_t count_ = 0; 255 256 RefPtr<LazyForEachBuilder> builder_; 257 258 ACE_DISALLOW_COPY_AND_MOVE(LazyForEachNode); 259 }; 260 261 } // namespace OHOS::Ace::NG 262 263 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_SYNTAX_LAZY_FOR_EACH_NODE_H