1 /* 2 * Copyright (c) 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_PATTERN_WATERFLOW_WATER_FLOW_LAYOUT_INFO_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WATERFLOW_WATER_FLOW_LAYOUT_INFO_H 18 19 #include <cstdint> 20 #include <map> 21 #include <optional> 22 #include <sstream> 23 24 #include "core/components_ng/pattern/waterflow/layout/water_flow_layout_algorithm_base.h" 25 #include "core/components_ng/pattern/waterflow/layout/water_flow_layout_info_base.h" 26 #include "core/components_ng/pattern/waterflow/water_flow_sections.h" 27 28 namespace OHOS::Ace::NG { 29 struct FlowItemIndex { 30 int32_t crossIndex = 0; 31 int32_t lastItemIndex = 0; 32 }; 33 34 struct FlowItemPosition { 35 int32_t crossIndex = 0; 36 float startMainPos = 0; 37 }; 38 39 class WaterFlowLayoutInfo : public WaterFlowLayoutInfoBase { 40 DECLARE_ACE_TYPE(WaterFlowLayoutInfo, WaterFlowLayoutInfoBase); 41 42 public: 43 WaterFlowLayoutInfo() = default; 44 ~WaterFlowLayoutInfo() override = default; 45 Mode()46 WaterFlowLayoutMode Mode() const override 47 { 48 return WaterFlowLayoutMode::TOP_DOWN; 49 } Offset()50 float Offset() const override 51 { 52 return currentOffset_; 53 } FirstIdx()54 int32_t FirstIdx() const override 55 { 56 return firstIndex_; 57 } 58 int32_t GetCrossIndex(int32_t itemIndex) const override; 59 60 void UpdateStartIndex() override; 61 int32_t GetEndIndexByOffset(float offset) const; 62 float GetMaxMainHeight() const; 63 float GetContentHeight() const override; 64 float EstimateContentHeight() const; 65 bool IsAllCrossReachEnd(float mainSize) const; 66 67 /** 68 * @brief Get the next available cross index to place a new item. 69 * 70 * @param segmentIdx index of the WaterFlow segment. 71 * @return FlowItemIndex 72 */ 73 FlowItemIndex GetCrossIndexForNextItem(int32_t segmentIdx) const; 74 75 float GetMainHeight(int32_t crossIndex, int32_t itemIndex) const; 76 float GetStartMainPos(int32_t crossIndex, int32_t itemIndex) const; 77 void Reset() override; 78 void Reset(int32_t resetFrom); 79 int32_t GetCrossCount() const override; 80 int32_t GetMainCount() const override; 81 void ClearCacheAfterIndex(int32_t currentIndex); 82 83 bool ReachStart(float prevOffset, bool firstLayout) const override; 84 bool ReachEnd(float prevOffset, bool firstLayout) const override; 85 bool OutOfBounds() const override; 86 87 OverScrollOffset GetOverScrolledDelta(float delta) const override; 88 float CalcOverScroll(float mainSize, float delta) const override; 89 90 void UpdateOffset(float delta) override; 91 CalibrateOffset()92 float CalibrateOffset() override 93 { 94 /* offset always accurate */ 95 return 0.0f; 96 } 97 98 float CalcTargetPosition(int32_t idx, int32_t crossIdx) const override; 99 GetDelta(float prevPos)100 float GetDelta(float prevPos) const override 101 { 102 return prevPos - currentOffset_; 103 } 104 CurrentPos()105 float CurrentPos() const override 106 { 107 return currentOffset_; 108 } TopFinalPos()109 float TopFinalPos() const override 110 { 111 return 0.0f; 112 }; BottomFinalPos(float viewHeight)113 float BottomFinalPos(float viewHeight) const override 114 { 115 float endOffset = viewHeight - GetContentHeight(); 116 return Negative(endOffset) ? endOffset : 0.0f; 117 }; 118 119 float JumpToTargetAlign(const std::pair<float, float>& item) const; 120 void JumpTo(const std::pair<float, float>& item); 121 IsMisaligned()122 bool IsMisaligned() const override 123 { 124 return false; 125 } 126 127 /** 128 * @brief Init data structures based on new WaterFlow Sections. 129 * 130 * @param sections vector of Sections info. 131 * @param start index of the first modified section, all sections prior to [start] remain the same. 132 */ 133 void InitSegments(const std::vector<WaterFlowSections::Section>& sections, int32_t start) override; 134 135 // set up startPos of next segment after initializing margins_ 136 void PrepareSegmentStartPos(); 137 138 void ResetSegmentStartPos(); 139 140 /** 141 * @brief Record a new FlowItem in ItemMap and update related data structures. 142 * 143 * @param idx index of FlowItem. 144 * @param pos position of this FlowItem 145 * @param height FlowItem height. 146 */ 147 void RecordItem(int32_t idx, const FlowItemPosition& pos, float height); 148 149 /** 150 * @brief FInd the first item inside viewport in log_n time using endPosReverseMap_. 151 * 152 * @return index of the starting item. 153 */ 154 int32_t FastSolveStartIndex() const; 155 156 /** 157 * @brief Find the last item inside viewport in log_n time using itemInfos_. 158 * 159 * @param mainSize main-axis length of viewport. 160 * @return index of the item. 161 */ 162 int32_t FastSolveEndIndex(float mainSize) const; 163 164 /** 165 * @brief Calculate and set the start position of next segment after filling the tail item of the current segment. 166 * 167 * @param itemIdx index of the current flow item. 168 */ 169 void SetNextSegmentStartPos(int32_t itemIdx); 170 171 /** 172 * @brief Update member variables after measure. 173 * 174 * @param mainSize waterFlow length on the main axis. 175 * @param overScroll whether overScroll is allowed. Might adjust offset if not. 176 */ 177 void Sync(float mainSize, bool overScroll); 178 179 /** 180 * @brief Obtain index of last item recorded in Original layout. 181 * @note in segmented layout, use itemInfos_ instead. 182 */ 183 int32_t GetLastItem() const; 184 NotifyDataChange(int32_t index,int32_t count)185 void NotifyDataChange(int32_t index, int32_t count) override {}; InitSegmentsForKeepPositionMode(const std::vector<WaterFlowSections::Section> & sections,const std::vector<WaterFlowSections::Section> & prevSections,int32_t start)186 void InitSegmentsForKeepPositionMode(const std::vector<WaterFlowSections::Section>& sections, 187 const std::vector<WaterFlowSections::Section>& prevSections, int32_t start) override 188 {} 189 190 int32_t childrenCount_ = 0; 191 192 float currentOffset_ = 0.0f; 193 // 0.0f until itemEnd_ is true 194 float maxHeight_ = 0.0f; 195 196 // first index for onScrollIndex 197 int32_t firstIndex_ = 0; 198 199 // Map structure: [crossIndex, [index, {mainOffset, itemMainSize}]], 200 using ItemMap = std::map<int32_t, std::map<int32_t, std::pair<float, float>>>; 201 202 std::vector<ItemMap> items_ { ItemMap() }; 203 204 struct ItemInfo; 205 // quick access to FlowItem by index 206 std::vector<ItemInfo> itemInfos_; 207 208 /** 209 * @brief pair = { item bottom position, item index }. 210 * A strictly increasing array of item endPos to speed up startIndex solver. 211 * Only add to this map when a new endPos is greater than the last one in array. 212 */ 213 std::vector<std::pair<float, int32_t>> endPosArray_; 214 215 // Stores the start position of each segment. 216 std::vector<float> segmentStartPos_ = { 0.0f }; 217 218 void PrintWaterFlowItems() const; 219 }; 220 221 struct WaterFlowLayoutInfo::ItemInfo { 222 ItemInfo() = default; ItemInfoItemInfo223 ItemInfo(int32_t cross, float offset, float size) : crossIdx(cross), mainOffset(offset), mainSize(size) {} 224 bool operator==(const ItemInfo& other) const 225 { 226 return crossIdx == other.crossIdx && mainOffset == other.mainOffset && mainSize == other.mainSize; 227 } 228 229 int32_t crossIdx = 0; 230 float mainOffset = 0.0f; 231 float mainSize = 0.0f; 232 }; 233 234 } // namespace OHOS::Ace::NG 235 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WATERFLOW_WATER_FLOW_LAYOUT_INFO_H 236