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 "core/animation/chain_animation.h" 20 #include "core/components_ng/pattern/list/list_accessibility_property.h" 21 #include "core/components_ng/pattern/list/list_content_modifier.h" 22 #include "core/components_ng/pattern/list/list_event_hub.h" 23 #include "core/components_ng/pattern/list/list_item_pattern.h" 24 #include "core/components_ng/pattern/list/list_layout_algorithm.h" 25 #include "core/components_ng/pattern/list/list_layout_property.h" 26 #include "core/components_ng/pattern/list/list_paint_method.h" 27 #include "core/components_ng/pattern/scroll/inner/scroll_bar.h" 28 #include "core/components_ng/pattern/scroll_bar/proxy/scroll_bar_proxy.h" 29 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h" 30 #include "core/components_ng/render/render_context.h" 31 #include "core/pipeline_ng/pipeline_context.h" 32 33 namespace OHOS::Ace::NG { 34 struct ListItemGroupPara { 35 int32_t lanes = -1; 36 int32_t itemEndIndex = -1; 37 int32_t displayStartIndex = -1; 38 int32_t displayEndIndex = -1; 39 }; 40 41 class ListPattern : public ScrollablePattern { 42 DECLARE_ACE_TYPE(ListPattern, ScrollablePattern); 43 44 public: ListPattern()45 ListPattern() : ScrollablePattern(EdgeEffect::SPRING, false) {} 46 ~ListPattern() override = default; 47 48 RefPtr<NodePaintMethod> CreateNodePaintMethod() override; 49 CreateLayoutProperty()50 RefPtr<LayoutProperty> CreateLayoutProperty() override 51 { 52 return MakeRefPtr<ListLayoutProperty>(); 53 } 54 CreateEventHub()55 RefPtr<EventHub> CreateEventHub() override 56 { 57 return MakeRefPtr<ListEventHub>(); 58 } 59 CreateAccessibilityProperty()60 RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override 61 { 62 return MakeRefPtr<ListAccessibilityProperty>(); 63 } 64 UsResRegion()65 bool UsResRegion() override 66 { 67 return false; 68 } 69 70 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override; 71 72 void ToJsonValue(std::unique_ptr<JsonValue>& json) const override; 73 74 void FromJson(const std::unique_ptr<JsonValue>& json) override; 75 76 bool UpdateCurrentOffset(float offset, int32_t source) override; 77 78 DisplayMode GetDefaultScrollBarDisplayMode() const override; 79 GetStartIndex()80 int32_t GetStartIndex() const 81 { 82 return startIndex_; 83 } 84 GetEndIndex()85 int32_t GetEndIndex() const 86 { 87 return endIndex_; 88 } 89 GetMaxListItemIndex()90 int32_t GetMaxListItemIndex() const 91 { 92 return maxListItemIndex_; 93 } 94 IsScrollable()95 bool IsScrollable() const override 96 { 97 return scrollable_; 98 } 99 100 bool IsAtTop() const override; 101 bool IsAtBottom() const override; 102 bool OutBoundaryCallback() override; 103 OverScrollOffset GetOverScrollOffset(double delta) const override; 104 float GetOffsetWithLimit(float offset) const override; 105 void HandleScrollBarOutBoundary(); 106 GetFocusPattern()107 FocusPattern GetFocusPattern() const override 108 { 109 return { FocusType::SCOPE, true }; 110 } 111 GetScopeFocusAlgorithm()112 ScopeFocusAlgorithm GetScopeFocusAlgorithm() override 113 { 114 auto property = GetLayoutProperty<ListLayoutProperty>(); 115 if (!property) { 116 return {}; 117 } 118 return ScopeFocusAlgorithm(property->GetListDirection().value_or(Axis::VERTICAL) == Axis::VERTICAL, true, 119 ScopeType::OTHERS, 120 [wp = WeakClaim(this)]( 121 FocusStep step, const WeakPtr<FocusHub>& currFocusNode, WeakPtr<FocusHub>& nextFocusNode) { 122 auto list = wp.Upgrade(); 123 if (list) { 124 nextFocusNode = list->GetNextFocusNode(step, currFocusNode); 125 } 126 }); 127 } 128 129 bool ScrollToNode(const RefPtr<FrameNode>& focusFrameNode) override; 130 GetItemPosition()131 const ListLayoutAlgorithm::PositionMap& GetItemPosition() const 132 { 133 return itemPosition_; 134 } 135 GetTotalOffset()136 float GetTotalOffset() const override 137 { 138 return currentOffset_; 139 } 140 141 float GetTotalHeight() const override; 142 143 // scroller 144 void ScrollTo(float position) override; 145 void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START) override; 146 void ScrollToItemInGroup(int32_t index, int32_t indexInGroup, bool smooth = false, 147 ScrollAlign align = ScrollAlign::START); 148 bool CheckTargetValid(int32_t index, int32_t indexInGroup); 149 bool ScrollPage(bool reverse); 150 void ScrollBy(float offset); 151 bool AnimateToTarget(int32_t index, std::optional<int32_t> indexInGroup, ScrollAlign align); 152 Offset GetCurrentOffset() const; 153 Rect GetItemRect(int32_t index) const override; 154 Rect GetItemRectInGroup(int32_t index, int32_t indexInGroup) const; 155 void OnAnimateStop() override; GetMainContentSize()156 float GetMainContentSize() const override 157 { 158 return contentMainSize_; 159 }; 160 161 void UpdateScrollBarOffset() override; 162 // chain animation 163 void SetChainAnimation(); 164 void SetChainAnimationOptions(const ChainAnimationOptions& options); 165 float FlushChainAnimation(float dragOffset); 166 void ProcessDragStart(float startPosition); 167 void ProcessDragUpdate(float dragOffset, int32_t source); 168 float GetChainDelta(int32_t index) const; 169 170 // multiSelectable SetMultiSelectable(bool multiSelectable)171 void SetMultiSelectable(bool multiSelectable) 172 { 173 multiSelectable_ = multiSelectable; 174 } 175 176 void SetSwiperItem(WeakPtr<ListItemPattern> swiperItem); SetSwiperItemEnd(WeakPtr<ListItemPattern> swiperItem)177 void SetSwiperItemEnd(WeakPtr<ListItemPattern> swiperItem) 178 { 179 if (swiperItem == swiperItem_) { 180 canReplaceSwiperItem_ = true; 181 } 182 } IsCurrentSwiperItem(WeakPtr<ListItemPattern> swiperItem)183 bool IsCurrentSwiperItem(WeakPtr<ListItemPattern> swiperItem) 184 { 185 if (!swiperItem_.Upgrade()) { 186 return true; 187 } 188 return swiperItem == swiperItem_; 189 } CanReplaceSwiperItem()190 bool CanReplaceSwiperItem() 191 { 192 if (!swiperItem_.Upgrade()) { 193 canReplaceSwiperItem_ = true; 194 } 195 return canReplaceSwiperItem_; 196 } 197 SetPredictSnapOffset(float predictSnapOffset)198 void SetPredictSnapOffset(float predictSnapOffset) 199 { 200 predictSnapOffset_ = predictSnapOffset; 201 } 202 bool OnScrollSnapCallback(double targetOffset, double velocity) override; 203 204 int32_t GetItemIndexByPosition(float xOffset, float yOffset); 205 SetPredictLayoutParam(std::optional<ListPredictLayoutParam> param)206 void SetPredictLayoutParam(std::optional<ListPredictLayoutParam> param) 207 { 208 predictLayoutParam_ = param; 209 } GetPredictLayoutParam()210 std::optional<ListPredictLayoutParam> GetPredictLayoutParam() const 211 { 212 return predictLayoutParam_; 213 } 214 215 void CloseAllSwipeActions(OnFinishFunc&&); 216 217 std::string ProvideRestoreInfo() override; 218 void OnRestoreInfo(const std::string& restoreInfo) override; 219 void DumpAdvanceInfo() override; 220 SetNeedToUpdateListDirectionInCardStyle(bool isNeedToUpdateListDirection)221 void SetNeedToUpdateListDirectionInCardStyle(bool isNeedToUpdateListDirection) 222 { 223 isNeedToUpdateListDirection_ = isNeedToUpdateListDirection; 224 } 225 IsNeedToUpdateListDirectionInCardStyle()226 bool IsNeedToUpdateListDirectionInCardStyle() const 227 { 228 return isNeedToUpdateListDirection_; 229 } 230 231 private: IsNeedInitClickEventRecorder()232 bool IsNeedInitClickEventRecorder() const override 233 { 234 return true; 235 } 236 237 void OnScrollEndCallback() override; 238 239 void OnModifyDone() override; 240 void ChangeAxis(RefPtr<UINode> node); 241 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 242 float CalculateTargetPos(float startPos, float endPos); 243 244 void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub); 245 bool OnKeyEvent(const KeyEvent& event); 246 bool HandleDirectionKey(const KeyEvent& event); 247 WeakPtr<FocusHub> GetNextFocusNode(FocusStep step, const WeakPtr<FocusHub>& currentFocusNode); 248 WeakPtr<FocusHub> GetChildFocusNodeByIndex(int32_t tarMainIndex, int32_t tarGroupIndex); 249 WeakPtr<FocusHub> ScrollAndFindFocusNode(int32_t nextIndex, int32_t curIndex, int32_t& nextIndexInGroup, 250 int32_t curIndexInGroup, int32_t moveStep, FocusStep step); 251 bool ScrollListForFocus(int32_t nextIndex, int32_t curIndex, int32_t nextIndexInGroup); 252 bool ScrollListItemGroupForFocus(int32_t nextIndex, int32_t& nextIndexInGroup, int32_t curIndexInGroup, 253 int32_t moveStep, FocusStep step, bool isScrollIndex); 254 255 void MarkDirtyNodeSelf(); 256 SizeF GetContentSize() const; 257 void ProcessEvent(bool indexChanged, float finalOffset, bool isJump, float prevStartOffset, float prevEndOffset); 258 void CheckScrollable(); 259 bool IsOutOfBoundary(bool useCurrentDelta = true) override; 260 bool OnScrollCallback(float offset, int32_t source) override; 261 void InitScrollableEvent(); 262 void SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect>& scrollEffect) override; 263 void HandleScrollEffect(float offset); 264 void CheckRestartSpring(bool sizeDiminished); 265 void StartDefaultOrCustomSpringMotion(float start, float end, const RefPtr<InterpolatingSpring>& curve); 266 void UpdateScrollSnap(); 267 bool IsScrollSnapAlignCenter() const; 268 void SetChainAnimationLayoutAlgorithm( 269 RefPtr<ListLayoutAlgorithm> listLayoutAlgorithm, RefPtr<ListLayoutProperty> listLayoutProperty); 270 bool NeedScrollSnapAlignEffect() const; 271 ScrollAlign GetScrollAlignByScrollSnapAlign() const; 272 bool GetListItemAnimatePos(float startPos, float endPos, ScrollAlign align, float& targetPos); 273 bool GetListItemGroupAnimatePosWithoutIndexInGroup(int32_t index, float startPos, float endPos, 274 ScrollAlign align, float& targetPos); 275 bool GetListItemGroupAnimatePosWithIndexInGroup(int32_t index, int32_t indexInGroup, float startPos, 276 ScrollAlign align, float& targetPos); 277 278 // multiSelectable 279 void ClearMultiSelect() override; 280 bool IsItemSelected(const GestureEvent& info) override; 281 void MultiSelectWithoutKeyboard(const RectF& selectedZone) override; 282 void HandleCardModeSelectedEvent( 283 const RectF& selectedZone, const RefPtr<FrameNode>& itemGroupNode, float itemGroupTop); 284 285 void DrivenRender(const RefPtr<LayoutWrapper>& layoutWrapper); 286 void SetAccessibilityAction(); 287 ListItemGroupPara GetListItemGroupParameter(const RefPtr<FrameNode>& node); 288 bool IsListItemGroup(int32_t listIndex, RefPtr<FrameNode>& node); 289 void GetListItemGroupEdge(bool& groupAtStart, bool& groupAtEnd) const; 290 void RefreshLanesItemRange(); 291 void UpdateListDirectionInCardStyle(); 292 RefPtr<ListContentModifier> listContentModifier_; 293 294 int32_t maxListItemIndex_ = 0; 295 int32_t startIndex_ = -1; 296 int32_t endIndex_ = -1; 297 int32_t centerIndex_ = -1; 298 float startMainPos_ = 0.0f; 299 float endMainPos_ = 0.0f; 300 float currentOffset_ = 0.0f; 301 float spaceWidth_ = 0.0f; 302 float contentMainSize_ = 0.0f; 303 float contentStartOffset_ = 0.0f; 304 float contentEndOffset_ = 0.0f; 305 306 float currentDelta_ = 0.0f; 307 bool crossMatchChild_ = false; 308 bool smooth_ = false; 309 float scrollSnapVelocity_ = 0.0f; 310 311 std::optional<int32_t> jumpIndex_; 312 std::optional<int32_t> jumpIndexInGroup_; 313 std::optional<int32_t> targetIndex_; 314 std::optional<int32_t> targetIndexInGroup_; 315 std::optional<float> predictSnapOffset_; 316 std::optional<float> predictSnapEndPos_; 317 ScrollAlign scrollAlign_ = ScrollAlign::START; 318 bool scrollable_ = true; 319 bool paintStateFlag_ = false; 320 bool isFramePaintStateValid_ = false; 321 bool isNeedCheckOffset_ = false; 322 323 ListLayoutAlgorithm::PositionMap itemPosition_; 324 325 std::map<int32_t, int32_t> lanesItemRange_; 326 int32_t lanes_ = 1; 327 float laneGutter_ = 0.0f; 328 // chain animation 329 RefPtr<ChainAnimation> chainAnimation_; 330 bool dragFromSpring_ = false; 331 RefPtr<SpringProperty> springProperty_; 332 std::optional<ChainAnimationOptions> chainAnimationOptions_; 333 334 bool isOritationListenerRegisted_ = false; 335 336 // ListItem swiperAction 337 WeakPtr<ListItemPattern> swiperItem_; 338 bool canReplaceSwiperItem_ = true; 339 340 RefPtr<SpringMotion> scrollToIndexMotion_; 341 RefPtr<SpringMotion> scrollSnapMotion_; 342 RefPtr<Scrollable> scrollableTouchEvent_; 343 344 bool isScrollEnd_ = false; 345 std::optional<ListPredictLayoutParam> predictLayoutParam_; 346 347 bool isNeedToUpdateListDirection_ = false; 348 349 bool endIndexChanged_ = false; 350 }; 351 } // namespace OHOS::Ace::NG 352 353 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_PATTERN_H 354