• 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_LAYOUTS_LAYOUT_WRAPPER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_LAYOUTS_LAYOUT_WRAPPER_H
18 
19 #include <cstdint>
20 #include <map>
21 #include <optional>
22 #include <set>
23 #include <string>
24 #include <unordered_map>
25 
26 #include "base/memory/referenced.h"
27 #include "base/utils/macros.h"
28 #include "base/utils/noncopyable.h"
29 #include "core/components_ng/base/geometry_node.h"
30 #include "core/components_ng/layout/layout_algorithm.h"
31 #include "core/components_ng/layout/layout_wrapper_builder.h"
32 #include "core/components_ng/property/constraint_flags.h"
33 #include "core/components_ng/property/layout_constraint.h"
34 #include "ui/properties/safe_area_insets.h"
35 
36 namespace OHOS::Ace::NG {
37 class FrameNode;
38 class UINode;
39 class LayoutProperty;
40 struct SafeAreaInsets;
41 struct SafeAreaExpandOpts;
42 
43 class RecursiveLock {
44 public:
Lock()45     virtual void Lock() {}
Unlock()46     virtual void Unlock() {}
47 };
48 
49 class RecursionGuard final {
50 public:
RecursionGuard(RecursiveLock & lock)51     RecursionGuard(RecursiveLock& lock) : lock_(lock)
52     {
53         lock_.Lock();
54     }
~RecursionGuard()55     ~RecursionGuard()
56     {
57         lock_.Unlock();
58     }
RecursionGuard(const RecursionGuard & rhs)59     RecursionGuard(const RecursionGuard& rhs) : lock_(rhs.lock_)
60     {
61         lock_.Lock();
62     }
63 
64 private:
65     RecursiveLock& lock_;
66 };
67 
68 class ChildrenListWithGuard final {
69 public:
ChildrenListWithGuard(const std::list<RefPtr<LayoutWrapper>> & children,RecursiveLock & lock)70     ChildrenListWithGuard(const std::list<RefPtr<LayoutWrapper>>& children, RecursiveLock& lock)
71         : children_(children), guard_(lock)
72     {}
begin()73     auto begin() const
74     {
75         return children_.begin();
76     }
end()77     auto end() const
78     {
79         return children_.end();
80     }
rbegin()81     auto rbegin() const
82     {
83         return children_.rbegin();
84     }
rend()85     auto rend() const
86     {
87         return children_.rend();
88     }
empty()89     auto empty() const
90     {
91         return children_.empty();
92     }
size()93     auto size() const
94     {
95         return children_.size();
96     }
front()97     auto& front() const
98     {
99         return children_.front();
100     }
back()101     auto& back() const
102     {
103         return children_.back();
104     }
105     operator std::list<RefPtr<LayoutWrapper>>() const
106     {
107         return children_;
108     }
109 
110 private:
111     const std::list<RefPtr<LayoutWrapper>>& children_;
112     RecursionGuard guard_;
113 };
114 
115 struct ActiveChildRange {
116     int32_t start = -1;
117     int32_t end = -1;
118     int32_t cacheStart = 0;
119     int32_t cacheEnd = 0;
120 };
121 
122 struct ActiveChildSets {
123     std::set<int32_t> activeItems;
124     std::set<int32_t> cachedItems;
125 };
126 
127 enum class IgnoreStrategy {
128     NORMAL = 0,
129     FROM_MARGIN,
130     STRIDE_OVER,
131     AXIS_INSENSITIVE
132 };
133 class ACE_FORCE_EXPORT LayoutWrapper : public virtual AceType {
134     DECLARE_ACE_TYPE(LayoutWrapper, AceType);
135 public:
LayoutWrapper(WeakPtr<FrameNode> hostNode)136     LayoutWrapper(WeakPtr<FrameNode> hostNode) : hostNode_(std::move(hostNode)) {}
137     ~LayoutWrapper() override = default;
138 
139     virtual const RefPtr<LayoutAlgorithmWrapper>& GetLayoutAlgorithm(bool needReset = false) = 0;
140     // This will call child and self measure process.
141     virtual void Measure(const std::optional<LayoutConstraintF>& parentConstraint) = 0;
142 
143     // Called to perform layout children.
144     virtual void Layout() = 0;
145 
146     virtual int32_t GetTotalChildCount() const = 0;
147     virtual const RefPtr<GeometryNode>& GetGeometryNode() const = 0;
148     virtual const RefPtr<LayoutProperty>& GetLayoutProperty() const = 0;
149 
150     virtual RefPtr<LayoutWrapper> GetOrCreateChildByIndex(
151         uint32_t index, bool addToRenderTree = true, bool isCache = false) = 0;
152     /**
153      * @param isCache if false, child is added to render tree and AttachToMainTree is called.
154      */
155     virtual RefPtr<LayoutWrapper> GetChildByIndex(uint32_t index, bool isCache = false) = 0;
156     virtual ChildrenListWithGuard GetAllChildrenWithBuild(bool addToRenderTree = true) = 0;
157     virtual void RemoveChildInRenderTree(uint32_t index) = 0;
158     virtual void RemoveAllChildInRenderTree() = 0;
159     /**
160      * @param cacheStart number of items to cache before @c start
161      * @param cacheEnd number of items to cache after @c end
162      * @param showCached whether to set cached items as active
163      * @note To deactivate all children, set @c start and @c end to -1
164      */
165     virtual void SetActiveChildRange(
166         int32_t start, int32_t end, int32_t cacheStart = 0, int32_t cacheEnd = 0, bool showCached = false) = 0;
167     virtual void SetActiveChildRange(const std::optional<ActiveChildSets>& activeChildSets,
168         const std::optional<ActiveChildRange>& activeChildRange = std::nullopt)
169     {}
170     virtual void RecycleItemsByIndex(int32_t start, int32_t end) = 0;
171 
SetActiveChildRange(const std::set<int32_t> & activeIndexes,const std::set<int32_t> & cachedIndexes)172     virtual void SetActiveChildRange(const std::set<int32_t>& activeIndexes, const std::set<int32_t>& cachedIndexes) {}
RecycleItemsByIndex(const std::set<int32_t> & indexes)173     virtual void RecycleItemsByIndex(const std::set<int32_t>& indexes) {}
174 
175     RefPtr<FrameNode> GetHostNode() const;
176     virtual const std::string& GetHostTag() const = 0;
177     virtual bool IsActive() const = 0;
178     virtual void SetActive(bool active = true, bool needRebuildRenderContext = false) = 0;
179 
IsRootMeasureNode()180     bool IsRootMeasureNode() const
181     {
182         return isRootNode_;
183     }
184 
185     void SetRootMeasureNode(bool isRoot = true)
186     {
187         isRootNode_ = isRoot;
188     }
189 
IsOutOfLayout()190     virtual bool IsOutOfLayout() const
191     {
192         return false;
193     }
194 
195     virtual OffsetF GetParentGlobalOffsetWithSafeArea(bool checkBoundary = false, bool checkPosition = false) const;
196 
197     virtual bool SkipMeasureContent() const;
198 
199     virtual void SetCacheCount(
200         int32_t cacheCount = 0, const std::optional<LayoutConstraintF>& itemConstraint = std::nullopt) = 0;
201     virtual float GetBaselineDistance() const = 0;
CheckShouldRunOnMain()202     virtual bool CheckShouldRunOnMain()
203     {
204         return true;
205     }
206 
207     virtual bool CheckNeedForceMeasureAndLayout() = 0;
208 
ReachResponseDeadline()209     virtual bool ReachResponseDeadline() const
210     {
211         return false;
212     }
213 
SetIsOverlayNode(bool isOverlayNode)214     void SetIsOverlayNode(bool isOverlayNode)
215     {
216         isOverlayNode_ = isOverlayNode;
217     }
218 
219     // ------------------------------------------------------------------------
220     // performance check
221     void AddNodeFlexLayouts();
222     void AddNodeLayoutTime(int64_t time);
223     // ------------------------------------------------------------------------
224 
BuildLazyItem()225     virtual void BuildLazyItem() {}
226 
ConstraintChanged()227     bool ConstraintChanged() const
228     {
229         return !isConstraintNotChanged_;
230     }
GetConstraintChanges()231     const ConstraintFlags& GetConstraintChanges() const
232     {
233         return constraintChanges_;
234     }
GetContentChanges()235     const ConstraintFlags& GetContentChanges() const
236     {
237         return contentConstraintChanges_;
238     }
239 
SetLongPredictTask()240     virtual void SetLongPredictTask() {}
241 
242     static void ApplySafeArea(const SafeAreaInsets& insets, LayoutConstraintF& constraint);
243 
244     // apply keyboard avoidance on content rootNodes
245     bool AvoidKeyboard(bool isFocusOnPage = true);
246     // expand the SafeArea of expansive nodes, which are previously recorded during Layout traversal
247     void ExpandSafeArea();
248     void AdjustNotExpandNode();
249     void AdjustFixedSizeNode(RectF& frame);
250     void ExpandHelper(const std::unique_ptr<SafeAreaExpandOpts>& opts, RectF& frame);
251     ExpandEdges GetAccumulatedSafeAreaExpand(bool includingSelf = false,
252         IgnoreLayoutSafeAreaOpts options = { .type = NG::LAYOUT_SAFE_AREA_TYPE_SYSTEM,
253             .edges = NG::LAYOUT_SAFE_AREA_EDGE_ALL },
254         IgnoreStrategy strategy = IgnoreStrategy::NORMAL);
255     void ResetSafeAreaPadding();
256 
SkipSyncGeometryNode()257     bool SkipSyncGeometryNode() const
258     {
259         return needSkipSyncGeometryNode_;
260     }
261 
262     void SetSkipSyncGeometryNode(bool needSkip = true)
263     {
264         needSkipSyncGeometryNode_ = needSkip;
265     }
266 
267     RectF GetFrameRectWithoutSafeArea() const;
268     RectF GetFrameRectWithSafeArea(bool checkPosition = false) const;
269     void AddChildToExpandListIfNeeded(const WeakPtr<FrameNode>& node);
270     void ApplyConstraintWithoutMeasure(const std::optional<LayoutConstraintF>& constraint);
271     RectF GetBackGroundAccumulatedSafeAreaExpand();
272 
GetIgnoreLayoutProcess()273     bool GetIgnoreLayoutProcess()
274     {
275         return ignoreLayoutProcess_;
276     }
277 
278     // Paired with GetHasPreMeasured. Once a node being collected as a measure-delayed child, set true.
SetHasPreMeasured()279     void SetHasPreMeasured()
280     {
281         hasPreMeasured_ = true;
282     }
283 
284     // Paired with SetHasPreMeasured. To avoid re-entering PreMeasure in the delayed measure process.
GetHasPreMeasured()285     bool GetHasPreMeasured()
286     {
287         return std::exchange(hasPreMeasured_, false);
288     }
289 
CheckHasPreMeasured()290     bool CheckHasPreMeasured() const
291     {
292         return hasPreMeasured_;
293     }
294 
SetEscapeDelayForIgnore(bool noDelay)295     void SetEscapeDelayForIgnore(bool noDelay)
296     {
297         escapeDelayForIgnore_ = noDelay;
298     }
299 
GetEscapeDelayForIgnore()300     bool GetEscapeDelayForIgnore() const
301     {
302         return escapeDelayForIgnore_;
303     }
304 
305     bool PredictMeasureResult(LayoutWrapper* childWrapper, const std::optional<LayoutConstraintF>& parentConstraint);
306 
307     // Paired with GetDelaySelfLayoutForIgnore. Once a node being collected as a layout-delayed child, set true.
SetDelaySelfLayoutForIgnore()308     void SetDelaySelfLayoutForIgnore()
309     {
310         delaySelfLayoutForIgnore_ = true;
311     }
312 
313     // Paired with SetDelaySelfLayoutForIgnore. Access to skip THE JUST first layout after SetDelaySelfLayoutForIgnore,
314     // and valid layout should be called during PostponedTaskForIgnore.
GetDelaySelfLayoutForIgnore()315     bool GetDelaySelfLayoutForIgnore()
316     {
317         return std::exchange(delaySelfLayoutForIgnore_, false);
318     }
319 
320     bool IsIgnoreOptsValid();
321 
IsScrollableAxisInsensitive()322     bool IsScrollableAxisInsensitive()
323     {
324         return isScrollableAxis_;
325     }
326 
327 protected:
328     void CreateRootConstraint();
329     void ApplyConstraint(LayoutConstraintF constraint);
330 
331     void OffsetNodeToSafeArea();
332     // keyboard avoidance is done by offsetting, to expand into keyboard area, reverse the offset.
333     OffsetF ExpandIntoKeyboard();
334     bool CheckValidSafeArea();
335     float GetPageCurrentOffset();
336 
SetIgnoreLayoutProcess(bool switchTo)337     void SetIgnoreLayoutProcess(bool switchTo)
338     {
339         ignoreLayoutProcess_ = switchTo;
340     }
341 
ResetIgnoreLayoutProcess()342     void ResetIgnoreLayoutProcess()
343     {
344         ignoreLayoutProcess_ = false;
345     }
346 
347     enum class StartPoint {
348         NORMAL = 0,
349         INCLUDING_SELF,
350         FROM_MARGIN
351     };
352     bool AccumulateExpandCacheHit(ExpandEdges& totalExpand, const PaddingPropertyF& innerSpace);
353     ExpandEdges GetAccumulatedSafeAreaExpandForAllEdges(
354         StartPoint startPoint = StartPoint::NORMAL, LayoutSafeAreaType ignoreType = NG::LAYOUT_SAFE_AREA_TYPE_SYSTEM);
355     void GetAccumulatedSafeAreaExpandHelper(RectF& adjustingRect, ExpandEdges& totalExpand, bool fromSelf = false,
356         LayoutSafeAreaType ignoreType = NG::LAYOUT_SAFE_AREA_TYPE_SYSTEM);
357     void ParseSafeAreaPaddingSides(const PaddingPropertyF& parentSafeAreaPadding,
358         const PaddingPropertyF& parentInnerSpace, const RectF& adjustingRect, ExpandEdges& rollingExpand);
359     WeakPtr<FrameNode> hostNode_;
360 
361     ConstraintFlags constraintChanges_;
362     ConstraintFlags contentConstraintChanges_;
363 
364     bool isConstraintNotChanged_ = false;
365     bool isRootNode_ = false;
366     bool isOverlayNode_ = false;
367     bool needSkipSyncGeometryNode_ = false;
368     std::optional<bool> skipMeasureContent_;
369     std::optional<bool> needForceMeasureAndLayout_;
370     bool ignoreLayoutProcess_ = false;
371     bool hasPreMeasured_ = false;
372     bool delaySelfLayoutForIgnore_ = false;
373     bool escapeDelayForIgnore_ = false;
374     bool isScrollableAxis_ = false;
375 private:
376     void AdjustChildren(const OffsetF& offset, bool parentScrollable);
377     void AdjustChild(RefPtr<UINode> node, const OffsetF& offset, bool parentScrollable);
378 
379     ACE_DISALLOW_COPY_AND_MOVE(LayoutWrapper);
380 };
381 } // namespace OHOS::Ace::NG
382 
383 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_LAYOUTS_LAYOUT_WRAPPER_H
384