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