1 /* 2 * Copyright (c) 2022-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_PATTERNS_GRID_GRID_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRID_GRID_PATTERN_H 18 19 #include "core/components_ng/pattern/grid/grid_accessibility_property.h" 20 #include "core/components_ng/pattern/grid/grid_event_hub.h" 21 #include "core/components_ng/pattern/grid/grid_layout_info.h" 22 #include "core/components_ng/pattern/grid/grid_layout_property.h" 23 #include "core/components_ng/pattern/grid/grid_paint_method.h" 24 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h" 25 26 namespace OHOS::Ace::NG { 27 class InspectorFilter; 28 29 struct GridItemIndexInfo { 30 int32_t mainIndex = -1; 31 int32_t crossIndex = -1; 32 int32_t mainSpan = -1; 33 int32_t crossSpan = -1; 34 int32_t mainStart = -1; 35 int32_t mainEnd = -1; 36 int32_t crossStart = -1; 37 int32_t crossEnd = -1; 38 }; 39 40 class ACE_EXPORT GridPattern : public ScrollablePattern { 41 DECLARE_ACE_TYPE(GridPattern, ScrollablePattern); 42 43 public: 44 GridPattern() = default; 45 CreateLayoutProperty()46 RefPtr<LayoutProperty> CreateLayoutProperty() override 47 { 48 return MakeRefPtr<GridLayoutProperty>(); 49 } 50 51 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override; 52 53 void BeforeCreateLayoutWrapper() override; 54 55 RefPtr<NodePaintMethod> CreateNodePaintMethod() override; 56 CreateAccessibilityProperty()57 RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override 58 { 59 return MakeRefPtr<GridAccessibilityProperty>(); 60 } 61 IsScrollable()62 bool IsScrollable() const override 63 { 64 return isConfigScrollable_; 65 } 66 67 DisplayMode GetDefaultScrollBarDisplayMode() const override; 68 SetMultiSelectable(bool multiSelectable)69 void SetMultiSelectable(bool multiSelectable) 70 { 71 multiSelectable_ = multiSelectable; 72 } 73 MultiSelectable()74 bool MultiSelectable() const 75 { 76 return multiSelectable_; 77 } 78 SetSupportAnimation(bool supportAnimation)79 void SetSupportAnimation(bool supportAnimation) 80 { 81 supportAnimation_ = supportAnimation; 82 } 83 SupportAnimation()84 bool SupportAnimation() const 85 { 86 return supportAnimation_; 87 } 88 GetFocusPattern()89 FocusPattern GetFocusPattern() const override 90 { 91 return { FocusType::SCOPE, true }; 92 } 93 GetScopeFocusAlgorithm()94 ScopeFocusAlgorithm GetScopeFocusAlgorithm() override 95 { 96 auto property = GetLayoutProperty<GridLayoutProperty>(); 97 if (!property) { 98 return ScopeFocusAlgorithm(); 99 } 100 return ScopeFocusAlgorithm(property->IsVertical(), true, ScopeType::OTHERS, 101 [wp = WeakClaim(this)]( 102 FocusStep step, const WeakPtr<FocusHub>& currFocusNode, WeakPtr<FocusHub>& nextFocusNode) { 103 auto grid = wp.Upgrade(); 104 if (grid) { 105 nextFocusNode = grid->GetNextFocusNode(step, currFocusNode); 106 } 107 }); 108 } 109 110 int32_t GetFocusNodeIndex(const RefPtr<FocusHub>& focusNode) override; 111 112 void ScrollToFocusNodeIndex(int32_t index) override; 113 114 std::pair<std::function<bool(float)>, Axis> GetScrollOffsetAbility() override; 115 116 std::function<bool(int32_t)> GetScrollIndexAbility() override; 117 118 bool ScrollToNode(const RefPtr<FrameNode>& focusFrameNode) override; 119 CreateEventHub()120 RefPtr<EventHub> CreateEventHub() override 121 { 122 return MakeRefPtr<GridEventHub>(); 123 } 124 UsResRegion()125 bool UsResRegion() override 126 { 127 return false; 128 } 129 GetGridLayoutInfo()130 const GridLayoutInfo& GetGridLayoutInfo() const 131 { 132 return gridLayoutInfo_; 133 } 134 135 /* caution when using mutable reference */ GetMutableLayoutInfo()136 GridLayoutInfo& GetMutableLayoutInfo() 137 { 138 return gridLayoutInfo_; 139 } 140 ResetGridLayoutInfo()141 void ResetGridLayoutInfo() 142 { 143 gridLayoutInfo_.lineHeightMap_.clear(); 144 gridLayoutInfo_.gridMatrix_.clear(); 145 gridLayoutInfo_.endIndex_ = gridLayoutInfo_.startIndex_ - 1; 146 gridLayoutInfo_.endMainLineIndex_ = 0; 147 gridLayoutInfo_.ResetPositionFlags(); 148 gridLayoutInfo_.irregularItemsPosition_.clear(); 149 gridLayoutInfo_.clearStretch_ = true; 150 } 151 SetIrregular(bool value)152 void SetIrregular(bool value) 153 { 154 irregular_ = value; 155 } 156 ResetPositionFlags()157 void ResetPositionFlags() 158 { 159 gridLayoutInfo_.ResetPositionFlags(); 160 } 161 162 void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override; 163 164 bool UpdateCurrentOffset(float offset, int32_t source) override; 165 IsAtTop()166 bool IsAtTop() const override 167 { 168 return gridLayoutInfo_.reachStart_; 169 } 170 IsAtBottom()171 bool IsAtBottom() const override 172 { 173 return gridLayoutInfo_.offsetEnd_; 174 } 175 176 OverScrollOffset GetOverScrollOffset(double delta) const override; 177 void GetEndOverScrollIrregular(OverScrollOffset& offset, float delta) const; 178 179 void ScrollPage(bool reverse, AccessibilityScrollType scrollType = AccessibilityScrollType::SCROLL_FULL); 180 181 bool UpdateStartIndex(int32_t index); 182 183 bool UpdateStartIndex(int32_t index, ScrollAlign align); 184 GetTotalOffset()185 float GetTotalOffset() const override 186 { 187 return EstimateHeight(); 188 } 189 190 float GetTotalHeight() const override; 191 192 void OnAnimateStop() override; 193 194 void AnimateTo( 195 float position, float duration, const RefPtr<Curve>& curve, bool smooth, bool canOverScroll = false, 196 bool useTotalOffset = true) override; 197 void ScrollTo(float position) override; 198 199 void ScrollBy(float offset); 200 GetDefaultScrollAlign()201 ScrollAlign GetDefaultScrollAlign() const override 202 { 203 return ScrollAlign::AUTO; 204 } 205 206 void ScrollToEdge(ScrollEdgeType scrollEdgeType, bool smooth) override; 207 208 void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::AUTO, 209 std::optional<float> extraOffset = std::nullopt) override; 210 void AnimateToTarget(ScrollAlign align, const RefPtr<LayoutAlgorithmWrapper>& algo); 211 bool AnimateToTargetImpl(ScrollAlign align, const RefPtr<LayoutAlgorithmWrapper>& algo); 212 213 int32_t GetOriginalIndex() const; 214 int32_t GetCrossCount() const; 215 int32_t GetChildrenCount() const; 216 void MoveItems(int32_t itemIndex, int32_t insertIndex); 217 void ClearDragState(); 218 float EstimateHeight() const; 219 float GetAverageHeight() const; 220 221 void DumpAdvanceInfo() override; 222 223 std::string ProvideRestoreInfo() override; 224 void OnRestoreInfo(const std::string& restoreInfo) override; 225 Rect GetItemRect(int32_t index) const override; 226 IsNeedInitClickEventRecorder()227 bool IsNeedInitClickEventRecorder() const override 228 { 229 return true; 230 } 231 GetPreloadItemList()232 const std::list<GridPreloadItem>& GetPreloadItemList() const 233 { 234 return preloadItemList_; 235 } 236 SetPreloadItemList(std::list<GridPreloadItem> && list)237 void SetPreloadItemList(std::list<GridPreloadItem>&& list) 238 { 239 preloadItemList_ = std::move(list); 240 } 241 242 std::vector<RefPtr<FrameNode>> GetVisibleSelectedItems() override; 243 244 void StopAnimate() override; 245 246 bool IsPredictOutOfRange(int32_t index) const; 247 248 bool IsReverse() const override; 249 GetAxis()250 Axis GetAxis() const override 251 { 252 return gridLayoutInfo_.axis_; 253 } 254 GetDefaultCachedCount()255 int32_t GetDefaultCachedCount() const 256 { 257 return gridLayoutInfo_.defCachedCount_; 258 } 259 260 private: 261 /** 262 * @brief calculate where startMainLine_ should be after spring animation. 263 * @return main axis position relative to viewport, positive when below viewport. 264 */ 265 float GetEndOffset(); 266 float GetMainGap() const; 267 float GetAllDelta(); 268 void CheckScrollable(); 269 bool IsOutOfBoundary(bool useCurrentDelta) override; 270 void SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect>& scrollEffect) override; 271 SizeF GetContentSize() const; 272 void OnModifyDone() override; 273 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 274 WeakPtr<FocusHub> GetNextFocusNode(FocusStep step, const WeakPtr<FocusHub>& currentFocusNode); 275 std::pair<int32_t, int32_t> GetNextIndexByStep( 276 int32_t curMainIndex, int32_t curCrossIndex, int32_t curMainSpan, int32_t curCrossSpan, FocusStep step); 277 WeakPtr<FocusHub> SearchFocusableChildInCross(int32_t tarMainIndex, int32_t tarCrossIndex, int32_t maxCrossCount, 278 int32_t curMainIndex = -1, int32_t curCrossIndex = -1); 279 WeakPtr<FocusHub> SearchIrregularFocusableChild(int32_t tarMainIndex, int32_t tarCrossIndex); 280 WeakPtr<FocusHub> GetChildFocusNodeByIndex(int32_t tarMainIndex, int32_t tarCrossIndex, int32_t tarIndex = -1); 281 std::unordered_set<int32_t> GetFocusableChildCrossIndexesAt(int32_t tarMainIndex); 282 void ScrollToFocusNode(const WeakPtr<FocusHub>& focusNode); 283 void FlushFocusOnScroll(const GridLayoutInfo& gridLayoutInfo); 284 std::pair<bool, bool> IsFirstOrLastFocusableChild(int32_t curMainIndex, int32_t curCrossIndex); 285 std::pair<FocusStep, FocusStep> GetFocusSteps(int32_t curMainIndex, int32_t curCrossIndex, FocusStep step); 286 void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub); 287 bool OnKeyEvent(const KeyEvent& event); 288 bool HandleDirectionKey(KeyCode code); 289 290 void ClearMultiSelect() override; 291 bool IsItemSelected(const GestureEvent& info) override; 292 void MultiSelectWithoutKeyboard(const RectF& selectedZone) override; 293 void UpdateScrollBarOffset() override; 294 void UpdateRectOfDraggedInItem(int32_t insertIndex); 295 296 void ProcessEvent(bool indexChanged, float finalOffset); 297 void MarkDirtyNodeSelf(); 298 void OnScrollEndCallback() override; 299 300 /** 301 * @brief preform a layout if LayoutInfo is out of sync before calculating spring positions. 302 * INVARIANT: overScroll always enabled in the scope of this function. Because this function only runs in the 303 * context of spring animation. 304 */ 305 void SyncLayoutBeforeSpring(); 306 307 void FireOnScrollStart() override; 308 void FireOnReachStart(const OnReachEvent& onReachStart) override; 309 void FireOnReachEnd(const OnReachEvent& onReachEnd) override; 310 void FireOnScrollIndex(bool indexChanged, const ScrollIndexFunc& onScrollIndex); 311 312 inline bool UseIrregularLayout() const; 313 314 int32_t CalcIntersectAreaInTargetDirectionShadow(GridItemIndexInfo itemIndexInfo, bool isFindInMainAxis); 315 double GetNearestDistanceFromChildToCurFocusItemInMainAxis(int32_t targetIndex, GridItemIndexInfo itemIndexInfo); 316 double GetNearestDistanceFromChildToCurFocusItemInCrossAxis(int32_t targetIndex, GridItemIndexInfo itemIndexInfo); 317 void ResetAllDirectionsStep(); 318 319 std::string GetIrregularIndexesString() const; 320 321 bool supportAnimation_ = false; 322 bool isConfigScrollable_ = false; 323 324 bool scrollable_ = true; 325 bool forceOverScroll_ = false; 326 327 float endHeight_ = 0.0f; 328 bool isLeftStep_ = false; 329 bool isRightStep_ = false; 330 bool isUpStep_ = false; 331 bool isDownStep_ = false; 332 bool isLeftEndStep_ = false; 333 bool isRightEndStep_ = false; 334 bool isSmoothScrolling_ = false; 335 bool irregular_ = false; // true if LayoutOptions require running IrregularLayout 336 337 ScrollAlign scrollAlign_ = ScrollAlign::AUTO; 338 std::optional<int32_t> targetIndex_; 339 std::pair<std::optional<float>, std::optional<float>> scrollbarInfo_; 340 GridItemIndexInfo curFocusIndexInfo_; 341 GridLayoutInfo scrollGridLayoutInfo_; 342 GridLayoutInfo gridLayoutInfo_; 343 std::list<GridPreloadItem> preloadItemList_; // list of GridItems to build preemptively in IdleTask 344 ACE_DISALLOW_COPY_AND_MOVE(GridPattern); 345 }; 346 347 } // namespace OHOS::Ace::NG 348 349 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRID_GRID_PATTERN_H 350