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 }; 42 43 enum ListItemGroupArea { 44 NONE_AREA, 45 IN_LIST_ITEM_AREA, 46 IN_HEADER_AREA, 47 IN_FOOTER_AREA 48 }; 49 50 struct VisibleContentInfo { 51 int32_t area = -1; 52 int32_t indexInGroup = -1; 53 }; 54 55 struct ListMainSizeValues { 56 float startPos = 0.0f; 57 float endPos = 0.0f; 58 std::optional<int32_t> jumpIndexInGroup; 59 float prevContentMainSize = 0.0f; 60 ScrollAlign scrollAlign = ScrollAlign::START; 61 std::optional<float> layoutStartMainPos; 62 std::optional<float> layoutEndMainPos; 63 float referencePos = 0.0f; 64 float contentStartOffset = 0.0f; 65 float contentEndOffset = 0.0f; 66 bool forward = true; 67 bool backward = false; 68 }; 69 70 class ACE_EXPORT ListItemGroupPattern : public Pattern { 71 DECLARE_ACE_TYPE(ListItemGroupPattern, Pattern); 72 73 public: ListItemGroupPattern(const RefPtr<ShallowBuilder> & shallowBuilder,V2::ListItemGroupStyle listItemGroupStyle)74 explicit ListItemGroupPattern( 75 const RefPtr<ShallowBuilder>& shallowBuilder, V2::ListItemGroupStyle listItemGroupStyle) 76 : shallowBuilder_(shallowBuilder), listItemGroupStyle_(listItemGroupStyle) 77 {} 78 ~ListItemGroupPattern() override = default; 79 80 void DumpAdvanceInfo() override; IsAtomicNode()81 bool IsAtomicNode() const override 82 { 83 return false; 84 } 85 86 void NotifyDataChange(int32_t index, int32_t count) override; 87 CreateLayoutProperty()88 RefPtr<LayoutProperty> CreateLayoutProperty() override 89 { 90 return MakeRefPtr<ListItemGroupLayoutProperty>(); 91 } 92 CreateAccessibilityProperty()93 RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override 94 { 95 return MakeRefPtr<ListItemGroupAccessibilityProperty>(); 96 } 97 98 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override; 99 100 RefPtr<NodePaintMethod> CreateNodePaintMethod() override; 101 AddHeader(const RefPtr<NG::UINode> & header)102 void AddHeader(const RefPtr<NG::UINode>& header) 103 { 104 auto host = GetHost(); 105 CHECK_NULL_VOID(host); 106 auto prevHeader = header_.Upgrade(); 107 if (!prevHeader) { 108 host->AddChild(header, 0); 109 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); 110 } else { 111 if (header != prevHeader) { 112 host->ReplaceChild(prevHeader, header); 113 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); 114 } 115 } 116 header_ = header; 117 } 118 AddFooter(const RefPtr<NG::UINode> & footer)119 void AddFooter(const RefPtr<NG::UINode>& footer) 120 { 121 auto host = GetHost(); 122 CHECK_NULL_VOID(host); 123 auto prevFooter = footer_.Upgrade(); 124 auto prevHeader = header_.Upgrade(); 125 if (!prevFooter) { 126 if (prevHeader) { 127 host->AddChildAfter(footer, prevHeader); 128 } else { 129 host->AddChild(footer, 0); 130 } 131 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); 132 } else { 133 if (footer != prevFooter) { 134 host->ReplaceChild(prevFooter, footer); 135 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); 136 } 137 } 138 footer_ = footer; 139 } 140 RemoveHeader()141 void RemoveHeader() 142 { 143 auto host = GetHost(); 144 CHECK_NULL_VOID(host); 145 auto prevHeader = header_.Upgrade(); 146 if (prevHeader && isHeaderComponentContentExist_) { 147 host->RemoveChild(prevHeader); 148 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); 149 header_ = nullptr; 150 isHeaderComponentContentExist_ = false; 151 } 152 } 153 RemoveFooter()154 void RemoveFooter() 155 { 156 auto host = GetHost(); 157 CHECK_NULL_VOID(host); 158 auto prevFooter = footer_.Upgrade(); 159 if (prevFooter && isFooterComponentContentExist_) { 160 host->RemoveChild(prevFooter); 161 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); 162 footer_ = nullptr; 163 isFooterComponentContentExist_ = false; 164 } 165 } 166 IsHasHeader()167 bool IsHasHeader() 168 { 169 auto headerNode = DynamicCast<FrameNode>(header_.Upgrade()); 170 return headerNode ? true : false; 171 } 172 IsHasFooter()173 bool IsHasFooter() 174 { 175 auto footerGroup = DynamicCast<FrameNode>(footer_.Upgrade()); 176 return footerGroup ? true : false; 177 } 178 GetItemPosition()179 const ListItemGroupLayoutAlgorithm::PositionMap& GetItemPosition() 180 { 181 return itemPosition_; 182 } 183 SetIndexInList(int32_t index)184 void SetIndexInList(int32_t index) 185 { 186 indexInList_ = index; 187 } 188 SetHeaderComponentContentExist(bool isHeaderComponentContentExist)189 void SetHeaderComponentContentExist(bool isHeaderComponentContentExist) 190 { 191 isHeaderComponentContentExist_ = isHeaderComponentContentExist; 192 } 193 SetFooterComponentContentExist(bool isFooterComponentContentExist)194 void SetFooterComponentContentExist(bool isFooterComponentContentExist) 195 { 196 isFooterComponentContentExist_ = isFooterComponentContentExist; 197 } 198 GetIndexInList()199 int32_t GetIndexInList() const 200 { 201 return indexInList_; 202 } 203 GetDisplayEndIndexInGroup()204 int32_t GetDisplayEndIndexInGroup() const 205 { 206 return itemDisplayEndIndex_; 207 } 208 GetDisplayStartIndexInGroup()209 int32_t GetDisplayStartIndexInGroup() const 210 { 211 return itemDisplayStartIndex_; 212 } 213 GetItemStartIndex()214 int32_t GetItemStartIndex() const 215 { 216 return itemStartIndex_; 217 } 218 GetEndIndexInGroup()219 int32_t GetEndIndexInGroup() const 220 { 221 return (itemTotalCount_ - 1); 222 } 223 GetTotalItemCount()224 int32_t GetTotalItemCount() const 225 { 226 return itemTotalCount_; 227 } 228 IsDisplayStart()229 bool IsDisplayStart() const 230 { 231 return itemDisplayStartIndex_ == 0; 232 } 233 IsDisplayEnd()234 int32_t IsDisplayEnd() const 235 { 236 return itemTotalCount_ == 0 || itemDisplayEndIndex_ == (itemTotalCount_ - 1); 237 } 238 GetLanesInGroup()239 int32_t GetLanesInGroup() const 240 { 241 return lanes_; 242 } 243 SetLanes(int32_t num)244 void SetLanes(int32_t num) 245 { 246 lanes_ = num; 247 } 248 GetListItemGroupStyle()249 V2::ListItemGroupStyle GetListItemGroupStyle() 250 { 251 return listItemGroupStyle_; 252 } 253 GetHeaderMainSize()254 float GetHeaderMainSize() const 255 { 256 return headerMainSize_; 257 } 258 GetFooterMainSize()259 float GetFooterMainSize() const 260 { 261 return footerMainSize_; 262 } 263 264 float GetEstimateOffset(float height, const std::pair<float, float>& targetPos) const; 265 float GetEstimateHeight(float& averageHeight) const; HasLayoutedItem()266 bool HasLayoutedItem() const 267 { 268 return layouted_ && (layoutedItemInfo_.has_value() || itemTotalCount_ == 0); 269 } 270 SetItemPressed(bool isPressed,int32_t id)271 void SetItemPressed(bool isPressed, int32_t id) 272 { 273 if (isPressed) { 274 pressedItem_.emplace(id); 275 } else { 276 pressedItem_.erase(id); 277 } 278 } 279 280 void SetListItemGroupStyle(V2::ListItemGroupStyle style); 281 RefPtr<ListChildrenMainSize> GetOrCreateListChildrenMainSize(); 282 void SetListChildrenMainSize(float defaultSize, const std::vector<float>& mainSize); 283 void OnChildrenSizeChanged(std::tuple<int32_t, int32_t, int32_t> change, ListChangeFlag flag); 284 bool ListChildrenSizeExist(); 285 RefPtr<FrameNode> GetListFrameNode() const; 286 VisibleContentInfo GetStartListItemIndex(); 287 VisibleContentInfo GetEndListItemIndex(); 288 void ResetChildrenSize(); 289 290 void ClearItemPosition(); 291 void ClearCachedItemPosition(); 292 void CalculateItemStartIndex(); 293 bool NeedCacheForward(const LayoutWrapper* listWrapper) const; 294 CachedIndexInfo UpdateCachedIndex(bool outOfView, bool reCache, int32_t forwardCache, int32_t backwardCache); 295 int32_t UpdateCachedIndexForward(bool outOfView, bool show, int32_t cacheCount); 296 int32_t UpdateCachedIndexBackward(bool outOfView, bool show, int32_t cacheCount); 297 std::pair<int32_t, int32_t> UpdateCachedIndexOmni(int32_t forwardCache, int32_t backwardCache); 298 void UpdateActiveChildRange(bool forward, int32_t cacheCount, bool show); 299 void UpdateActiveChildRange(bool show); 300 void SyncItemsToCachedItemPosition(); SetRecache(bool value)301 void SetRecache(bool value) 302 { 303 reCache_ = value; 304 } 305 void LayoutCache(const LayoutConstraintF& constraint, int64_t deadline, int32_t forwardCached, 306 int32_t backwardCached, ListMainSizeValues listSizeValues); 307 308 private: IsNeedInitClickEventRecorder()309 bool IsNeedInitClickEventRecorder() const override 310 { 311 return true; 312 } 313 314 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 315 void OnAttachToFrameNode() override; 316 void SetListItemGroupDefaultAttributes(const RefPtr<FrameNode>& itemGroupNode); 317 void OnColorConfigurationUpdate() override; 318 void CheckListDirectionInCardStyle(); 319 float GetPaddingAndMargin() const; 320 float GetListPaddingOffset(const RefPtr<FrameNode>& listNode) const; 321 bool FirstItemFullVisible(const RefPtr<FrameNode>& listNode) const; 322 bool CheckDataChangeOutOfStart(int32_t index, int32_t count, int32_t startIndex); 323 324 RefPtr<ShallowBuilder> shallowBuilder_; 325 RefPtr<ListPositionMap> posMap_; 326 RefPtr<ListChildrenMainSize> childrenSize_; 327 V2::ListItemGroupStyle listItemGroupStyle_ = V2::ListItemGroupStyle::NONE; 328 329 int32_t indexInList_ = 0; 330 331 WeakPtr<UINode> header_; 332 WeakPtr<UINode> footer_; 333 bool isHeaderComponentContentExist_ = false; 334 bool isFooterComponentContentExist_ = false; 335 int32_t itemStartIndex_ = 0; 336 int32_t headerIndex_ = -1; 337 int32_t footerIndex_ = -1; 338 int32_t itemTotalCount_ = -1; 339 int32_t itemDisplayEndIndex_ = -1; 340 int32_t itemDisplayStartIndex_ = -1; 341 float_t headerMainSize_ = 0.0f; 342 float_t footerMainSize_ = 0.0f; 343 344 std::optional<LayoutedItemInfo> layoutedItemInfo_; 345 std::set<int32_t> pressedItem_; 346 bool layouted_ = false; 347 LayoutConstraintF layoutConstraint_; 348 349 bool reCache_ = false; 350 int32_t backwardCachedIndex_ = INT_MAX; 351 int32_t forwardCachedIndex_ = -1; 352 ListItemGroupLayoutAlgorithm::PositionMap cachedItemPosition_; 353 float adjustRefPos_ = 0.0f; 354 float adjustTotalSize_ = 0.0f; 355 356 ListItemGroupLayoutAlgorithm::PositionMap itemPosition_; 357 float spaceWidth_ = 0.0f; 358 Axis axis_ = Axis::VERTICAL; 359 int32_t lanes_ = 1; 360 float laneGutter_ = 0.0f; 361 float startHeaderPos_ = 0.0f; 362 float endFooterPos_ = 0.0f; 363 TextDirection layoutDirection_ = TextDirection::LTR; 364 float mainSize_ = 0.0f; 365 ACE_DISALLOW_COPY_AND_MOVE(ListItemGroupPattern); 366 }; 367 } // namespace OHOS::Ace::NG 368 369 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_ITEM_PATTERN_H 370