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_LAYOUT_MANAGER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_LIST_LAYOUT_MANAGER_H 18 19 #include <map> 20 21 #include "base/geometry/dimension.h" 22 #include "base/geometry/offset.h" 23 #include "base/memory/ace_type.h" 24 #include "base/utils/system_properties.h" 25 #include "core/event/touch_event.h" 26 #include "core/pipeline/base/component.h" 27 #include "core/pipeline/base/render_node.h" 28 29 namespace OHOS::Ace { 30 31 const double DEFAULT_SCALE = 1.0; 32 const double TV_ITEM_SCALE = 1.05; 33 const double HALF_ITEM_SIZE = 0.5; 34 const int32_t LIST_PARAM_INVAID = -2; 35 const int32_t LIST_LENGTH_INFINITE = -1; 36 const double INFINITE_POSITION = 0.0; 37 38 // first bool mean if vertical, second bool mean if reverse 39 // false, false --> RIGHT 40 // false, true --> LEFT 41 // true, false --> DOWN 42 // true, true ---> UP 43 // This map will adapter the Grid FlexDirection with Key Direction. 44 extern const std::map<bool, std::map<FlexDirection, std::map<bool, std::map<bool, KeyDirection>>>> DIRECTION_MAP; 45 46 class LayoutManager : public virtual AceType { 47 DECLARE_ACE_TYPE(LayoutManager, AceType); 48 49 public: 50 LayoutManager() = default; 51 ~LayoutManager() override = default; 52 53 virtual void Update() = 0; 54 55 virtual void PerformLayout() = 0; 56 57 virtual void RefreshLayout() = 0; 58 59 virtual void CalculateCachedRange(int32_t viewBegin, int32_t viewEnd, int32_t cachedCount, int32_t& cachedBegin, 60 int32_t& cachedEnd) = 0; 61 62 virtual void RequestMoreItemsIfNeeded(int32_t viewBegin, int32_t viewEnd) = 0; 63 64 virtual int32_t focusMove(KeyDirection key) = 0; 65 CalculateFocusIndexPosition()66 virtual void CalculateFocusIndexPosition() {} 67 MoveItemToViewPort(double position)68 virtual void MoveItemToViewPort(double position) {} 69 MoveItemGroupToViewPort(double position,double size)70 virtual void MoveItemGroupToViewPort(double position, double size) {} 71 LayoutToItem(int32_t toIndex)72 virtual void LayoutToItem(int32_t toIndex) {} 73 LayoutToPosition(double position)74 virtual void LayoutToPosition(double position) {} 75 LayoutMore(double incDistance)76 virtual void LayoutMore(double incDistance) {} 77 NotifyNeedRefresh()78 virtual void NotifyNeedRefresh() {} 79 RequestNextFocus(bool vertical,bool reverse)80 int32_t RequestNextFocus(bool vertical, bool reverse) 81 { 82 KeyDirection key = DIRECTION_MAP.at(rightToLeft_).at(direction_).at(vertical).at(reverse); 83 int32_t index = focusMove(key); 84 if (index < 0) { 85 focusMove_ = focusIndex_; 86 return index; 87 } 88 focusMove_ = index; 89 focusIndex_ = index; 90 return focusMove_; 91 } 92 ListItemFocused(int32_t focusIndex)93 void ListItemFocused(int32_t focusIndex) 94 { 95 focusIndex_ = focusIndex; 96 focusMove_ = focusIndex; 97 } 98 MarkNeedRefresh()99 void MarkNeedRefresh() 100 { 101 needRefresh_ = true; 102 NotifyNeedRefresh(); 103 } 104 ResetLayoutRange(double head,double tail,Offset position,Size viewPort)105 void ResetLayoutRange(double head, double tail, Offset position, Size viewPort) 106 { 107 head_ = head; 108 tail_ = tail; 109 position_ = position; 110 viewPort_ = viewPort; 111 } 112 GetPosition()113 const Offset& GetPosition() const 114 { 115 return position_; 116 } 117 FlushChainAnimation()118 virtual double FlushChainAnimation() 119 { 120 return 0.0; 121 } 122 IsRowReverse()123 bool IsRowReverse() const 124 { 125 return (rightToLeft_ && direction_ == FlexDirection::ROW) 126 || (!rightToLeft_ && direction_ == FlexDirection::ROW_REVERSE); 127 } 128 IsColReverse()129 bool IsColReverse() const 130 { 131 return direction_ == FlexDirection::COLUMN_REVERSE; 132 } 133 GetItemGrid(int32_t index)134 int32_t GetItemGrid(int32_t index) const 135 { 136 auto iter = itemGrid_.find(index); 137 if (iter == itemGrid_.end()) { 138 return 0; 139 } 140 return iter->second; 141 } 142 CheckItemPosition(int32_t index)143 bool CheckItemPosition(int32_t index) const 144 { 145 return itemPosition_.find(index) != itemPosition_.end(); 146 } 147 GetItemAnimationValue(int32_t index)148 virtual double GetItemAnimationValue(int32_t index) const 149 { 150 return 0.0; 151 } 152 GetItemPosition(int32_t index)153 double GetItemPosition(int32_t index) const 154 { 155 auto iter = itemPosition_.find(index); 156 if (iter == itemPosition_.end()) { 157 return 0.0; 158 } 159 return iter->second; 160 } 161 GetChainInterval()162 double GetChainInterval() const 163 { 164 return enableChain_ ? chainInterval_ : 0.0; 165 } 166 GetChainItemRange(int32_t index,double & start,double & end)167 void GetChainItemRange(int32_t index, double& start, double& end) const 168 { 169 if (!enableChain_) { 170 return; 171 } 172 start = GetItemPosition(index) - GetChainInterval() * HALF_ITEM_SIZE; 173 double nextStartPosition = GetItemPosition(index + 1); 174 if (!NearZero(nextStartPosition)) { 175 end = nextStartPosition - GetChainInterval() * HALF_ITEM_SIZE; 176 } 177 } 178 GetIndexByPosition(double position)179 int32_t GetIndexByPosition(double position) const 180 { 181 int32_t index = 0; 182 double curPosition = 0.0; 183 for (const auto& item : itemPosition_) { 184 double correctedPosition = item.second + GetItemAnimationValue(item.first); 185 if (NearEqual(correctedPosition, position)) { 186 return item.first; 187 } else { 188 if (NearEqual(curPosition, correctedPosition)) { 189 continue; 190 } 191 curPosition = correctedPosition; 192 if (correctedPosition < position) { 193 index = item.first; 194 } else { 195 return index; 196 } 197 } 198 } 199 return index; 200 } 201 CalculateRepeatedIndex(int32_t cachedIndex)202 int32_t CalculateRepeatedIndex(int32_t cachedIndex) 203 { 204 int32_t repeatedIndex; 205 if (repeatedLength_ == LIST_LENGTH_INFINITE) { 206 repeatedIndex = ((cachedIndex - indexOffset_) > 0 ? (cachedIndex - indexOffset_) : 0); 207 } else { 208 if (cachedIndex < indexOffset_) { 209 repeatedIndex = 0; 210 } else { 211 if (cachedIndex > indexOffset_ + repeatedLength_) { 212 repeatedIndex = repeatedLength_; 213 } else { 214 repeatedIndex = cachedIndex - indexOffset_; 215 } 216 } 217 } 218 return repeatedIndex; 219 } 220 GetExpandStatus(int32_t groupIndex)221 bool GetExpandStatus(int32_t groupIndex) const 222 { 223 auto iter = itemGroupsExpand_.find(groupIndex); 224 if (iter != itemGroupsExpand_.end()) { 225 return iter->second; 226 } else { 227 return expandAll_; 228 } 229 } 230 GetItemGroupFocusIndex(int32_t groupIndex)231 int32_t GetItemGroupFocusIndex(int32_t groupIndex) const 232 { 233 auto iter = itemGroupsFocusIndex_.find(groupIndex); 234 if (iter != itemGroupsFocusIndex_.end()) { 235 return iter->second; 236 } 237 return 0; 238 } 239 SetExpandAll(bool expandAll)240 void SetExpandAll(bool expandAll) 241 { 242 expandAll_ = expandAll; 243 } 244 ClearItemGroupsExpand()245 void ClearItemGroupsExpand() 246 { 247 itemGroupsExpand_.clear(); 248 } 249 ClearItemPosition()250 void ClearItemPosition() 251 { 252 itemPosition_.clear(); 253 } 254 AddItemGroupExpand(int32_t index,bool expand)255 void AddItemGroupExpand(int32_t index, bool expand) 256 { 257 itemGroupsExpand_[index] = expand; 258 } 259 AddItemGroupFocusIndex(int32_t index,int32_t groupFocusIndex)260 void AddItemGroupFocusIndex(int32_t index, int32_t groupFocusIndex) 261 { 262 itemGroupsFocusIndex_[index] = groupFocusIndex; 263 } 264 GetFriction()265 double GetFriction() const 266 { 267 return friction_; 268 } 269 SetFriction(double friction)270 void SetFriction(double friction) 271 { 272 friction_ = friction; 273 } 274 GetSlipFactor()275 double GetSlipFactor() const 276 { 277 return slipFactor_; 278 } 279 280 protected: 281 double head_ = 0.0; 282 double tail_ = 0.0; 283 double lastHead_ = 0.0; 284 double lastTail_ = 0.0; 285 int32_t focusMove_ = 0; // Record the focus move path. 286 int32_t focusIndex_ = 0; // Record the index of focus item. 287 Offset position_; 288 Size viewPort_; 289 bool needRefresh_ = false; 290 bool firstLayout_ = true; 291 Dimension itemExtent_; 292 293 bool rightToLeft_ = false; 294 bool isVertical_ = false; 295 FlexDirection direction_ { FlexDirection::COLUMN }; 296 FlexAlign crossAxisAlign_ { FlexAlign::STRETCH }; 297 int32_t beginIndex_ = LIST_PARAM_INVAID; 298 int32_t endIndex_ = LIST_PARAM_INVAID; 299 int32_t length_ = 0; 300 int32_t repeatedLength_ = 0; 301 int32_t indexOffset_ = 0; 302 303 std::map<int32_t, int32_t> itemGrid_; 304 std::map<int32_t, double> itemPosition_; 305 std::map<int32_t, bool> itemGroupsExpand_; 306 std::map<int32_t, int32_t> itemGroupsFocusIndex_; 307 308 RefPtr<Animator> controller_; 309 std::vector<int32_t> needRemoveItems_; 310 std::map<int32_t, RefPtr<RenderNode>> newItems_; 311 bool isAnimating_ = false; 312 double friction_ = 1.0; 313 bool expandAll_ = false; 314 bool enableChain_ = false; // whether enables spring chain effect. 315 double chainInterval_ = 0.0; 316 int32_t itemCountOfPage_ = 0; 317 double slipFactor_ = 0.0; 318 }; 319 320 } // namespace OHOS::Ace 321 322 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_LIST_LAYOUT_MANAGER_H 323