1 /* 2 * Copyright (c) 2022-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_PATTERNS_LIST_LIST_ITEM_GROUP_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_ITEM_GROUP_PATTERN_H 18 19 #include "base/memory/referenced.h" 20 #include "base/utils/noncopyable.h" 21 #include "base/utils/utils.h" 22 #include "core/components_ng/pattern/list/list_item_group_accessibility_property.h" 23 #include "core/components_ng/pattern/list/list_children_main_size.h" 24 #include "core/components_ng/pattern/list/list_item_group_layout_algorithm.h" 25 #include "core/components_ng/pattern/list/list_item_group_layout_property.h" 26 #include "core/components_ng/pattern/list/list_layout_property.h" 27 #include "core/components_ng/pattern/list/list_position_map.h" 28 #include "core/components_ng/pattern/pattern.h" 29 #include "core/components_ng/syntax/shallow_builder.h" 30 31 namespace OHOS::Ace::NG { 32 33 struct ListItemGroupPaintInfo { 34 TextDirection layoutDirection = TextDirection::LTR; 35 float mainSize = 0.0f; 36 bool vertical = false; 37 int32_t lanes = 1; 38 float spaceWidth = 0.0f; 39 float laneGutter = 0.0f; 40 int32_t totalItemCount = 0; 41 float listContentSize = FLT_MAX; 42 }; 43 44 enum ListItemGroupArea { 45 NONE_AREA, 46 IN_LIST_ITEM_AREA, 47 IN_HEADER_AREA, 48 IN_FOOTER_AREA 49 }; 50 51 struct VisibleContentInfo { 52 int32_t area = -1; 53 int32_t indexInGroup = -1; 54 }; 55 56 struct ListMainSizeValues { 57 float startPos = 0.0f; 58 float endPos = 0.0f; 59 std::optional<int32_t> jumpIndexInGroup; 60 float prevContentMainSize = 0.0f; 61 ScrollAlign scrollAlign = ScrollAlign::START; 62 std::optional<float> layoutStartMainPos; 63 std::optional<float> layoutEndMainPos; 64 float referencePos = 0.0f; 65 float contentStartOffset = 0.0f; 66 float contentEndOffset = 0.0f; 67 bool forward = true; 68 bool backward = false; 69 }; 70 71 class ACE_EXPORT ListItemGroupPattern : public Pattern { 72 DECLARE_ACE_TYPE(ListItemGroupPattern, Pattern); 73 74 public: ListItemGroupPattern(const RefPtr<ShallowBuilder> & shallowBuilder,V2::ListItemGroupStyle listItemGroupStyle)75 explicit ListItemGroupPattern( 76 const RefPtr<ShallowBuilder>& shallowBuilder, V2::ListItemGroupStyle listItemGroupStyle) 77 : shallowBuilder_(shallowBuilder), listItemGroupStyle_(listItemGroupStyle) 78 {} 79 ~ListItemGroupPattern() override = default; 80 81 void DumpAdvanceInfo() override; 82 void DumpAdvanceInfo(std::unique_ptr<JsonValue>& json) override; IsAtomicNode()83 bool IsAtomicNode() const override 84 { 85 return false; 86 } 87 GetFocusPattern()88 FocusPattern GetFocusPattern() const override 89 { 90 return { FocusType::SCOPE, true }; 91 } 92 93 ScopeFocusAlgorithm GetScopeFocusAlgorithm() override; 94 95 bool FindHeadOrTailChild(const RefPtr<FocusHub>& groupFocus, FocusStep step, WeakPtr<FocusHub>& target); 96 97 WeakPtr<FocusHub> GetChildFocusNodeByIndex(int32_t tarIndexInGroup); 98 99 WeakPtr<FocusHub> GetNextFocusNode(FocusStep step, const WeakPtr<FocusHub>& currentFocusNode); 100 101 void NotifyDataChange(int32_t index, int32_t count) override; 102 CreateLayoutProperty()103 RefPtr<LayoutProperty> CreateLayoutProperty() override 104 { 105 return MakeRefPtr<ListItemGroupLayoutProperty>(); 106 } 107 CreateAccessibilityProperty()108 RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override 109 { 110 return MakeRefPtr<ListItemGroupAccessibilityProperty>(); 111 } 112 113 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override; 114 115 RefPtr<NodePaintMethod> CreateNodePaintMethod() override; 116 OnAttachAdapter(const RefPtr<FrameNode> & node,const RefPtr<UINode> & child)117 bool OnAttachAdapter(const RefPtr<FrameNode>& node, const RefPtr<UINode>& child) override 118 { 119 node->AddChild(child); 120 return true; 121 } 122 AddHeader(const RefPtr<NG::UINode> & header)123 void AddHeader(const RefPtr<NG::UINode>& header) 124 { 125 auto host = GetHost(); 126 CHECK_NULL_VOID(host); 127 auto prevHeader = header_.Upgrade(); 128 if (!prevHeader) { 129 host->AddChild(header, 0); 130 // Initialize headerIndex_, itemStartIndex_ 131 if (headerIndex_ == -1) { 132 auto count = header->FrameCount(); 133 if (count > 0) { 134 headerIndex_ = 0; 135 itemStartIndex_ += count; 136 } 137 if (footerIndex_ >= 0) { 138 footerIndex_ = footerIndex_ + count; 139 } 140 } 141 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); 142 } else { 143 if (header != prevHeader) { 144 host->ReplaceChild(prevHeader, header); 145 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); 146 } 147 } 148 header_ = header; 149 } 150 AddFooter(const RefPtr<NG::UINode> & footer)151 void AddFooter(const RefPtr<NG::UINode>& footer) 152 { 153 auto host = GetHost(); 154 CHECK_NULL_VOID(host); 155 auto prevFooter = footer_.Upgrade(); 156 auto prevHeader = header_.Upgrade(); 157 if (!prevFooter) { 158 if (prevHeader) { 159 host->AddChildAfter(footer, prevHeader); 160 } else { 161 host->AddChild(footer, 0); 162 } 163 // Initialize itemStartIndex_, footerIndex_ 164 if (footerIndex_ == -1) { 165 int32_t count = footer->FrameCount(); 166 if (count > 0) { 167 footerIndex_ = itemStartIndex_; 168 itemStartIndex_ += count; 169 } 170 } 171 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); 172 } else { 173 if (footer != prevFooter) { 174 host->ReplaceChild(prevFooter, footer); 175 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); 176 } 177 } 178 footer_ = footer; 179 } 180 RemoveHeader()181 void RemoveHeader() 182 { 183 auto host = GetHost(); 184 CHECK_NULL_VOID(host); 185 auto prevHeader = header_.Upgrade(); 186 if (prevHeader && isHeaderComponentContentExist_) { 187 host->RemoveChild(prevHeader); 188 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); 189 header_ = nullptr; 190 headerIndex_ = -1; 191 itemStartIndex_ = 0; 192 isHeaderComponentContentExist_ = false; 193 } 194 } 195 RemoveFooter()196 void RemoveFooter() 197 { 198 auto host = GetHost(); 199 CHECK_NULL_VOID(host); 200 auto prevFooter = footer_.Upgrade(); 201 if (prevFooter && isFooterComponentContentExist_) { 202 host->RemoveChild(prevFooter); 203 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); 204 footer_ = nullptr; 205 footerIndex_ = -1; 206 footerCount_ = 0; 207 isFooterComponentContentExist_ = false; 208 } 209 } 210 IsHasHeader()211 bool IsHasHeader() 212 { 213 auto headerNode = DynamicCast<FrameNode>(header_.Upgrade()); 214 return headerNode ? true : false; 215 } 216 IsHasFooter()217 bool IsHasFooter() 218 { 219 auto footerGroup = DynamicCast<FrameNode>(footer_.Upgrade()); 220 return footerGroup ? true : false; 221 } 222 GetItemPosition()223 const ListItemGroupLayoutAlgorithm::PositionMap& GetItemPosition() 224 { 225 return itemPosition_; 226 } 227 SetIndexInList(int32_t index)228 void SetIndexInList(int32_t index) 229 { 230 indexInList_ = index; 231 } 232 SetHeaderComponentContentExist(bool isHeaderComponentContentExist)233 void SetHeaderComponentContentExist(bool isHeaderComponentContentExist) 234 { 235 isHeaderComponentContentExist_ = isHeaderComponentContentExist; 236 } 237 SetFooterComponentContentExist(bool isFooterComponentContentExist)238 void SetFooterComponentContentExist(bool isFooterComponentContentExist) 239 { 240 isFooterComponentContentExist_ = isFooterComponentContentExist; 241 } 242 GetIndexInList()243 int32_t GetIndexInList() const 244 { 245 return indexInList_; 246 } 247 GetDisplayEndIndexInGroup()248 int32_t GetDisplayEndIndexInGroup() const 249 { 250 return itemDisplayEndIndex_; 251 } 252 GetDisplayStartIndexInGroup()253 int32_t GetDisplayStartIndexInGroup() const 254 { 255 return itemDisplayStartIndex_; 256 } 257 GetItemStartIndex()258 int32_t GetItemStartIndex() const 259 { 260 return itemStartIndex_; 261 } 262 GetEndIndexInGroup()263 int32_t GetEndIndexInGroup() const 264 { 265 return (itemTotalCount_ - 1); 266 } 267 GetTotalItemCount()268 int32_t GetTotalItemCount() const 269 { 270 return itemTotalCount_; 271 } 272 IsDisplayStart()273 bool IsDisplayStart() const 274 { 275 return itemDisplayStartIndex_ == 0; 276 } 277 IsDisplayEnd()278 int32_t IsDisplayEnd() const 279 { 280 return itemTotalCount_ == 0 || itemDisplayEndIndex_ == (itemTotalCount_ - 1); 281 } 282 GetLanesInGroup()283 int32_t GetLanesInGroup() const 284 { 285 return lanes_; 286 } 287 SetLanes(int32_t num)288 void SetLanes(int32_t num) 289 { 290 lanes_ = num; 291 } 292 GetListItemGroupStyle()293 V2::ListItemGroupStyle GetListItemGroupStyle() 294 { 295 return listItemGroupStyle_; 296 } 297 GetHeaderMainSize()298 float GetHeaderMainSize() const 299 { 300 return headerMainSize_; 301 } 302 GetFooterMainSize()303 float GetFooterMainSize() const 304 { 305 return footerMainSize_; 306 } 307 308 float GetEstimateOffset(float height, const std::pair<float, float>& targetPos, 309 float headerMainSize, float footerMainSize) const; 310 float GetEstimateHeight(float& averageHeight, float headerMainSize, float footerMainSize, float spaceWidth) const; HasLayoutedItem()311 bool HasLayoutedItem() const 312 { 313 return layouted_ && (layoutedItemInfo_.has_value() || itemTotalCount_ == 0); 314 } 315 SetItemPressed(bool isPressed,int32_t id)316 void SetItemPressed(bool isPressed, int32_t id) 317 { 318 if (isPressed) { 319 pressedItem_.emplace(id); 320 } else { 321 pressedItem_.erase(id); 322 } 323 } 324 ResetLayoutedInfo()325 void ResetLayoutedInfo() 326 { 327 layouted_ = false; 328 layoutedItemInfo_.reset(); 329 itemPosition_.clear(); 330 } 331 332 void SetListItemGroupStyle(V2::ListItemGroupStyle style); 333 RefPtr<ListChildrenMainSize> GetOrCreateListChildrenMainSize(); 334 void SetListChildrenMainSize(float defaultSize, const std::vector<float>& mainSize); 335 void OnChildrenSizeChanged(std::tuple<int32_t, int32_t, int32_t> change, ListChangeFlag flag); 336 bool ListChildrenSizeExist(); 337 RefPtr<FrameNode> GetListFrameNode() const; 338 VisibleContentInfo GetStartListItemIndex(); 339 VisibleContentInfo GetEndListItemIndex(); 340 void ResetChildrenSize(); 341 bool IsInViewport(int32_t index) const; 342 343 void ClearItemPosition(); 344 void ClearCachedItemPosition(); 345 void CalculateItemStartIndex(); 346 bool NeedCacheForward(const LayoutWrapper* listWrapper) const; 347 CachedIndexInfo UpdateCachedIndex(bool outOfView, bool reCache, int32_t forwardCache, int32_t backwardCache); 348 int32_t UpdateCachedIndexForward(bool outOfView, bool show, int32_t cacheCount); 349 int32_t UpdateCachedIndexBackward(bool outOfView, bool show, int32_t cacheCount); 350 std::pair<int32_t, int32_t> UpdateCachedIndexOmni(int32_t forwardCache, int32_t backwardCache); 351 void UpdateActiveChildRange(bool forward, int32_t cacheCount, bool show); 352 void UpdateActiveChildRange(bool show); 353 void SyncItemsToCachedItemPosition(); 354 bool IsVisible() const; SetRecache(bool value)355 void SetRecache(bool value) 356 { 357 reCache_ = value; 358 } 359 void LayoutCache(const LayoutConstraintF& constraint, int64_t deadline, int32_t forwardCached, 360 int32_t backwardCached, ListMainSizeValues listSizeValues); 361 GetHeader()362 RefPtr<UINode> GetHeader() const 363 { 364 return header_.Upgrade(); 365 } 366 GetFooter()367 RefPtr<UINode> GetFooter() const 368 { 369 return footer_.Upgrade(); 370 } 371 372 void OnColorModeChange(uint32_t colorMode) override; 373 void UpdateDefaultColor(); 374 ChildPreMeasureHelperEnabled()375 bool ChildPreMeasureHelperEnabled() override 376 { 377 return true; 378 } PostponedTaskForIgnoreEnabled()379 bool PostponedTaskForIgnoreEnabled() override 380 { 381 return true; 382 } 383 NeedCustomizeSafeAreaPadding()384 bool NeedCustomizeSafeAreaPadding() override 385 { 386 return true; 387 } 388 ChildTentativelyLayouted()389 bool ChildTentativelyLayouted() override 390 { 391 return true; 392 } 393 394 private: 395 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 396 void OnAttachToFrameNode() override; 397 void OnAttachToFrameNodeMultiThread(); 398 void OnAttachToMainTree() override; 399 void OnAttachToMainTreeMultiThread(); 400 void SetListItemGroupDefaultAttributes(const RefPtr<FrameNode>& itemGroupNode); 401 void OnColorConfigurationUpdate() override; 402 void CheckListDirectionInCardStyle(); 403 float GetPaddingAndMargin() const; 404 float GetListPaddingOffset(const RefPtr<FrameNode>& listNode) const; 405 bool FirstItemFullVisible(const RefPtr<FrameNode>& listNode) const; 406 bool CheckDataChangeOutOfStart(int32_t index, int32_t count, int32_t startIndex, int32_t endIndex); 407 408 void HandleForwardStep( 409 const RefPtr<FrameNode>& curFrame, int32_t curIndexInGroup, int32_t& moveStep, int32_t& nextIndex); 410 void HandleBackwardStep( 411 const RefPtr<FrameNode>& curFrame, int32_t curIndexInGroup, int32_t& moveStep, int32_t& nextIndex); 412 bool HandleCrossAxisRightOrDownStep( 413 bool isVertical, int32_t curIndexInGroup, int32_t& moveStep, int32_t& nextIndex); 414 bool HandleCrossAxisLeftOrUpStep(bool isVertical, int32_t curIndexInGroup, int32_t& moveStep, int32_t& nextIndex); 415 416 bool GetCurrentFocusIndices( 417 const RefPtr<FrameNode>& curFrame, const RefPtr<Pattern>& curPattern, int32_t& curIndexInGroup); 418 bool IsListVertical() const; 419 void AdjustFocusStepForRtl(FocusStep& step, bool isVertical); 420 bool DetermineSingleLaneStep( 421 FocusStep step, bool isVertical, int32_t curIndex, int32_t& moveStep, int32_t& nextIndex); 422 bool DetermineMultiLaneStep(FocusStep step, bool isVertical, const RefPtr<FrameNode>& curFrame, 423 int32_t curIndexInGroup, int32_t& moveStep, int32_t& nextIndex); 424 bool IsIndexInValidRange(int32_t index, int32_t maxIndex); 425 bool IsFocusMovementBlock(int32_t nextIndex, int32_t curIndex, int32_t maxIndex) const; 426 WeakPtr<FocusHub> FindNextValidFocus(int32_t moveStep, int32_t curIndexInGroup, int32_t curGroupIndexInList, 427 int32_t nextIndexInGroup, const WeakPtr<FocusHub>& currentFocusNode, FocusStep step); 428 void AdjustMountTreeSequence(int32_t footerCount); 429 void MappingPropertiesFromLayoutAlgorithm(const RefPtr<ListItemGroupLayoutAlgorithm>& layoutAlgorithm); 430 const ListItemGroupInfo* GetPosition(int32_t index) const; 431 bool NextPositionBlocksMove( 432 const ListItemGroupInfo* curPos, const ListItemGroupInfo* nextPos, bool isVertical) const; 433 434 RefPtr<ShallowBuilder> shallowBuilder_; 435 RefPtr<ListPositionMap> posMap_; 436 RefPtr<ListChildrenMainSize> childrenSize_; 437 V2::ListItemGroupStyle listItemGroupStyle_ = V2::ListItemGroupStyle::NONE; 438 439 int32_t indexInList_ = 0; 440 441 WeakPtr<UINode> header_; 442 WeakPtr<UINode> footer_; 443 bool isHeaderComponentContentExist_ = false; 444 bool isFooterComponentContentExist_ = false; 445 int32_t itemStartIndex_ = 0; 446 int32_t headerIndex_ = -1; 447 int32_t footerIndex_ = -1; 448 int32_t footerCount_ = 0; 449 int32_t itemTotalCount_ = -1; 450 int32_t itemDisplayEndIndex_ = -1; 451 int32_t itemDisplayStartIndex_ = -1; 452 float_t headerMainSize_ = 0.0f; 453 float_t footerMainSize_ = 0.0f; 454 455 std::optional<LayoutedItemInfo> layoutedItemInfo_; 456 std::set<int32_t> pressedItem_; 457 bool layouted_ = false; 458 459 bool reCache_ = false; 460 int32_t backwardCachedIndex_ = INT_MAX; 461 int32_t forwardCachedIndex_ = -1; 462 ListItemGroupLayoutAlgorithm::PositionMap cachedItemPosition_; 463 float adjustRefPos_ = 0.0f; 464 float adjustTotalSize_ = 0.0f; 465 466 ListItemGroupLayoutAlgorithm::PositionMap itemPosition_; 467 float spaceWidth_ = 0.0f; 468 Axis axis_ = Axis::VERTICAL; 469 int32_t lanes_ = 1; 470 float laneGutter_ = 0.0f; 471 float startHeaderPos_ = 0.0f; 472 float endFooterPos_ = 0.0f; 473 TextDirection layoutDirection_ = TextDirection::LTR; 474 float mainSize_ = 0.0f; 475 float listContentSize_ = 0.0f; 476 bool isStackFromEnd_ = false; 477 bool prevMeasureBreak_ = false; 478 ACE_DISALLOW_COPY_AND_MOVE(ListItemGroupPattern); 479 }; 480 } // namespace OHOS::Ace::NG 481 482 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_ITEM_PATTERN_H 483