1 /*
2  * Copyright (c) 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 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_LAYOUTS_LAYOUT_WRAPPER_NODE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_LAYOUTS_LAYOUT_WRAPPER_NODE_H
18 
19 #include <map>
20 #include <optional>
21 #include <string>
22 #include <unordered_map>
23 
24 #include "base/geometry/offset.h"
25 #include "base/memory/ace_type.h"
26 #include "base/memory/referenced.h"
27 #include "base/thread/cancelable_callback.h"
28 #include "base/utils/macros.h"
29 #include "base/utils/noncopyable.h"
30 #include "core/components_ng/base/geometry_node.h"
31 #include "core/components_ng/layout/box_layout_algorithm.h"
32 #include "core/components_ng/layout/layout_algorithm.h"
33 #include "core/components_ng/layout/layout_property.h"
34 #include "core/components_ng/layout/layout_wrapper.h"
35 #include "core/components_ng/layout/layout_wrapper_builder.h"
36 #include "core/components_ng/property/geometry_property.h"
37 #include "core/components_ng/property/layout_constraint.h"
38 #include "core/components_ng/property/magic_layout_property.h"
39 #include "core/components_ng/property/measure_property.h"
40 #include "core/components_ng/property/position_property.h"
41 #include "core/components_ng/property/property.h"
42 #include "core/components_v2/inspector/inspector_constants.h"
43 
44 namespace OHOS::Ace::NG {
45 class FrameNode;
46 class LayoutWrapperNode;
47 
48 using LazyBuildFunction = std::function<void(RefPtr<LayoutWrapperNode>)>;
49 
50 class ACE_EXPORT LayoutWrapperNode : public LayoutWrapper {
51     DECLARE_ACE_TYPE(LayoutWrapperNode, LayoutWrapper)
52 public:
53     LayoutWrapperNode(
54         WeakPtr<FrameNode> hostNode, RefPtr<GeometryNode> geometryNode, RefPtr<LayoutProperty> layoutProperty);
55 
LayoutWrapperNode(LazyBuildFunction && fun)56     LayoutWrapperNode(LazyBuildFunction&& fun)
57         : LayoutWrapper(nullptr), geometryNode_(MakeRefPtr<GeometryNode>()),
58           layoutProperty_(MakeRefPtr<LayoutProperty>()), lazyBuildFunction_(fun)
59     {}
60     ~LayoutWrapperNode() override = default;
61 
62     void Update(WeakPtr<FrameNode> hostNode, RefPtr<GeometryNode> geometryNode, RefPtr<LayoutProperty> layoutProperty);
63 
64     void AppendChild(const RefPtr<LayoutWrapperNode>& child, bool isOverlayNode = false);
65 
SetLayoutWrapperBuilder(const RefPtr<LayoutWrapperBuilder> & builder)66     void SetLayoutWrapperBuilder(const RefPtr<LayoutWrapperBuilder>& builder)
67     {
68         CHECK_NULL_VOID(builder);
69         builder->SetStartIndex(currentChildCount_);
70         currentChildCount_ += builder->GetTotalCount();
71         layoutWrapperBuilder_ = builder;
72     }
73 
SetLayoutAlgorithm(const RefPtr<LayoutAlgorithmWrapper> & layoutAlgorithm)74     void SetLayoutAlgorithm(const RefPtr<LayoutAlgorithmWrapper>& layoutAlgorithm)
75     {
76         layoutAlgorithm_ = layoutAlgorithm;
77     }
78 
79     const RefPtr<LayoutAlgorithmWrapper>& GetLayoutAlgorithm(bool needReset = false) override
80     {
81         return layoutAlgorithm_;
82     }
83 
84     // This will call child and self measure process.
85     void Measure(const std::optional<LayoutConstraintF>& parentConstraint) override;
86 
87     // Called to perform layout children.
88     void Layout() override;
89 
GetGeometryNode()90     const RefPtr<GeometryNode>& GetGeometryNode() const override
91     {
92         return geometryNode_;
93     }
94 
GetLayoutProperty()95     const RefPtr<LayoutProperty>& GetLayoutProperty() const override
96     {
97         return layoutProperty_;
98     }
99 
100     // Calling these two method will mark the node as in use by default, nodes marked as use state will be added to the
101     // render area, and nodes in the render area will be mounted on the render tree after the layout is complete. You
102     // can call the RemoveChildInRenderTree method to explicitly remove the node from the area to be rendered.
103     RefPtr<LayoutWrapper> GetOrCreateChildByIndex(
104         uint32_t index, bool addToRenderTree = true, bool isCache = false) override;
105     ChildrenListWithGuard GetAllChildrenWithBuild(bool addToRenderTree = true) override;
106     RefPtr<LayoutWrapper> GetChildByIndex(uint32_t index, bool isCache = false) override
107     {
108         return nullptr;
109     }
110 
GetTotalChildCount()111     int32_t GetTotalChildCount() const override
112     {
113         return currentChildCount_;
114     }
115 
116     std::list<RefPtr<FrameNode>> GetChildrenInRenderArea() const;
117 
118     void RemoveChildInRenderTree(uint32_t index) override;
119     void RemoveAllChildInRenderTree() override;
120     void SetActiveChildRange(
121         int32_t start, int32_t end, int32_t cacheStart = 0, int32_t cacheEnd = 0, bool showCached = false) override
122     {}
RecycleItemsByIndex(int32_t start,int32_t end)123     void RecycleItemsByIndex(int32_t start, int32_t end) override {}
124 
125     void ResetHostNode();
126 
127     const std::string& GetHostTag() const override;
128     int32_t GetHostDepth() const;
129 
IsActive()130     bool IsActive() const override
131     {
132         return isActive_;
133     }
134 
135     void SetActive(bool active = true, bool needRebuildRenderContext = false) override
136     {
137         isActive_ = active;
138     }
139 
IsRootMeasureNode()140     bool IsRootMeasureNode() const
141     {
142         return isRootNode_;
143     }
144 
SetRootMeasureNode()145     void SetRootMeasureNode()
146     {
147         isRootNode_ = true;
148     }
149 
CheckShouldRunOnMain()150     bool CheckShouldRunOnMain() override
151     {
152         return (CanRunOnWhichThread() & MAIN_TASK) == MAIN_TASK;
153     }
154 
CanRunOnWhichThread()155     TaskThread CanRunOnWhichThread()
156     {
157         if (layoutWrapperBuilder_) {
158             return MAIN_TASK;
159         }
160         TaskThread taskThread = UNDEFINED_TASK;
161         if (layoutAlgorithm_) {
162             taskThread = taskThread | layoutAlgorithm_->CanRunOnWhichThread();
163         }
164         if ((taskThread & MAIN_TASK) == MAIN_TASK) {
165             return MAIN_TASK;
166         }
167         for (const auto& child : children_) {
168             taskThread = taskThread | child->CanRunOnWhichThread();
169         }
170         return taskThread;
171     }
172 
173     bool SkipMeasureContent() const override;
174 
IsConstraintNoChanged()175     bool IsConstraintNoChanged() const
176     {
177         return isConstraintNotChanged_;
178     }
179 
180     // dirty layoutBox mount to host and switch layoutBox.
181     // Notice: only the cached layoutWrapper (after call GetChildLayoutWrapper) will update the host.
182     void MountToHostOnMainThread();
183     void SwapDirtyLayoutWrapperOnMainThread();
184     void SwapDirtyLayoutWrapperOnMainThreadForChild(RefPtr<LayoutWrapperNode> child);
185 
IsForceSyncRenderTree()186     bool IsForceSyncRenderTree() const
187     {
188         return needForceSyncRenderTree_;
189     }
190 
GetBaselineDistance()191     float GetBaselineDistance() const override
192     {
193         if (children_.empty()) {
194             return geometryNode_->GetBaselineDistance();
195         }
196         float distance = 0.0;
197         for (const auto& child : children_) {
198             float childBaseline = child->GetBaselineDistance();
199             distance = NearZero(distance) ? childBaseline : std::min(distance, childBaseline);
200         }
201         return distance;
202     }
203 
IsOutOfLayout()204     bool IsOutOfLayout() const override
205     {
206         return outOfLayout_;
207     }
208 
SetOutOfLayout(bool outOfLayout)209     void SetOutOfLayout(bool outOfLayout)
210     {
211         outOfLayout_ = outOfLayout;
212     }
213 
214     // Check the flag attribute with descendant node
215     bool CheckNeedForceMeasureAndLayout() override;
216 
217     bool CheckChildNeedForceMeasureAndLayout();
218 
219     void SetCacheCount(
220         int32_t cacheCount = 0, const std::optional<LayoutConstraintF>& itemConstraint = std::nullopt) override;
221 
222     void BuildLazyItem() override;
223 
224     std::pair<int32_t, int32_t> GetLazyBuildRange();
225     void SetLongPredictTask() override;
226 
227 private:
228     void Build(bool addToRenderTree);
229     void LayoutOverlay();
230     // Used to save a persist wrapper created by child, ifElse, ForEach, the map stores [index, Wrapper].
231     std::list<RefPtr<LayoutWrapperNode>> children_;
232     // Speed up the speed of getting child by index.
233     std::unordered_map<int32_t, RefPtr<LayoutWrapperNode>> childrenMap_;
234     RefPtr<LayoutWrapperNode> overlayChild_;
235     // cached for GetAllChildrenWithBuild function.
236     std::list<RefPtr<LayoutWrapper>> cachedList_;
237 
238     // The Wrapper Created by LazyForEach stores in the LayoutWrapperBuilder object.
239     RefPtr<LayoutWrapperBuilder> layoutWrapperBuilder_;
240 
241     RefPtr<GeometryNode> geometryNode_;
242     RefPtr<LayoutProperty> layoutProperty_;
243     RefPtr<LayoutAlgorithmWrapper> layoutAlgorithm_;
244 
245     int32_t currentChildCount_ = 0;
246     bool isActive_ = false;
247     bool needForceSyncRenderTree_ = false;
248     bool isRootNode_ = false;
249     std::optional<bool> skipMeasureContent_;
250     std::optional<bool> needForceMeasureAndLayout_;
251 
252     LazyBuildFunction lazyBuildFunction_;
253 
254     // When the location property is set, it departs from the layout flow.
255     bool outOfLayout_ = false;
256 
257     ACE_DISALLOW_COPY_AND_MOVE(LayoutWrapperNode);
258 };
259 } // namespace OHOS::Ace::NG
260 
261 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_LAYOUTS_LAYOUT_WRAPPER_NODE_H
262