1 /* 2 * Copyright (c) 2021-2024 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_V2_LIST_RENDER_LIST_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_V2_LIST_RENDER_LIST_H 18 19 #include <functional> 20 #include <limits> 21 #include <list> 22 23 #include "core/animation/bilateral_spring_adapter.h" 24 #include "core/animation/simple_spring_chain.h" 25 #include "core/components/positioned/positioned_component.h" 26 #include "core/components/refresh/render_refresh_target.h" 27 #include "core/components/scroll/scroll_edge_effect.h" 28 #include "core/components/scroll/scrollable.h" 29 #include "core/components_v2/list/list_component.h" 30 #include "core/components_v2/list/render_list_item.h" 31 #include "core/components_v2/list/list_item_generator.h" 32 #include "core/gestures/raw_recognizer.h" 33 #include "core/pipeline/base/render_node.h" 34 35 namespace OHOS::Ace::V2 { 36 37 using UpdateBuilderFunc = std::function<void(const Dimension&, const Dimension&)>; 38 39 enum class ListEvents { 40 NONE = 0, 41 SCROLL, 42 SCROLL_STOP, 43 REACH_START, 44 REACH_END, 45 }; 46 47 enum class ItemPositionState { 48 AHEAD_OF_VIEWPORT = 0, 49 IN_VIEWPORT, 50 BEHIND_VIEWPORT, 51 }; 52 53 class RenderList : public RenderNode, public RenderRefreshTarget { 54 DECLARE_ACE_TYPE(V2::RenderList, RenderNode, RenderRefreshTarget); 55 56 public: 57 using ScrollEventBack = std::function<void(void)>; 58 static RefPtr<RenderNode> Create(); 59 60 RenderList() = default; 61 ~RenderList() override; 62 63 void Update(const RefPtr<Component>& component) override; 64 65 void PerformLayout() override; 66 67 void PaintChild(const RefPtr<RenderNode>& child, RenderContext& context, const Offset& offset) override; 68 69 void OnPaintFinish() override; 70 71 bool IsUseOnly() override; 72 73 template<class T> MakeValue(double mainValue,double crossValue)74 T MakeValue(double mainValue, double crossValue) const 75 { 76 return vertical_ ? T(crossValue, mainValue) : T(mainValue, crossValue); 77 } 78 GetMainSize(const Size & size)79 double GetMainSize(const Size& size) const 80 { 81 return vertical_ ? size.Height() : size.Width(); 82 } 83 GetCrossSize(const Size & size)84 double GetCrossSize(const Size& size) const 85 { 86 return vertical_ ? size.Width() : size.Height(); 87 } 88 GetMainAxis(const Offset & size)89 double GetMainAxis(const Offset& size) const 90 { 91 return vertical_ ? size.GetY() : size.GetX(); 92 } 93 GetCrossAxis(const Offset & size)94 double GetCrossAxis(const Offset& size) const 95 { 96 return vertical_ ? size.GetX() : size.GetY(); 97 } 98 GetSpace()99 double GetSpace() const 100 { 101 return spaceWidth_; 102 } 103 GetStartIndex()104 double GetStartIndex() const 105 { 106 return startIndex_; 107 } 108 GetIndex()109 double GetIndex() const 110 { 111 return initialIndex_; 112 } 113 IsVertical()114 bool IsVertical() const 115 { 116 return vertical_; 117 } 118 GetAxis()119 Axis GetAxis() const 120 { 121 return vertical_ ? Axis::VERTICAL : Axis::HORIZONTAL; 122 } 123 GetEditable()124 bool GetEditable() const 125 { 126 if (component_) { 127 return component_->GetEditMode(); 128 } 129 return false; 130 } 131 GetLinkage()132 bool GetLinkage() const 133 { 134 if (component_) { 135 return component_->GetChainAnimation(); 136 } 137 return false; 138 } 139 RegisterItemGenerator(WeakPtr<ListItemGenerator> && listItemGenerator)140 void RegisterItemGenerator(WeakPtr<ListItemGenerator>&& listItemGenerator) 141 { 142 itemGenerator_ = std::move(listItemGenerator); 143 } 144 GetRestoreId()145 int32_t GetRestoreId() const 146 { 147 return component_ ? component_->GetRestoreId() : -1; 148 } 149 GetMultiSelectable()150 bool GetMultiSelectable() const 151 { 152 return isMultiSelectable_; 153 } 154 155 void RemoveAllItems(); 156 157 void JumpToIndex(int32_t idx); 158 159 void AnimateTo(const Dimension& position, float duration, const RefPtr<Curve>& curve); 160 161 void ScrollToEdge(ScrollEdgeType scrollEdgeType, bool smooth); 162 163 void ScrollPage(bool reverse, bool smooth); 164 165 void ScrollBy(double pixelX, double pixelY); 166 GetComponent()167 RefPtr<Component> GetComponent() override 168 { 169 return component_; 170 } 171 GetCurrentOffset()172 Offset GetCurrentOffset() const 173 { 174 return vertical_ ? Offset(0.0, -currentOffset_) : Offset(-currentOffset_, 0.0); 175 } 176 GetRealMainSize()177 double GetRealMainSize() const 178 { 179 return realMainSize_; 180 } 181 GetEstimatedHeight()182 double GetEstimatedHeight() const 183 { 184 return estimatedHeight_; 185 } 186 GetLastOffset()187 Offset GetLastOffset() const 188 { 189 return vertical_ ? Offset(0.0, lastOffset_) : Offset(lastOffset_, 0.0); 190 } 191 192 Offset CurrentOffset(); 193 GetListSpace()194 Dimension GetListSpace() const 195 { 196 return listSpace_; 197 } 198 GetUpdateBuilderFuncId()199 const UpdateBuilderFunc& GetUpdateBuilderFuncId() const 200 { 201 return updateBuilder_; 202 } 203 SetUpdateBuilderFuncId(const UpdateBuilderFunc & updateBuilder)204 void SetUpdateBuilderFuncId(const UpdateBuilderFunc& updateBuilder) 205 { 206 updateBuilder_ = updateBuilder; 207 } 208 GetOnItemDragEnter()209 const OnItemDragEnterFunc& GetOnItemDragEnter() const 210 { 211 return onItemDragEnter_; 212 } 213 GetOnItemDragMove()214 const OnItemDragMoveFunc& GetOnItemDragMove() const 215 { 216 return onItemDragMove_; 217 } 218 GetOnItemDragLeave()219 const OnItemDragLeaveFunc& GetOnItemDragLeave() const 220 { 221 return onItemDragLeave_; 222 } 223 GetOnItemDrop()224 const OnItemDropFunc& GetOnItemDrop() const 225 { 226 return onItemDrop_; 227 } 228 SetPreTargetRenderList(const RefPtr<RenderList> & preTargetRenderList)229 void SetPreTargetRenderList(const RefPtr<RenderList>& preTargetRenderList) 230 { 231 preTargetRenderList_ = preTargetRenderList; 232 } 233 GetPreTargetRenderList()234 const RefPtr<RenderList>& GetPreTargetRenderList() const 235 { 236 return preTargetRenderList_; 237 } 238 SetBetweenItemAndBuilder(const Offset & betweenItemAndBuilder)239 void SetBetweenItemAndBuilder(const Offset& betweenItemAndBuilder) 240 { 241 betweenItemAndBuilder_ = betweenItemAndBuilder; 242 } 243 GetBetweenItemAndBuilder()244 const Offset& GetBetweenItemAndBuilder() const 245 { 246 return betweenItemAndBuilder_; 247 } 248 249 size_t CalculateSelectedIndex( 250 const RefPtr<RenderList> targetRenderlist, const GestureEvent& info, Size& selectedItemSize); 251 int32_t CalculateInsertIndex( 252 const RefPtr<RenderList> targetRenderlist, const GestureEvent& info, Size selectedItemSize); 253 254 void HandleAxisEvent(const AxisEvent& event) override; 255 256 bool IsAxisScrollable(AxisDirection direction) override; 257 258 int32_t RequestNextFocus(bool vertical, bool reverse); 259 260 // distribute 261 std::string ProvideRestoreInfo() override; 262 SetFocusIndex(int32_t focusIndex)263 void SetFocusIndex(int32_t focusIndex) 264 { 265 focusIndex_ = focusIndex; 266 } 267 GetLanes()268 int32_t GetLanes() const 269 { 270 return lanes_; 271 } 272 IsFramePaintStateValid()273 bool IsFramePaintStateValid() const 274 { 275 return isFramePaintStateValid_; 276 } 277 MarkFramePaintStateValid(bool isValid)278 void MarkFramePaintStateValid(bool isValid) 279 { 280 isFramePaintStateValid_ = isValid; 281 } 282 GetPaintState()283 bool GetPaintState() const 284 { 285 return paintStateFlag_; 286 } 287 SetPaintState(bool flag)288 void SetPaintState(bool flag) 289 { 290 paintStateFlag_ = flag; 291 MarkFramePaintStateValid(true); 292 } 293 294 protected: 295 void UpdateAccessibilityAttr(); 296 void UpdateAccessibilityScrollAttr(); 297 void UpdateAccessibilityVisible(); 298 bool HandleActionScroll(bool forward); 299 LayoutParam MakeInnerLayout(); 300 LayoutParam MakeInnerLayoutForLane(); 301 Size SetItemsPosition(double mainSize); 302 Size SetItemsPositionForLaneList(double mainSize); 303 bool HandleOverScroll(); 304 bool UpdateScrollPosition(double offset, int32_t source); 305 306 bool TouchTest(const Point& globalPoint, const Point& parentLocalPoint, const TouchRestrict& touchRestrict, 307 TouchTestResult& result) override; 308 void OnTouchTestHit( 309 const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result) override; 310 311 double ApplyLayoutParam(); 312 double LayoutOrRecycleCurrentItems(double mainSize); 313 void BackwardLayoutForCache(size_t& backwardLayoutIndex, double& backwardLayoutOffset); 314 double LayoutOrRecycleCurrentItemsForCache(double mainSize); 315 double LayoutOrRecycleCurrentItemsForLaneList(double mainSize); 316 RefPtr<RenderListItem> RequestAndLayoutNewItem(size_t index, double currMainPos, bool forward = true); 317 318 RefPtr<RenderListItem> RequestListItem(size_t index); 319 void RecycleListItem(size_t index); 320 size_t FindItemStartIndex(size_t index); 321 size_t GetItemRelativeIndex(size_t index); 322 size_t TotalCount(); 323 size_t FindPreviousStickyListItem(size_t index); 324 325 void OnItemDelete(const RefPtr<RenderListItem>& item); 326 void OnItemSelect(const RefPtr<RenderListItem>& item); 327 size_t GetIndexByListItem(const RefPtr<RenderListItem>& item) const; 328 bool PrepareRawRecognizer(); 329 void OnSelectedItemMove(double position); 330 void OnSelectedItemStopMoving(bool canceled); 331 332 void UpdateStickyListItem(const RefPtr<RenderListItem>& newStickyItem, size_t newStickyItemIndex, 333 const RefPtr<RenderListItem>& nextStickyItem); 334 335 void ApplyPreviousStickyListItem(size_t index, bool forceLayout = false); 336 337 double GetCurrentPosition() const; 338 void AdjustOffset(Offset& delta, int32_t source); 339 bool IsOutOfBoundary() const; 340 void ResetEdgeEffect(); 341 void SetEdgeEffectAttribute(); 342 void CalculateMainScrollExtent(double curMainPos, double mainSize); 343 bool GetCurMainPosAndMainSize(double &curMainPos, double &mainSize); 344 345 // notify start position in global main axis when drag start 346 void ProcessDragStart(double startPosition); 347 // notify drag offset in global main axis 348 void ProcessDragUpdate(double dragOffset); 349 // notify scroll over 350 void ProcessScrollOverCallback(double velocity); 351 void InitChainAnimation(int32_t nodeCount); 352 double GetChainDelta(int32_t index) const; 353 size_t GetNearChildByPosition(double mainOffset) const; 354 double FlushChainAnimation(); GetOverSpringProperty()355 const RefPtr<SpringProperty>& GetOverSpringProperty() const 356 { 357 return overSpringProperty_; 358 } GetChainProperty()359 const SpringChainProperty& GetChainProperty() const 360 { 361 return chainProperty_; 362 } 363 void CalculateLanes(); 364 void ModifyLaneLength(const std::optional<std::pair<Dimension, Dimension>>& laneConstrain); 365 ItemPositionState GetItemPositionState(double curMainPos, double lastItemMainSize); 366 double GetLaneLengthInPx(const Dimension& length); 367 double CalculateLaneCrossOffset(double crossSize, double childCrossSize); 368 void RequestNewItemsAtEnd(double& curMainPos, double mainSize); 369 void RequestNewItemsAtEndForLaneList(double& curMainPos, double mainSize); 370 void RequestNewItemsAtStart(); 371 void RequestNewItemsAtStartForLaneList(); 372 373 RefPtr<ListComponent> component_; 374 375 static constexpr size_t INVALID_CHILD_INDEX = std::numeric_limits<size_t>::max(); 376 static constexpr size_t INITIAL_CHILD_INDEX = INVALID_CHILD_INDEX - 1; 377 378 size_t startIndex_ = INITIAL_CHILD_INDEX; 379 size_t initialIndex_ = INITIAL_CHILD_INDEX; 380 std::list<RefPtr<RenderListItem>> items_; 381 382 int32_t midDisplayIndex_ = 0; 383 double spaceWidth_ = 0.0; 384 double lastOffset_ = 0.0; 385 double startIndexOffset_ = 0.0; 386 double startMainPos_ = 0.0; 387 double endMainPos_ = 0.0; 388 double currentOffset_ = 0.0; 389 double mainSize_ = 0.0; 390 double mainScrollExtent_ = 0.0; 391 392 bool useEstimateCurrentOffset_ = false; 393 bool reachStart_ = false; 394 bool reachEnd_ = false; 395 bool isOutOfBoundary_ = false; 396 bool vertical_ = true; 397 bool fixedMainSizeByLayoutParam_ = true; 398 bool fixedMainSize_ = true; 399 bool fixedCrossSize_ = false; 400 bool chainAnimation_ = false; 401 bool chainOverScroll_ = false; 402 double currentDelta_ = 0.0; 403 bool inLinkRefresh_ = false; 404 405 SpringChainProperty chainProperty_; 406 RefPtr<SpringProperty> overSpringProperty_; 407 RefPtr<BilateralSpringAdapter> chainAdapter_; 408 RefPtr<SimpleSpringChain> chain_; 409 RefPtr<Animator> animator_; 410 411 size_t firstDisplayIndex_ = INITIAL_CHILD_INDEX; 412 size_t lastDisplayIndex_ = INITIAL_CHILD_INDEX; 413 size_t dragStartIndexPending_ = 0; 414 size_t dragStartIndex_ = 0; 415 bool hasActionScroll_ = false; 416 bool isActionByScroll_ = false; 417 ScrollEventBack scrollFinishEventBack_; 418 419 WeakPtr<ListItemGenerator> itemGenerator_; 420 RefPtr<Scrollable> scrollable_; 421 RefPtr<ScrollEdgeEffect> scrollEffect_; 422 RefPtr<ScrollBarProxy> scrollBarProxy_; // user defined scroll bar 423 RefPtr<ScrollBar> scrollBar_; // system defined scroll bar 424 425 size_t currentStickyIndex_ = INITIAL_CHILD_INDEX; 426 RefPtr<RenderListItem> currentStickyItem_; 427 428 size_t targetIndex_ = INITIAL_CHILD_INDEX; 429 size_t selectedItemIndex_ = INITIAL_CHILD_INDEX; 430 RefPtr<RenderListItem> selectedItem_; 431 double selectedItemMainAxis_ = 0.0; 432 double targetMainAxis_ = 0.0; 433 RefPtr<RawRecognizer> rawRecognizer_; 434 double lastPos_ = 0.0f; 435 bool autoScrollingForItemMove_ = false; 436 bool movingForward_ = false; 437 double dipScale_ = 1.0; 438 double offset_ = 0.0; 439 440 size_t insertItemIndex_ = INITIAL_CHILD_INDEX; 441 Offset betweenItemAndBuilder_; 442 RefPtr<RenderListItem> selectedDragItem_; 443 444 Offset mouseStartOffset_; 445 Offset mouseEndOffset_; 446 int32_t focusIndex_ = 0; 447 int32_t scrollBarOpacity_ = 0; 448 double prevOffset_ = 0.0; 449 double prevMainPos_ = 0.0; 450 double estimatedHeight_ = 0.0; 451 bool isRightToLeft_ = false; 452 bool drivenRender_ = false; 453 454 private: 455 int32_t lanes_ = -1; 456 double minLaneLength_ = -1.0; // in vertical list, [minLaneLength_] means the minimum width of a lane 457 double maxLaneLength_ = -1.0; // in vertical list, [maxLaneLength_] means the maximum width of a lane 458 bool isLaneList_ = false; 459 bool IsReachStart(); 460 void HandleListEvent(); 461 bool ActionByScroll(bool forward, ScrollEventBack scrollEventBack); 462 void ModifyActionScroll(); 463 void InitScrollBarProxy(); 464 void InitScrollBar(); 465 void SetScrollBarCallback(); 466 void LayoutChild(RefPtr<RenderNode> child, double referencePos = 0.0, bool forward = true); 467 static void SetChildPosition(RefPtr<RenderNode> child, const Offset& offset); 468 void AddChildItem(RefPtr<RenderNode> child); 469 void AdjustForReachEnd(double mainSize, double curMainPos); 470 void AdjustForReachStart(double &curMainPos); 471 Dimension listSpace_; 472 double realMainSize_ = 0.0; // Real size of main axis. 473 size_t startCachedCount_ = 0; 474 size_t endCachedCount_ = 0; 475 size_t cachedCount_ = 0; 476 StickyStyle sticky_ = StickyStyle::NONE; 477 478 void CreateDragDropRecognizer(); 479 RefPtr<RenderListItem> FindCurrentListItem(const Point& point); 480 481 RefPtr<GestureRecognizer> dragDropGesture_; 482 RefPtr<RenderList> preTargetRenderList_; 483 OnItemDragStartFunc onItemDragStart_; 484 OnItemDragEnterFunc onItemDragEnter_; 485 OnItemDragMoveFunc onItemDragMove_; 486 OnItemDragLeaveFunc onItemDragLeave_; 487 OnItemDropFunc onItemDrop_; 488 489 UpdateBuilderFunc updateBuilder_; 490 491 bool HandleMouseEvent(const MouseEvent& event) override; 492 bool isMultiSelectable_ = false; 493 bool forbidMultiSelect_ = false; 494 void ClearMultiSelect(); 495 bool mouseIsHover_ = false; 496 bool hasHeight_ = false; 497 bool hasWidth_ = false; 498 bool isAxisResponse_ = true; 499 ScrollState scrollState_; 500 bool paintStateFlag_ = false; 501 bool isFramePaintStateValid_ = false; 502 503 void MultiSelectWithoutKeyboard(const Rect& selectedZone); 504 void HandleMouseEventWithoutKeyboard(const MouseEvent& event); 505 506 void MultiSelectWhenCtrlDown(const Rect& selectedZone); 507 void HandleMouseEventWhenCtrlDown(const MouseEvent& event); 508 void CollectSelectedItems(); 509 std::set<RefPtr<RenderListItem>> selectedItemsWithCtrl_; 510 511 void MultiSelectWhenShiftDown(const Rect& selectedZone); 512 RefPtr<RenderListItem> GetPressItemWhenShiftDown(const Rect& selectedZone); 513 void HandleMouseEventWhenShiftDown(const MouseEvent& event); 514 void MultiSelectAllInRange(const RefPtr<RenderListItem>& firstItem, const RefPtr<RenderListItem>& secondItem); 515 RefPtr<RenderListItem> firstItemWithShift_; 516 RefPtr<RenderListItem> secondItemWithShift_; 517 518 void MultiSelectAllWhenCtrlA(); 519 520 // distribute 521 void ApplyRestoreInfo(); 522 523 void InitScrollable(Axis axis); 524 525 // when window size change, add offset to keep clicked textfield in display area 526 void SizeChangeOffset(double newWindowHeight); 527 528 bool hasDragItem_ = false; 529 std::map<ListEvents, bool> listEventFlags_; 530 531 ACE_DISALLOW_COPY_AND_MOVE(RenderList); 532 }; 533 534 } // namespace OHOS::Ace::V2 535 536 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_V2_LIST_RENDER_LIST_H 537