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