1 /* 2 * Copyright (c) 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_NG_PATTERN_WATERFLOW_WATER_FLOW_LAYOUT_INFO_SW_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WATERFLOW_WATER_FLOW_LAYOUT_INFO_SW_H 18 19 #include <algorithm> 20 #include <deque> 21 #include <vector> 22 23 #include "core/components_ng/pattern/waterflow/layout/water_flow_layout_algorithm_base.h" 24 #include "core/components_ng/pattern/waterflow/layout/water_flow_layout_info_base.h" 25 26 namespace OHOS::Ace::NG { 27 constexpr int32_t EMPTY_NEW_START_INDEX = -1; 28 constexpr int32_t INVALID_NEW_START_INDEX = -2; 29 /** 30 * @brief Layout data structure for Sliding Window version of WaterFlowLayout 31 */ 32 class WaterFlowLayoutInfoSW : public WaterFlowLayoutInfoBase { 33 DECLARE_ACE_TYPE(WaterFlowLayoutInfoSW, WaterFlowLayoutInfoBase); 34 35 public: Mode()36 WaterFlowLayoutMode Mode() const override 37 { 38 return WaterFlowLayoutMode::SLIDING_WINDOW; 39 } 40 Offset()41 float Offset() const override 42 { 43 return totalOffset_; 44 } FirstIdx()45 int32_t FirstIdx() const override 46 { 47 return startIndex_; 48 } 49 UpdateOffset(float delta)50 void UpdateOffset(float delta) override 51 { 52 delta_ += delta; 53 synced_ = false; 54 } 55 56 float CalibrateOffset() override; 57 58 int32_t GetCrossIndex(int32_t itemIndex) const override; 59 60 OverScrollOffset GetOverScrolledDelta(float delta) const override; 61 62 float CalcOverScroll(float mainSize, float delta) const override; 63 64 bool ReachStart(float prevPos, bool firstLayout) const override; 65 66 bool ReachEnd(float prevPos, bool firstLayout) const override; 67 68 bool OutOfBounds() const override; 69 70 float GetContentHeight() const override; 71 72 float CalcTargetPosition(int32_t idx, int32_t crossIdx) const override; 73 GetDelta(float prevPos)74 float GetDelta(float prevPos) const override 75 { 76 return prevPos - totalOffset_; 77 } 78 79 int32_t GetMainCount() const override; GetCrossCount()80 int32_t GetCrossCount() const override 81 { 82 if (lanes_.empty()) { 83 return 0; 84 } 85 return lanes_[0].size(); 86 } 87 CurrentPos()88 float CurrentPos() const override 89 { 90 return 0.0f; 91 } 92 float TopFinalPos() const override; 93 float BottomFinalPos(float viewHeight) const override; 94 95 void Reset() override; 96 97 bool IsMisaligned() const override; 98 99 void InitSegments(const std::vector<WaterFlowSections::Section>& sections, int32_t start) override; 100 101 /** 102 * @brief reset layout data and setting up a base position for each lane. 103 * 104 * @param laneBasePos base value for lane's start&end position. 105 * When not provided, lane positions are not modified. 106 */ 107 void ResetWithLaneOffset(std::optional<float> laneBasePos); 108 BeginUpdate()109 void BeginUpdate() 110 { 111 synced_ = false; 112 } 113 /** 114 * @brief synchronize data after update is completed. 115 * 116 * @param itemCnt number of FlowItems. 117 * @param mainSize main-axis length of the viewport. 118 * @param mainGap main-axis gap between items. 119 */ 120 void Sync(int32_t itemCnt, float mainSize, const std::vector<float>& mainGap); 121 122 /** 123 * @brief Mark beginning of cache item layout and save current lanes_ state. 124 * 125 */ 126 void BeginCacheUpdate(); 127 /** 128 * @brief mark synced and restore lanes_ after cache item layout 129 */ 130 void EndCacheUpdate(); 131 132 /** 133 * @brief Calculates distance from the item's top edge to the top of the viewport. 134 * 135 * @param item index 136 * @return positive result when item's top edge is below viewport. 137 */ 138 float DistanceToTop(int32_t item, float mainGap) const; 139 140 /** 141 * @brief Calculates distance from the item's bottom edge to the bottom of the viewport. 142 * 143 * @param item index 144 * @param mainSize of the viewport 145 * @return positive result when item's bottom edge is above viewport. 146 */ 147 float DistanceToBottom(int32_t item, float mainSize, float mainGap) const; 148 149 int32_t StartIndex() const; 150 int32_t EndIndex() const; ItemInView(int32_t idx)151 inline bool ItemInView(int32_t idx) const 152 { 153 return !lanes_.empty() && idx >= StartIndex() && idx <= EndIndex(); 154 } 155 /** 156 * @param idx of the item. 157 * @return true the item is approximately within 1 full-viewport distance. 158 */ 159 bool ItemCloseToView(int32_t idx) const; 160 161 /** 162 * @return maximum end position of items in lanes_. 163 */ 164 float EndPos() const; EndPosWithMargin()165 inline float EndPosWithMargin() const 166 { 167 return EndPos() + BotMargin(); 168 } 169 /** 170 * @return minimum start position of items in lanes_. 171 */ 172 float StartPos() const; StartPosWithMargin()173 inline float StartPosWithMargin() const 174 { 175 return StartPos() - TopMargin(); 176 } 177 178 void ClearDataFrom(int32_t idx, const std::vector<float>& mainGap); 179 TopMargin()180 inline float TopMargin() const 181 { 182 if (margins_.empty()) { 183 return 0.0f; 184 } 185 return (axis_ == Axis::VERTICAL ? margins_.front().top : margins_.front().left).value_or(0.0f); 186 } BotMargin()187 inline float BotMargin() const 188 { 189 if (margins_.empty()) { 190 return 0.0f; 191 } 192 return (axis_ == Axis::VERTICAL ? margins_.back().bottom : margins_.back().right).value_or(0.0f); 193 } 194 195 /** 196 * @brief prepare lanes in the current section. 197 * 198 * @param idx current item index 199 * @param fillBack true if preparing in the forward direction (prevIdx < curIdx). 200 */ 201 void PrepareSectionPos(int32_t idx, bool fillBack); 202 203 void NotifyDataChange(int32_t index, int32_t count) override; 204 void UpdateLanesIndex(int32_t updateIdx); 205 void InitSegmentsForKeepPositionMode(const std::vector<WaterFlowSections::Section>& sections, 206 const std::vector<WaterFlowSections::Section>& prevSections, int32_t start) override; 207 208 struct Lane; 209 /** 210 * @brief Find item's corresponding Lane 211 */ 212 const Lane* GetLane(int32_t itemIdx) const; 213 Lane* GetMutableLane(int32_t itemIdx); 214 215 bool LaneOutOfBounds(size_t laneIdx, int32_t section) const; 216 217 /** 218 * @brief lanes in multiple sections. 219 * REQUIRES: In stable state (outside update phase), only items inside viewport are in lanes_. 220 */ 221 std::vector<std::vector<Lane>> lanes_; 222 /** 223 * @brief mapping of all items previously or currently in lanes_. 224 * REQUIRES: All items in lanes_ are in idxToLane_. 225 */ 226 std::unordered_map<int32_t, size_t> idxToLane_; 227 228 float delta_ = 0.0f; 229 /* Record total offset when continuously scrolling. No longer accurate after jump. Reset when reach top */ 230 float totalOffset_ = 0.0f; 231 232 std::vector<float> mainGap_; // update this at the end of a layout 233 234 // maximum content height encountered so far, mainly for comparing content and viewport height 235 float maxHeight_ = 0.0f; 236 float footerHeight_ = 0.0f; 237 238 // record the new startIndex_ after changing the datasource, corresponding to the old startIndex_. 239 int32_t newStartIndex_ = EMPTY_NEW_START_INDEX; 240 241 private: 242 inline void PrepareJump(); 243 244 void InitSegmentTails(const std::vector<WaterFlowSections::Section>& sections); 245 void InitLanes(const std::vector<WaterFlowSections::Section>& sections, int32_t start); 246 247 /** 248 * @brief prepare newStartIndex_ 249 * 250 * @return false if the value of newStartIndex_ is INVALID. 251 */ 252 bool PrepareNewStartIndex(); 253 254 /** 255 * @brief Adjust Lanes_ when the change happens in front of lane. 256 * 257 * @param sections the new sections after change. 258 * @param start segment index of the first change section. 259 * @param prevSegIdx segment index of original startIndex_ belongs to. 260 * 261 * @return true if adjust successfully. 262 */ 263 bool AdjustLanes(const std::vector<WaterFlowSections::Section>& sections, 264 const WaterFlowSections::Section& prevSection, int32_t start, int32_t prevSegIdx); 265 266 void ClearData(); 267 268 /** 269 * @brief Sync state when there has no items in lanes. 270 */ 271 void SyncOnEmptyLanes(); 272 273 std::unique_ptr<decltype(lanes_)> savedLanes_; // temporarily store current lanes_ state in Cache Item operations. 274 275 /* cache */ 276 float startPos_ = 0.0f; 277 float endPos_ = 0.0f; 278 279 bool synced_ = false; 280 281 struct ItemInfo; 282 }; 283 284 struct WaterFlowLayoutInfoSW::ItemInfo { 285 int32_t idx = -1; 286 float mainSize = 0.0f; 287 }; 288 289 struct WaterFlowLayoutInfoSW::Lane { 290 std::string ToString() const; 291 292 float startPos = 0.0f; 293 float endPos = 0.0f; 294 std::deque<ItemInfo> items_; 295 }; 296 } // namespace OHOS::Ace::NG 297 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WATERFLOW_WATER_FLOW_LAYOUT_INFO_SW_H 298