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_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_PATTERN_H 18 19 #include <tuple> 20 #include "core/animation/chain_animation.h" 21 #include "core/components_ng/pattern/list/list_accessibility_property.h" 22 #include "core/components_ng/pattern/list/list_children_main_size.h" 23 #include "core/components_ng/pattern/list/list_content_modifier.h" 24 #include "core/components_ng/pattern/list/list_event_hub.h" 25 #include "core/components_ng/pattern/list/list_item_pattern.h" 26 #include "core/components_ng/pattern/list/list_layout_algorithm.h" 27 #include "core/components_ng/pattern/list/list_layout_property.h" 28 #include "core/components_ng/pattern/list/list_paint_method.h" 29 #include "core/components_ng/pattern/list/list_position_map.h" 30 #include "core/components_ng/pattern/scroll/inner/scroll_bar.h" 31 #include "core/components_ng/pattern/scroll_bar/proxy/scroll_bar_proxy.h" 32 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h" 33 #include "core/components_ng/render/render_context.h" 34 #include "core/pipeline_ng/pipeline_context.h" 35 36 namespace OHOS::Ace::NG { 37 class InspectorFilter; 38 39 struct ListItemGroupPara { 40 int32_t lanes = -1; 41 int32_t itemEndIndex = -1; 42 int32_t displayStartIndex = -1; 43 int32_t displayEndIndex = -1; 44 }; 45 46 struct ListScrollTarget { 47 int32_t index = -1; 48 float extraOffset = 0.0f; 49 ScrollAlign align = ScrollAlign::START; 50 float targetOffset; 51 }; 52 53 class ListPattern : public ScrollablePattern { 54 DECLARE_ACE_TYPE(ListPattern, ScrollablePattern); 55 56 public: ListPattern()57 ListPattern() : ScrollablePattern(EdgeEffect::SPRING, false) {} 58 ~ListPattern() override = default; 59 60 RefPtr<NodePaintMethod> CreateNodePaintMethod() override; 61 CreateLayoutProperty()62 RefPtr<LayoutProperty> CreateLayoutProperty() override 63 { 64 return MakeRefPtr<ListLayoutProperty>(); 65 } 66 CreateEventHub()67 RefPtr<EventHub> CreateEventHub() override 68 { 69 return MakeRefPtr<ListEventHub>(); 70 } 71 CreateAccessibilityProperty()72 RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override 73 { 74 return MakeRefPtr<ListAccessibilityProperty>(); 75 } 76 UsResRegion()77 bool UsResRegion() override 78 { 79 return false; 80 } 81 82 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override; 83 84 void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override; 85 86 void FromJson(const std::unique_ptr<JsonValue>& json) override; 87 88 bool UpdateCurrentOffset(float offset, int32_t source) override; 89 90 DisplayMode GetDefaultScrollBarDisplayMode() const override; 91 GetStartIndex()92 int32_t GetStartIndex() const 93 { 94 return startIndex_; 95 } 96 GetEndIndex()97 int32_t GetEndIndex() const 98 { 99 return endIndex_; 100 } 101 GetMaxListItemIndex()102 int32_t GetMaxListItemIndex() const 103 { 104 return maxListItemIndex_; 105 } 106 IsScrollable()107 bool IsScrollable() const override 108 { 109 return isScrollable_; 110 } 111 SetMaintainVisibleContentPosition(bool enabled)112 void SetMaintainVisibleContentPosition(bool enabled) 113 { 114 maintainVisibleContentPosition_ = enabled; 115 } 116 GetMaintainVisibleContentPosition()117 bool GetMaintainVisibleContentPosition() 118 { 119 return maintainVisibleContentPosition_; 120 } 121 MarkNeedReEstimateOffset()122 void MarkNeedReEstimateOffset() 123 { 124 needReEstimateOffset_ = true; 125 } 126 127 void NotifyDataChange(int32_t index, int32_t count) override; 128 129 bool IsAtTop() const override; 130 bool IsAtBottom() const override; 131 void OnTouchDown(const TouchEventInfo& info) override; 132 OverScrollOffset GetOutBoundaryOffset(bool useCurrentDelta) const; 133 OverScrollOffset GetOverScrollOffset(double delta) const override; 134 float GetOffsetWithLimit(float offset) const override; 135 void HandleScrollBarOutBoundary(); 136 GetFocusPattern()137 FocusPattern GetFocusPattern() const override 138 { 139 return { FocusType::SCOPE, true }; 140 } 141 GetScopeFocusAlgorithm()142 ScopeFocusAlgorithm GetScopeFocusAlgorithm() override 143 { 144 auto property = GetLayoutProperty<ListLayoutProperty>(); 145 if (!property) { 146 return {}; 147 } 148 return ScopeFocusAlgorithm(property->GetListDirection().value_or(Axis::VERTICAL) == Axis::VERTICAL, true, 149 ScopeType::OTHERS, 150 [wp = WeakClaim(this)]( 151 FocusStep step, const WeakPtr<FocusHub>& currFocusNode, WeakPtr<FocusHub>& nextFocusNode) { 152 auto list = wp.Upgrade(); 153 if (list) { 154 nextFocusNode = list->GetNextFocusNode(step, currFocusNode); 155 } 156 }); 157 } 158 159 ScrollOffsetAbility GetScrollOffsetAbility() override; 160 161 std::function<bool(int32_t)> GetScrollIndexAbility() override; 162 163 bool ScrollToNode(const RefPtr<FrameNode>& focusFrameNode) override; 164 GetItemPosition()165 const ListLayoutAlgorithm::PositionMap& GetItemPosition() const 166 { 167 return itemPosition_; 168 } 169 GetTotalOffset()170 float GetTotalOffset() const override 171 { 172 return currentOffset_; 173 } 174 GetPositionController()175 RefPtr<ScrollControllerBase> GetPositionController() const 176 { 177 return positionController_; 178 } 179 180 int32_t ProcessAreaVertical(double& x, double& y, Rect& groupRect, int32_t& index, 181 RefPtr<ListItemGroupPattern> groupItemPattern) const; 182 int32_t ProcessAreaHorizontal(double& x, double& y, Rect& groupRect, int32_t& index, 183 RefPtr<ListItemGroupPattern> groupItemPattern) const; 184 void TriggerModifyDone(); 185 186 float GetTotalHeight() const override; 187 188 // scroller 189 void ScrollTo(float position) override; 190 void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START, 191 std::optional<float> extraOffset = std::nullopt) override; 192 void ScrollToItemInGroup(int32_t index, int32_t indexInGroup, bool smooth = false, 193 ScrollAlign align = ScrollAlign::START); 194 bool CheckTargetValid(int32_t index, int32_t indexInGroup); 195 void ScrollPage(bool reverse, bool smooth = false, 196 AccessibilityScrollType scrollType = AccessibilityScrollType::SCROLL_FULL) override; 197 void ScrollBy(float offset); 198 bool AnimateToTarget(int32_t index, std::optional<int32_t> indexInGroup, ScrollAlign align); 199 Offset GetCurrentOffset() const; 200 Rect GetItemRect(int32_t index) const override; 201 int32_t GetItemIndex(double x, double y) const override; 202 Rect GetItemRectInGroup(int32_t index, int32_t indexInGroup) const; 203 ListItemIndex GetItemIndexInGroup(double x, double y) const; 204 bool GetGroupItemIndex(double x, double y, RefPtr<FrameNode> itemFrameNode, int32_t& index, 205 ListItemIndex& itemIndex) const; 206 void OnAnimateStop() override; GetMainContentSize()207 float GetMainContentSize() const override 208 { 209 return contentMainSize_; 210 } GetLanes()211 int32_t GetLanes() const 212 { 213 return lanes_; 214 } 215 216 void UpdatePosMapStart(float delta); 217 void UpdatePosMapEnd(); 218 void CalculateCurrentOffset(float delta, const ListLayoutAlgorithm::PositionMap& recycledItemPosition); 219 void UpdateScrollBarOffset() override; 220 // chain animation 221 void SetChainAnimation(); 222 void SetChainAnimationOptions(const ChainAnimationOptions& options); 223 float FlushChainAnimation(float dragOffset); 224 void ProcessDragStart(float startPosition); 225 void ProcessDragUpdate(float dragOffset, int32_t source); 226 float GetChainDelta(int32_t index) const; 227 228 // multiSelectable SetMultiSelectable(bool multiSelectable)229 void SetMultiSelectable(bool multiSelectable) 230 { 231 multiSelectable_ = multiSelectable; 232 } 233 234 void SetSwiperItem(WeakPtr<ListItemPattern> swiperItem); GetSwiperItem()235 WeakPtr<ListItemPattern> GetSwiperItem() 236 { 237 if (!swiperItem_.Upgrade()) { 238 return nullptr; 239 } 240 return swiperItem_; 241 } SetSwiperItemEnd(WeakPtr<ListItemPattern> swiperItem)242 void SetSwiperItemEnd(WeakPtr<ListItemPattern> swiperItem) 243 { 244 if (swiperItem == swiperItem_) { 245 canReplaceSwiperItem_ = true; 246 } 247 } IsCurrentSwiperItem(WeakPtr<ListItemPattern> swiperItem)248 bool IsCurrentSwiperItem(WeakPtr<ListItemPattern> swiperItem) 249 { 250 if (!swiperItem_.Upgrade()) { 251 return true; 252 } 253 return swiperItem == swiperItem_; 254 } CanReplaceSwiperItem()255 bool CanReplaceSwiperItem() 256 { 257 auto listItemPattern = swiperItem_.Upgrade(); 258 if (!listItemPattern) { 259 canReplaceSwiperItem_ = true; 260 return canReplaceSwiperItem_; 261 } 262 auto host = listItemPattern->GetHost(); 263 if (!host || !host->IsOnMainTree()) { 264 canReplaceSwiperItem_ = true; 265 return canReplaceSwiperItem_; 266 } 267 return canReplaceSwiperItem_; 268 } 269 SetPredictSnapOffset(float predictSnapOffset)270 void SetPredictSnapOffset(float predictSnapOffset) 271 { 272 predictSnapOffset_ = predictSnapOffset; 273 } 274 bool OnScrollSnapCallback(double targetOffset, double velocity) override; 275 276 int32_t GetItemIndexByPosition(float xOffset, float yOffset); 277 SetPredictLayoutParam(std::optional<ListPredictLayoutParam> param)278 void SetPredictLayoutParam(std::optional<ListPredictLayoutParam> param) 279 { 280 predictLayoutParam_ = param; 281 } GetPredictLayoutParam()282 std::optional<ListPredictLayoutParam> GetPredictLayoutParam() const 283 { 284 return predictLayoutParam_; 285 } 286 SetPredictLayoutParamV2(std::optional<ListPredictLayoutParamV2> param)287 void SetPredictLayoutParamV2(std::optional<ListPredictLayoutParamV2> param) 288 { 289 predictLayoutParamV2_ = param; 290 } 291 GetPredictLayoutParamV2()292 std::optional<ListPredictLayoutParamV2> GetPredictLayoutParamV2() const 293 { 294 return predictLayoutParamV2_; 295 } 296 297 void CloseAllSwipeActions(OnFinishFunc&&); 298 299 std::string ProvideRestoreInfo() override; 300 void OnRestoreInfo(const std::string& restoreInfo) override; 301 void DumpAdvanceInfo() override; 302 SetNeedToUpdateListDirectionInCardStyle(bool isNeedToUpdateListDirection)303 void SetNeedToUpdateListDirectionInCardStyle(bool isNeedToUpdateListDirection) 304 { 305 isNeedToUpdateListDirection_ = isNeedToUpdateListDirection; 306 } 307 IsNeedToUpdateListDirectionInCardStyle()308 bool IsNeedToUpdateListDirectionInCardStyle() const 309 { 310 return isNeedToUpdateListDirection_; 311 } 312 313 std::vector<RefPtr<FrameNode>> GetVisibleSelectedItems() override; 314 SetItemPressed(bool isPressed,int32_t id)315 void SetItemPressed(bool isPressed, int32_t id) 316 { 317 if (isPressed) { 318 pressedItem_.emplace(id); 319 } else { 320 pressedItem_.erase(id); 321 } 322 } 323 324 RefPtr<ListChildrenMainSize> GetOrCreateListChildrenMainSize(); 325 void SetListChildrenMainSize(float defaultSize, const std::vector<float>& mainSize); 326 void OnChildrenSizeChanged(std::tuple<int32_t, int32_t, int32_t> change, ListChangeFlag flag); 327 void ResetChildrenSize(); ListChildrenSizeExist()328 bool ListChildrenSizeExist() 329 { 330 return static_cast<bool>(childrenSize_); 331 } CanOverScroll(int32_t source)332 bool CanOverScroll(int32_t source) override 333 { 334 auto canOverScroll = (IsScrollableSpringEffect() && source != SCROLL_FROM_AXIS && source != SCROLL_FROM_BAR && 335 IsScrollable() && (!ScrollableIdle() || animateOverScroll_ || animateCanOverScroll_) && 336 (IsAtBottom() || IsAtTop())); 337 if (canOverScroll != lastCanOverScroll_) { 338 lastCanOverScroll_ = canOverScroll; 339 AddScrollableFrameInfo(source); 340 } 341 return canOverScroll; 342 } 343 void UpdateChildPosInfo(int32_t index, float delta, float sizeChange); 344 345 SizeF GetChildrenExpandedSize() override; 346 private: 347 IsNeedInitClickEventRecorder()348 bool IsNeedInitClickEventRecorder() const override 349 { 350 return true; 351 } 352 353 void OnScrollEndCallback() override; 354 void FireOnReachStart(const OnReachEvent& onReachStart) override; 355 void FireOnReachEnd(const OnReachEvent& onReachEnd) override; 356 void FireOnScrollIndex(bool indexChanged, const OnScrollIndexEvent& onScrollIndex); 357 void OnModifyDone() override; 358 void ChangeAxis(RefPtr<UINode> node); 359 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 360 float CalculateTargetPos(float startPos, float endPos); 361 362 void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub); 363 bool OnKeyEvent(const KeyEvent& event); 364 bool HandleDirectionKey(const KeyEvent& event); 365 WeakPtr<FocusHub> GetNextFocusNode(FocusStep step, const WeakPtr<FocusHub>& currentFocusNode); 366 WeakPtr<FocusHub> GetChildFocusNodeByIndex(int32_t tarMainIndex, int32_t tarGroupIndex); 367 WeakPtr<FocusHub> ScrollAndFindFocusNode(int32_t nextIndex, int32_t curIndex, int32_t& nextIndexInGroup, 368 int32_t curIndexInGroup, int32_t moveStep, FocusStep step); 369 bool ScrollListForFocus(int32_t nextIndex, int32_t curIndex, int32_t nextIndexInGroup); 370 bool ScrollListItemGroupForFocus(int32_t nextIndex, int32_t& nextIndexInGroup, int32_t curIndexInGroup, 371 int32_t moveStep, FocusStep step, bool isScrollIndex); 372 373 void MarkDirtyNodeSelf(); 374 SizeF GetContentSize() const; 375 void ProcessEvent(bool indexChanged, float finalOffset, bool isJump); 376 void CheckScrollable(); 377 bool IsOutOfBoundary(bool useCurrentDelta = true) override; 378 bool OnScrollCallback(float offset, int32_t source) override; 379 void SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect>& scrollEffect) override; 380 void HandleScrollEffect(float offset); 381 void StartDefaultOrCustomSpringMotion(float start, float end, const RefPtr<InterpolatingSpring>& curve); 382 bool IsScrollSnapAlignCenter() const; 383 void SetChainAnimationCallback(); 384 void SetChainAnimationToPosMap(); 385 void SetChainAnimationLayoutAlgorithm( 386 RefPtr<ListLayoutAlgorithm> listLayoutAlgorithm, RefPtr<ListLayoutProperty> listLayoutProperty); 387 bool NeedScrollSnapAlignEffect() const; 388 ScrollAlign GetScrollAlignByScrollSnapAlign() const; 389 bool GetListItemAnimatePos(float startPos, float endPos, ScrollAlign align, float& targetPos); 390 bool GetListItemGroupAnimatePosWithoutIndexInGroup(int32_t index, float startPos, float endPos, 391 ScrollAlign align, float& targetPos); 392 bool GetListItemGroupAnimatePosWithIndexInGroup(int32_t index, int32_t indexInGroup, float startPos, 393 ScrollAlign align, float& targetPos); 394 395 // multiSelectable 396 void ClearMultiSelect() override; 397 bool IsItemSelected(const GestureEvent& info) override; 398 void MultiSelectWithoutKeyboard(const RectF& selectedZone) override; 399 void HandleCardModeSelectedEvent( 400 const RectF& selectedZone, const RefPtr<FrameNode>& itemGroupNode, float itemGroupTop); 401 402 void DrivenRender(const RefPtr<LayoutWrapper>& layoutWrapper); 403 ListItemGroupPara GetListItemGroupParameter(const RefPtr<FrameNode>& node); 404 bool IsListItemGroup(int32_t listIndex, RefPtr<FrameNode>& node); 405 void GetListItemGroupEdge(bool& groupAtStart, bool& groupAtEnd) const; 406 void RefreshLanesItemRange(); 407 void UpdateListDirectionInCardStyle(); 408 bool UpdateStartListItemIndex(); 409 bool UpdateEndListItemIndex(); 410 float GetStartOverScrollOffset(float offset, float startMainPos) const; 411 float GetEndOverScrollOffset(float offset, float endMainPos, float startMainPos) const; 412 float UpdateTotalOffset(const RefPtr<ListLayoutAlgorithm>& listLayoutAlgorithm, bool isJump); 413 RefPtr<ListContentModifier> listContentModifier_; 414 415 int32_t maxListItemIndex_ = 0; 416 int32_t startIndex_ = -1; 417 int32_t endIndex_ = -1; 418 int32_t centerIndex_ = -1; 419 float startMainPos_ = 0.0f; 420 float endMainPos_ = 0.0f; 421 float prevStartOffset_ = 0.f; 422 float prevEndOffset_ = 0.f; 423 float currentOffset_ = 0.0f; 424 float spaceWidth_ = 0.0f; 425 float contentMainSize_ = 0.0f; 426 float contentStartOffset_ = 0.0f; 427 float contentEndOffset_ = 0.0f; 428 bool maintainVisibleContentPosition_ = false; 429 430 float currentDelta_ = 0.0f; 431 bool crossMatchChild_ = false; 432 bool smooth_ = false; 433 float scrollSnapVelocity_ = 0.0f; 434 bool snapTrigOnScrollStart_ = false; 435 436 std::optional<int32_t> jumpIndex_; 437 std::optional<int32_t> jumpIndexInGroup_; 438 std::optional<int32_t> targetIndex_; 439 std::optional<int32_t> targetIndexInGroup_; 440 std::optional<ListScrollTarget> scrollTarget_; 441 std::optional<float> predictSnapOffset_; 442 std::optional<float> predictSnapEndPos_; 443 ScrollAlign scrollAlign_ = ScrollAlign::START; 444 bool isScrollable_ = true; 445 bool paintStateFlag_ = false; 446 bool isFramePaintStateValid_ = false; 447 bool isNeedCheckOffset_ = false; 448 449 ListLayoutAlgorithm::PositionMap itemPosition_; 450 ListLayoutAlgorithm::PositionMap cachedItemPosition_; 451 RefPtr<ListPositionMap> posMap_; 452 RefPtr<ListChildrenMainSize> childrenSize_; 453 float listTotalHeight_ = 0.0f; 454 455 std::map<int32_t, int32_t> lanesItemRange_; 456 std::set<int32_t> pressedItem_; 457 int32_t lanes_ = 1; 458 float laneGutter_ = 0.0f; 459 // chain animation 460 RefPtr<ChainAnimation> chainAnimation_; 461 bool dragFromSpring_ = false; 462 RefPtr<SpringProperty> springProperty_; 463 std::optional<ChainAnimationOptions> chainAnimationOptions_; 464 465 bool isOritationListenerRegisted_ = false; 466 467 // ListItem swiperAction 468 WeakPtr<ListItemPattern> swiperItem_; 469 bool canReplaceSwiperItem_ = true; 470 471 RefPtr<SpringMotion> scrollToIndexMotion_; 472 RefPtr<SpringMotion> scrollSnapMotion_; 473 RefPtr<Scrollable> scrollable_; 474 475 bool isScrollEnd_ = false; 476 bool needReEstimateOffset_ = false; 477 std::optional<ListPredictLayoutParam> predictLayoutParam_; 478 std::optional<ListPredictLayoutParamV2> predictLayoutParamV2_; 479 480 bool isNeedToUpdateListDirection_ = false; 481 bool startIndexChanged_ = false; 482 bool endIndexChanged_ = false; 483 484 ListItemIndex startInfo_ = {-1, -1, -1}; 485 ListItemIndex endInfo_ = {-1, -1, -1}; 486 }; 487 } // namespace OHOS::Ace::NG 488 489 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_PATTERN_H 490