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