1 /* 2 * Copyright (c) 2021 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_LIST_RENDER_LIST_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_LIST_RENDER_LIST_H 18 19 #include <functional> 20 #include <map> 21 #include <vector> 22 23 #include "core/animation/simple_spring_chain.h" 24 #include "core/components/common/layout/constants.h" 25 #include "core/components/list/layout_manager.h" 26 #include "core/components/list/render_list_item.h" 27 #include "core/components/scroll/render_scroll.h" 28 #include "core/components/scroll/scrollable.h" 29 30 namespace OHOS::Ace { 31 32 class ListComponent; 33 34 constexpr int32_t INVALID_INDEX = -1; 35 constexpr int32_t ZERO_INDEX = 0; 36 37 using RotationEventFunc = std::function<void(const RotationEvent& info)>; 38 39 class RenderList : public RenderNode { 40 DECLARE_ACE_TYPE(RenderList, RenderNode); 41 42 public: 43 static RefPtr<RenderNode> Create(); 44 45 void Update(const RefPtr<Component>& component) override; 46 47 void UpdateTouchRect() override; 48 IsUseOnly()49 bool IsUseOnly() override 50 { 51 return true; 52 } 53 54 void PerformLayout() override; 55 56 void OnPaintFinish() override; 57 58 bool TouchTest(const Point& globalPoint, const Point& parentLocalPoint, const TouchRestrict& touchRestrict, 59 TouchTestResult& result) override; 60 61 void ResetLayoutRange(double head, double tail, Offset position, Size viewport); 62 63 using RequestListDataFunc = std::function<void(int32_t index, int32_t count)>; RegisterRequestItemsCallback(const RequestListDataFunc & requestItems)64 void RegisterRequestItemsCallback(const RequestListDataFunc& requestItems) 65 { 66 requestItems_ = requestItems; 67 } 68 69 using StickyItemBuildFunc = std::function<RefPtr<RenderNode>(int32_t index, bool next)>; RegisterStickyItemBuilderCallback(const StickyItemBuildFunc & stickyItemBuilder)70 void RegisterStickyItemBuilderCallback(const StickyItemBuildFunc& stickyItemBuilder) 71 { 72 stickyItemBuilder_ = stickyItemBuilder; 73 } 74 75 using StickyItemSearchFunc = std::function<int32_t(int32_t index)>; RegisterStickyItemSearcherCallback(const StickyItemSearchFunc & stickyItemSearcher)76 void RegisterStickyItemSearcherCallback(const StickyItemSearchFunc& stickyItemSearcher) 77 { 78 stickyItemSearcher_ = stickyItemSearcher; 79 } 80 81 using RecycleByRangeFunc = std::function<bool(int32_t& from, int32_t& to)>; RegisterRecycleByRangeCallback(const RecycleByRangeFunc & recycle)82 void RegisterRecycleByRangeCallback(const RecycleByRangeFunc& recycle) 83 { 84 recycleByRange_ = recycle; 85 } 86 87 using RecycleByItemsFunc = std::function<bool(const std::vector<int32_t>& items)>; RegisterRecycleByItemsCallback(const RecycleByItemsFunc & recycle)88 void RegisterRecycleByItemsCallback(const RecycleByItemsFunc& recycle) 89 { 90 recycleByItems_ = recycle; 91 } 92 93 using BuildListDataFunc = std::function<bool(int32_t index)>; RegisterBuildItemCallback(const BuildListDataFunc & buildItem)94 void RegisterBuildItemCallback(const BuildListDataFunc& buildItem) 95 { 96 buildItem_ = buildItem; 97 } 98 99 using OnRefreshedFunc = std::function<void()>; RegisterOnRefreshedCallback(const OnRefreshedFunc & onRefreshed)100 void RegisterOnRefreshedCallback(const OnRefreshedFunc& onRefreshed) 101 { 102 onRefreshed_ = onRefreshed; 103 } 104 105 void AddListItem(int32_t index, const RefPtr<RenderNode>& renderNode); 106 107 template<typename T> MakeValue(double mainValue,double crossValue)108 T MakeValue(double mainValue, double crossValue) const 109 { 110 return IsRowDirection() ? T(mainValue, crossValue) : T(crossValue, mainValue); 111 } 112 SetMainSize(Size & size,double mainValue)113 void SetMainSize(Size& size, double mainValue) 114 { 115 IsRowDirection() ? size.SetWidth(mainValue) : size.SetHeight(mainValue); 116 } 117 SetCrossSize(Size & size,double crossValue)118 void SetCrossSize(Size& size, double crossValue) 119 { 120 IsRowDirection() ? size.SetHeight(crossValue) : size.SetWidth(crossValue); 121 } 122 GetMainSize(const Size & size)123 double GetMainSize(const Size& size) const 124 { 125 return IsRowDirection() ? size.Width() : size.Height(); 126 } 127 GetCrossSize(const Size & size)128 double GetCrossSize(const Size& size) const 129 { 130 return IsRowDirection() ? size.Height() : size.Width(); 131 } 132 GetMainPosition(const Offset & offset)133 double GetMainPosition(const Offset& offset) const 134 { 135 return IsRowDirection() ? offset.GetX() : offset.GetY(); 136 } 137 IsRowDirection()138 bool IsRowDirection() const 139 { 140 return direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE; 141 } 142 IsLayoutChanged()143 bool IsLayoutChanged() const 144 { 145 return IsLayoutParamChanged(); 146 } 147 GetMaxCount()148 int32_t GetMaxCount() const 149 { 150 return maxCount_; 151 } 152 SetMaxCount(int32_t maxCount)153 void SetMaxCount(int32_t maxCount) 154 { 155 maxCount_ = maxCount; 156 } 157 GetCurrentMinIndex()158 int32_t GetCurrentMinIndex() const 159 { 160 int32_t currentMin = -1; 161 if (items_.begin() != items_.end()) { 162 currentMin = items_.begin()->first; 163 } 164 return currentMin; 165 } 166 GetCurrentMaxIndex()167 int32_t GetCurrentMaxIndex() const 168 { 169 int32_t currentMax = -1; 170 if (items_.rbegin() != items_.rend()) { 171 currentMax = items_.rbegin()->first; 172 } 173 return currentMax; 174 } 175 GetDirection()176 FlexDirection GetDirection() const 177 { 178 return direction_; 179 } 180 GetCachedCount()181 int32_t GetCachedCount() const 182 { 183 return cachedCount_; 184 } 185 GetBeginIndex()186 int32_t GetBeginIndex() const 187 { 188 return beginIndex_; 189 } 190 GetEndIndex()191 int32_t GetEndIndex() const 192 { 193 return endIndex_; 194 } 195 GetRepeatedLength()196 int32_t GetRepeatedLength() const 197 { 198 return repeatLength_; 199 } 200 GetLength()201 int32_t GetLength() const 202 { 203 return length_; 204 } 205 SetLength(int32_t length)206 void SetLength(int32_t length) 207 { 208 length_ = length; 209 } 210 GetIndexOffset()211 int32_t GetIndexOffset() const 212 { 213 return indexOffset_; 214 } 215 GetFlexAlign()216 FlexAlign GetFlexAlign() const 217 { 218 return crossAxisAlign_; 219 } 220 GetColumnCount()221 int32_t GetColumnCount() const 222 { 223 return columnCount_; 224 } 225 GetColumnExtent()226 int32_t GetColumnExtent() const 227 { 228 return columnExtent_; 229 } 230 GetWidth()231 double GetWidth() const 232 { 233 return listWidth_; 234 } 235 GetHeight()236 double GetHeight() const 237 { 238 return listHeight_; 239 } 240 GetItemExtent()241 const Dimension& GetItemExtent() const 242 { 243 return itemExtent_; 244 } 245 GetRightToLeft()246 bool GetRightToLeft() const 247 { 248 return rightToLeft_; 249 } 250 GetItems()251 const std::map<int32_t, RefPtr<RenderNode>>& GetItems() const 252 { 253 return items_; 254 } 255 ResetItems(std::map<int32_t,RefPtr<RenderNode>> & items)256 void ResetItems(std::map<int32_t, RefPtr<RenderNode>>& items) 257 { 258 items_.clear(); 259 items_.swap(items); 260 } 261 262 void CalculateStickyItem(const Offset& position); 263 264 void RequestMoreItems(int32_t index, int32_t count); 265 266 int32_t RequestNextFocus(bool vertical, bool reverse); 267 268 void ListItemFocused(int32_t focusIndex); 269 270 void MoveItemToViewPort(double position); 271 272 void MoveItemGroupToViewPort(double position, double size); 273 274 RefPtr<RenderListItem> GetItemByIndex(int32_t index); 275 276 RefPtr<RenderNode> GetChildByPosition(double position) const; 277 RefPtr<RenderNode> GetNearChildByPosition(double position) const; 278 RefPtr<RenderNode> FindChildByIndex(int32_t index); 279 RefPtr<RenderNode> GetChildByIndex(int32_t index); 280 int32_t GetIndexByPosition(double position) const; 281 bool RecycleByRange(int32_t from, int32_t to); 282 bool RecycleByItems(const std::vector<int32_t>& items); 283 bool RecycleAllChild(); 284 void RecycleHead(int32_t head); 285 void RecycleTail(int32_t tail); 286 void SyncIndex(int32_t begin, int32_t end); 287 288 void CalculateFocusIndexPosition(); 289 290 double CalculateItemPosition(int32_t index, ScrollType type); 291 292 void CalculateItemPosition(double targetPos); 293 294 void MarkNeedRefresh(); 295 296 void RefreshOffset(double offset); 297 298 void RefreshScrollExtent(); 299 300 void SetGroupState(int32_t index, bool expand); 301 OnRefreshed()302 void OnRefreshed() 303 { 304 onRefreshed_(); 305 } 306 GetLayoutManager()307 const RefPtr<LayoutManager>& GetLayoutManager() const 308 { 309 return layoutManager_; 310 } 311 GetItemPosition(int32_t index)312 double GetItemPosition(int32_t index) const 313 { 314 if (layoutManager_) { 315 return layoutManager_->GetItemPosition(index); 316 } 317 return 0.0; 318 } 319 GetItemAnimationPosition(int32_t index)320 double GetItemAnimationPosition(int32_t index) const 321 { 322 if (layoutManager_) { 323 return layoutManager_->GetItemAnimationValue(index); 324 } 325 return 0.0; 326 } 327 GetController()328 const RefPtr<ScrollPositionController>& GetController() const 329 { 330 return controller_; 331 } 332 IsSupportScale()333 bool IsSupportScale() const 334 { 335 return itemScale_; 336 } 337 SetSupportItemCenter(bool center)338 void SetSupportItemCenter(bool center) 339 { 340 supportItemCenter_ = center; 341 } 342 GetSupportItemCenter()343 bool GetSupportItemCenter() const 344 { 345 return supportItemCenter_; 346 } 347 SupportStickyItem()348 bool SupportStickyItem() const 349 { 350 return !chainAnimation_ && (direction_ == FlexDirection::COLUMN || direction_ == FlexDirection::COLUMN_REVERSE); 351 } 352 IsCenterLayout()353 bool IsCenterLayout() const 354 { 355 return isCenterLayout_; 356 } 357 IsPageReady()358 bool IsPageReady() const 359 { 360 return pageReady_; 361 } 362 GetAddDeleteEffect()363 bool GetAddDeleteEffect() const 364 { 365 return updateEffect_ && pageReady_; 366 } 367 SetAddDeleteEffect(bool enabled)368 void SetAddDeleteEffect(bool enabled) 369 { 370 updateEffect_ = enabled; 371 } 372 373 void BuildNextItem(double start, double end, Offset position, Size viewPort); 374 SetShiftHeight(double shiftHeight)375 void SetShiftHeight(double shiftHeight) 376 { 377 shiftHeight_ = shiftHeight; 378 } 379 380 // notify start position in global main axis 381 void NotifyDragStart(double startPosition); 382 383 // notify drag offset in global main axis 384 void NotifyDragUpdate(double dragOffset); 385 386 void NotifyScrollOver(double velocity, bool isCrashTop, bool isCrashBottom); 387 IsEnableChain()388 bool IsEnableChain() const 389 { 390 return chainAnimation_; 391 } 392 GetDragStartIndexPending()393 int32_t GetDragStartIndexPending() const 394 { 395 return dragStartIndexPending_; 396 } 397 SetDragStartIndexPending(int32_t index)398 void SetDragStartIndexPending(int32_t index) 399 { 400 dragStartIndexPending_ = index; 401 } 402 GetDragStartIndex()403 int32_t GetDragStartIndex() const 404 { 405 return dragStartIndex_; 406 } 407 SetDragStartIndex(int32_t index)408 void SetDragStartIndex(int32_t index) 409 { 410 dragStartIndex_ = index; 411 } 412 GetCurrentDelta()413 double GetCurrentDelta() const 414 { 415 return currentDelta_; 416 } 417 418 // Reset when performLayout done. ResetCurrentDelta()419 void ResetCurrentDelta() 420 { 421 currentDelta_ = 0.0; 422 } 423 GetOverSpringProperty()424 const RefPtr<SpringProperty>& GetOverSpringProperty() const 425 { 426 return overSpringProperty_; 427 } 428 GetChainProperty()429 const SpringChainProperty& GetChainProperty() const 430 { 431 return chainProperty_; 432 } 433 FlushChainAnimation()434 double FlushChainAnimation() 435 { 436 if (!layoutManager_) { 437 return 0.0; 438 } 439 return layoutManager_->FlushChainAnimation(); 440 } 441 GetHeadAnimationValue()442 double GetHeadAnimationValue() const 443 { 444 if (chainAnimation_ && layoutManager_) { 445 return layoutManager_->GetItemAnimationValue(GetCurrentMinIndex()); 446 } else { 447 return 0.0; 448 } 449 } 450 IsVertical()451 bool IsVertical() const 452 { 453 return direction_ == FlexDirection::COLUMN || direction_ == FlexDirection::COLUMN_REVERSE; 454 } 455 GetListPosition()456 double GetListPosition() const 457 { 458 if (layoutManager_) { 459 return IsVertical() ? layoutManager_->GetPosition().GetY() : layoutManager_->GetPosition().GetX(); 460 } 461 return 0.0; 462 } 463 EstimateIndexByPosition(double position)464 double EstimateIndexByPosition(double position) const 465 { 466 if (layoutManager_) { 467 return layoutManager_->GetIndexByPosition(position); 468 } 469 return INVALID_INDEX; 470 } 471 GetTailAnimationValue()472 double GetTailAnimationValue() const 473 { 474 if (chainAnimation_ && layoutManager_) { 475 return GetItemAnimationPosition(GetCurrentMaxIndex()); 476 } else { 477 return 0.0; 478 } 479 } 480 SetMakeCardTransition(bool makeCardTransition)481 void SetMakeCardTransition(bool makeCardTransition) 482 { 483 makeCardTransition_ = makeCardTransition; 484 } 485 GetCenterIndex()486 int32_t GetCenterIndex() const 487 { 488 return centerIndex_; 489 } 490 SetCenterIndex(int32_t centerIndex)491 void SetCenterIndex(int32_t centerIndex) 492 { 493 centerIndex_ = centerIndex; 494 } 495 NeedRefresh()496 bool NeedRefresh() const 497 { 498 return needRefresh_; 499 } 500 SetNeedRefresh(bool needRefresh)501 void SetNeedRefresh(bool needRefresh) 502 { 503 needRefresh_ = needRefresh; 504 } 505 506 void OnChildRemoved(const RefPtr<RenderNode>& child) override; 507 void SetOnRotateCallback(const RefPtr<ListComponent>& component); 508 GetOnRotateCallback()509 const RotationEventFunc& GetOnRotateCallback() const 510 { 511 return rotationEvent_; 512 } 513 514 protected: GetStickyItem()515 RefPtr<RenderNode> GetStickyItem() const 516 { 517 return stickyItem_; 518 } 519 GetStickyNext()520 RefPtr<RenderNode> GetStickyNext() const 521 { 522 return stickyNext_; 523 } 524 GetStickyItemOffset()525 Offset GetStickyItemOffset() const 526 { 527 return stickyItemOffset_; 528 } 529 GetStickyNextOffset()530 Offset GetStickyNextOffset() const 531 { 532 return stickyNextOffset_; 533 } 534 535 int32_t GetItemIndex(const RefPtr<RenderNode>& node); 536 void PaintItems(RenderContext& context, const Offset& offset); 537 538 double shiftHeight_ = 0.0; 539 bool makeCardTransition_ = false; 540 541 private: 542 double GetStickyMainSize(int32_t index); 543 void CalculateStickyItemOffset(int32_t index, double position); 544 void UpdateAccessibilityAttr(); 545 bool HandleActionScroll(bool forward); 546 void ResetGroupItem(const RefPtr<RenderNode>& renderNode); 547 548 FlexDirection direction_ { FlexDirection::COLUMN }; 549 FlexAlign crossAxisAlign_ = FlexAlign::STRETCH; 550 551 int32_t cachedCount_ = 1; 552 int32_t beginIndex_ = LIST_PARAM_INVAID; 553 int32_t endIndex_ = LIST_PARAM_INVAID; 554 int32_t repeatLength_ = 0; 555 int32_t length_ = 0; 556 int32_t indexOffset_ = 0; 557 int32_t maxCount_ = 0; 558 int32_t itemsCount_ = 0; 559 // center list-item index if item center option is enabled. 560 int32_t centerIndex_ = INVALID_INDEX; 561 562 double listWidth_ = -1.0; 563 double listHeight_ = -1.0; 564 double currentDelta_ = 0.0; 565 SpringChainProperty chainProperty_; 566 RefPtr<SpringProperty> overSpringProperty_; 567 int32_t dragStartIndexPending_ = 0; 568 int32_t dragStartIndex_ = 0; 569 int32_t columnCount_ = 0; 570 int32_t columnExtent_ = 0; 571 int32_t firstItemIndex_ = 0; 572 Dimension itemExtent_; 573 bool rightToLeft_ = false; 574 bool updateEffect_ = false; 575 bool supportItemCenter_ = false; 576 bool isCenterLayout_ = false; 577 bool pageReady_ = false; 578 bool itemScale_ = false; 579 bool chainAnimation_ = false; 580 bool needRefresh_ = false; 581 582 std::map<int32_t, RefPtr<RenderNode>> items_; 583 RequestListDataFunc requestItems_; 584 RecycleByRangeFunc recycleByRange_; 585 RecycleByItemsFunc recycleByItems_; 586 BuildListDataFunc buildItem_; 587 OnRefreshedFunc onRefreshed_; 588 RefPtr<ScrollPositionController> controller_; 589 RefPtr<LayoutManager> layoutManager_; 590 591 StickyItemBuildFunc stickyItemBuilder_; 592 StickyItemSearchFunc stickyItemSearcher_; 593 RefPtr<RenderNode> stickyItem_; 594 RefPtr<RenderNode> stickyNext_; 595 std::map<int32_t, double> stickyItemMap_; 596 Offset stickyItemOffset_; 597 Offset stickyNextOffset_; 598 Offset currentOffset_; 599 RotationEventFunc rotationEvent_; 600 }; 601 602 } // namespace OHOS::Ace 603 604 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_LIST_RENDER_LIST_H 605