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 LOGD("Focus move from %{public}d to %{public}d", focusIndex_, index); 85 if (index < 0) { 86 focusMove_ = focusIndex_; 87 return index; 88 } 89 focusMove_ = index; 90 focusIndex_ = index; 91 return focusMove_; 92 } 93 ListItemFocused(int32_t focusIndex)94 void ListItemFocused(int32_t focusIndex) 95 { 96 focusIndex_ = focusIndex; 97 focusMove_ = focusIndex; 98 } 99 MarkNeedRefresh()100 void MarkNeedRefresh() 101 { 102 needRefresh_ = true; 103 NotifyNeedRefresh(); 104 } 105 ResetLayoutRange(double head,double tail,Offset position,Size viewPort)106 void ResetLayoutRange(double head, double tail, Offset position, Size viewPort) 107 { 108 head_ = head; 109 tail_ = tail; 110 position_ = position; 111 viewPort_ = viewPort; 112 } 113 GetPosition()114 const Offset& GetPosition() const 115 { 116 return position_; 117 } 118 FlushChainAnimation()119 virtual double FlushChainAnimation() 120 { 121 return 0.0; 122 } 123 IsRowReverse()124 bool IsRowReverse() const 125 { 126 return (rightToLeft_ && direction_ == FlexDirection::ROW) 127 || (!rightToLeft_ && direction_ == FlexDirection::ROW_REVERSE); 128 } 129 IsColReverse()130 bool IsColReverse() const 131 { 132 return direction_ == FlexDirection::COLUMN_REVERSE; 133 } 134 GetItemGrid(int32_t index)135 int32_t GetItemGrid(int32_t index) const 136 { 137 auto iter = itemGrid_.find(index); 138 if (iter == itemGrid_.end()) { 139 return 0; 140 } 141 return iter->second; 142 } 143 CheckItemPosition(int32_t index)144 bool CheckItemPosition(int32_t index) const 145 { 146 return itemPosition_.find(index) != itemPosition_.end(); 147 } 148 GetItemAnimationValue(int32_t index)149 virtual double GetItemAnimationValue(int32_t index) const 150 { 151 return 0.0; 152 } 153 GetItemPosition(int32_t index)154 double GetItemPosition(int32_t index) const 155 { 156 auto iter = itemPosition_.find(index); 157 if (iter == itemPosition_.end()) { 158 return 0.0; 159 } 160 return iter->second; 161 } 162 GetChainInterval()163 double GetChainInterval() const 164 { 165 return enableChain_ ? chainInterval_ : 0.0; 166 } 167 GetChainItemRange(int32_t index,double & start,double & end)168 void GetChainItemRange(int32_t index, double& start, double& end) const 169 { 170 if (!enableChain_) { 171 return; 172 } 173 start = GetItemPosition(index) - GetChainInterval() * HALF_ITEM_SIZE; 174 double nextStartPosition = GetItemPosition(index + 1); 175 if (!NearZero(nextStartPosition)) { 176 end = nextStartPosition - GetChainInterval() * HALF_ITEM_SIZE; 177 } 178 } 179 GetIndexByPosition(double position)180 int32_t GetIndexByPosition(double position) const 181 { 182 int32_t index = 0; 183 double curPosition = 0.0; 184 for (const auto& item : itemPosition_) { 185 double correctedPosition = item.second + GetItemAnimationValue(item.first); 186 if (NearEqual(correctedPosition, position)) { 187 return item.first; 188 } else { 189 if (NearEqual(curPosition, correctedPosition)) { 190 continue; 191 } 192 curPosition = correctedPosition; 193 if (correctedPosition < position) { 194 index = item.first; 195 } else { 196 return index; 197 } 198 } 199 } 200 return index; 201 } 202 CalculateRepeatedIndex(int32_t cachedIndex)203 int32_t CalculateRepeatedIndex(int32_t cachedIndex) 204 { 205 int32_t repeatedIndex; 206 if (repeatedLength_ == LIST_LENGTH_INFINITE) { 207 repeatedIndex = ((cachedIndex - indexOffset_) > 0 ? (cachedIndex - indexOffset_) : 0); 208 } else { 209 if (cachedIndex < indexOffset_) { 210 repeatedIndex = 0; 211 } else { 212 if (cachedIndex > indexOffset_ + repeatedLength_) { 213 repeatedIndex = repeatedLength_; 214 } else { 215 repeatedIndex = cachedIndex - indexOffset_; 216 } 217 } 218 } 219 return repeatedIndex; 220 } 221 GetExpandStatus(int32_t groupIndex)222 bool GetExpandStatus(int32_t groupIndex) const 223 { 224 auto iter = itemGroupsExpand_.find(groupIndex); 225 if (iter != itemGroupsExpand_.end()) { 226 return iter->second; 227 } else { 228 return expandAll_; 229 } 230 } 231 GetItemGroupFocusIndex(int32_t groupIndex)232 int32_t GetItemGroupFocusIndex(int32_t groupIndex) const 233 { 234 auto iter = itemGroupsFocusIndex_.find(groupIndex); 235 if (iter != itemGroupsFocusIndex_.end()) { 236 return iter->second; 237 } 238 return 0; 239 } 240 SetExpandAll(bool expandAll)241 void SetExpandAll(bool expandAll) 242 { 243 expandAll_ = expandAll; 244 } 245 ClearItemGroupsExpand()246 void ClearItemGroupsExpand() 247 { 248 itemGroupsExpand_.clear(); 249 } 250 ClearItemPosition()251 void ClearItemPosition() 252 { 253 itemPosition_.clear(); 254 } 255 AddItemGroupExpand(int32_t index,bool expand)256 void AddItemGroupExpand(int32_t index, bool expand) 257 { 258 itemGroupsExpand_[index] = expand; 259 } 260 AddItemGroupFocusIndex(int32_t index,int32_t groupFocusIndex)261 void AddItemGroupFocusIndex(int32_t index, int32_t groupFocusIndex) 262 { 263 itemGroupsFocusIndex_[index] = groupFocusIndex; 264 } 265 GetFriction()266 double GetFriction() const 267 { 268 return friction_; 269 } 270 SetFriction(double friction)271 void SetFriction(double friction) 272 { 273 friction_ = friction; 274 } 275 GetSlipFactor()276 double GetSlipFactor() const 277 { 278 return slipFactor_; 279 } 280 281 protected: 282 double head_ = 0.0; 283 double tail_ = 0.0; 284 double lastHead_ = 0.0; 285 double lastTail_ = 0.0; 286 int32_t focusMove_ = 0; // Record the focus move path. 287 int32_t focusIndex_ = 0; // Record the index of focus item. 288 Offset position_; 289 Size viewPort_; 290 bool needRefresh_ = false; 291 bool firstLayout_ = true; 292 Dimension itemExtent_; 293 294 bool rightToLeft_ = false; 295 bool isVertical_ = false; 296 FlexDirection direction_ { FlexDirection::COLUMN }; 297 FlexAlign crossAxisAlign_ { FlexAlign::STRETCH }; 298 int32_t beginIndex_ = LIST_PARAM_INVAID; 299 int32_t endIndex_ = LIST_PARAM_INVAID; 300 int32_t length_ = 0; 301 int32_t repeatedLength_ = 0; 302 int32_t indexOffset_ = 0; 303 304 std::map<int32_t, int32_t> itemGrid_; 305 std::map<int32_t, double> itemPosition_; 306 std::map<int32_t, bool> itemGroupsExpand_; 307 std::map<int32_t, int32_t> itemGroupsFocusIndex_; 308 309 RefPtr<Animator> controller_; 310 std::vector<int32_t> needRemoveItems_; 311 std::map<int32_t, RefPtr<RenderNode>> newItems_; 312 bool isAnimating_ = false; 313 double friction_ = 1.0; 314 bool expandAll_ = false; 315 bool enableChain_ = false; // whether enables spring chain effect. 316 double chainInterval_ = 0.0; 317 int32_t itemCountOfPage_ = 0; 318 double slipFactor_ = 0.0; 319 }; 320 321 } // namespace OHOS::Ace 322 323 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_LIST_LAYOUT_MANAGER_H 324