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_SCROLL_SCROLL_POSITION_CONTROLLER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLL_SCROLL_POSITION_CONTROLLER_H 18 19 #include <functional> 20 21 #include "core/animation/curve.h" 22 #include "core/components/scroll/scroll_controller_interface.h" 23 #include "core/components/scroll/scrollable.h" 24 #include "core/pipeline/base/render_node.h" 25 26 namespace OHOS::Ace { 27 28 constexpr uint32_t POSITION_MIDDLE = 0; 29 constexpr uint32_t POSITION_TOP = 1 << 0; 30 constexpr uint32_t POSITION_BOTTOM = 1 << 1; 31 32 enum class ScrollEvent : size_t { 33 SCROLL_TOP = 0, 34 SCROLL_BOTTOM, 35 SCROLL_TOUCHUP, 36 SCROLL_END, 37 SCROLL_POSITION, 38 SCROLL_EDGE, 39 SCROLL_LEFT, 40 SCROLL_RIGHT, 41 UNKNOWN, 42 }; 43 44 using OnScrollFunc = std::function<void(const std::string&)>; 45 46 class ScrollEventInfo : public BaseEventInfo, public EventToJSONStringAdapter { 47 DECLARE_RELATIONSHIP_OF_CLASSES(ScrollEventInfo, BaseEventInfo, EventToJSONStringAdapter); 48 public: 49 ScrollEventInfo(ScrollEvent type, double scrollX, double scrollY, int32_t scrollState); 50 51 ~ScrollEventInfo() = default; 52 53 std::string ToJSONString() const override; 54 GetType()55 ScrollEvent GetType() const 56 { 57 return type_; 58 } 59 GetScrollX()60 double GetScrollX() const 61 { 62 return scrollX_; 63 } 64 GetScrollY()65 double GetScrollY() const 66 { 67 return scrollY_; 68 } 69 GetScrollState()70 int32_t GetScrollState() const 71 { 72 return scrollState_; 73 } 74 SetScrollType(ScrollEvent type)75 void SetScrollType(ScrollEvent type) 76 { 77 type_ = type; 78 } 79 80 private: 81 ScrollEvent type_ = ScrollEvent::SCROLL_TOP; 82 double scrollX_ = 0.0; 83 double scrollY_ = 0.0; 84 int32_t scrollState_ = -1; 85 }; 86 87 using ScrollEventFunc = std::function<void(std::shared_ptr<ScrollEventInfo>&)>; 88 class ACE_EXPORT ScrollPositionController : public ScrollController { 89 DECLARE_ACE_TYPE(ScrollPositionController, AceType); 90 91 public: 92 ScrollPositionController() = default; 93 ~ScrollPositionController() override = default; 94 SetInitialIndex(int32_t index)95 void SetInitialIndex(int32_t index) 96 { 97 if (index == 0) { 98 flags_ = POSITION_TOP; 99 } else { 100 flags_ = POSITION_MIDDLE; 101 } 102 initialIndex_ = index; 103 } 104 GetInitialIndex()105 int32_t GetInitialIndex() const 106 { 107 return initialIndex_; 108 } 109 SetInitialOffset(double initialOffset)110 void SetInitialOffset(double initialOffset) 111 { 112 if (NearZero(initialOffset)) { 113 flags_ = POSITION_TOP; 114 } else { 115 flags_ = POSITION_MIDDLE; 116 } 117 initialOffset_ = initialOffset; 118 } 119 GetInitialOffset()120 double GetInitialOffset() const 121 { 122 return initialOffset_; 123 } 124 125 double GetCurrentPosition() const; 126 Axis GetScrollDirection() const override; 127 128 void JumpTo(int32_t index, int32_t source = SCROLL_FROM_JUMP) override; 129 void JumpTo(double position); 130 bool AnimateTo(const Dimension& position, float duration, const RefPtr<Curve>& curve) override; 131 bool AnimateTo(double position, float duration, const RefPtr<Curve>& curve, bool limitDuration = true, 132 const std::function<void()>& onFinish = nullptr); 133 bool AnimateToTarget(const ComposeId& targetId, float duration, const RefPtr<Curve>& curve, 134 bool limitDuration = true, const std::function<void()>& onFinish = nullptr); 135 void ScrollBy(double pixelX, double pixelY, bool smooth) override; 136 void ScrollArrow(double scrollDistance, bool reverse, bool smooth); 137 void ScrollToEdge(ScrollEdgeType scrollEdgeType, bool smooth) override; 138 void ScrollPage(bool reverse, bool smooth) override; 139 Offset GetCurrentOffset() const override; 140 141 SetScrollEvent(ScrollEvent event,const ScrollEventFunc & scrollEvent)142 void SetScrollEvent( 143 ScrollEvent event, const ScrollEventFunc& scrollEvent) 144 { 145 switch (event) { 146 case ScrollEvent::SCROLL_TOP: 147 scrollTop_ = scrollEvent; 148 break; 149 case ScrollEvent::SCROLL_BOTTOM: 150 scrollBottom_ = scrollEvent; 151 break; 152 case ScrollEvent::SCROLL_END: 153 scrollEnd_ = scrollEvent; 154 break; 155 case ScrollEvent::SCROLL_TOUCHUP: 156 scrollTouchUp_ = scrollEvent; 157 break; 158 case ScrollEvent::SCROLL_POSITION: 159 scrollPosition_ = scrollEvent; 160 break; 161 case ScrollEvent::SCROLL_EDGE: 162 scrollEdge_ = scrollEvent; 163 break; 164 default: 165 LOGW("unknown scroll event"); 166 break; 167 } 168 } 169 HandleScrollEvent(std::shared_ptr<ScrollEventInfo> info)170 void HandleScrollEvent(std::shared_ptr<ScrollEventInfo> info) const 171 { 172 if (!info) { 173 LOGE("scroll event info is null"); 174 return; 175 } 176 auto eventType = info->GetType(); 177 switch (eventType) { 178 case ScrollEvent::SCROLL_TOP: 179 if (scrollTop_) { 180 scrollTop_(info); 181 } 182 if (scrollEdge_) { 183 scrollEdge_(info); 184 } 185 break; 186 case ScrollEvent::SCROLL_BOTTOM: 187 if (scrollBottom_) { 188 scrollBottom_(info); 189 } 190 if (scrollEdge_) { 191 scrollEdge_(info); 192 } 193 break; 194 case ScrollEvent::SCROLL_END: 195 if (scrollEnd_) { 196 scrollEnd_(info); 197 } 198 break; 199 case ScrollEvent::SCROLL_TOUCHUP: 200 if (scrollTouchUp_) { 201 scrollTouchUp_(info); 202 } 203 break; 204 case ScrollEvent::SCROLL_POSITION: 205 if (scrollPosition_) { 206 scrollPosition_(info); 207 } 208 break; 209 default: 210 LOGW("handle unknown scroll event"); 211 break; 212 } 213 } 214 SetTop()215 void SetTop() 216 { 217 flags_ |= POSITION_TOP; 218 } 219 SetBottom()220 void SetBottom() 221 { 222 flags_ |= POSITION_BOTTOM; 223 } 224 SetMiddle()225 void SetMiddle() 226 { 227 flags_ = POSITION_MIDDLE; 228 } 229 IsTop()230 bool IsTop() const 231 { 232 return (flags_ & POSITION_TOP); 233 } 234 IsBottom()235 bool IsBottom() const 236 { 237 return (flags_ & POSITION_BOTTOM); 238 } 239 SetNonScrollable()240 void SetNonScrollable() 241 { 242 flags_ = (POSITION_TOP | POSITION_BOTTOM); 243 } 244 245 using OnFirstChanged = std::function<void(int32_t)>; AddFirstChangedCallback(const OnFirstChanged & callback)246 void AddFirstChangedCallback(const OnFirstChanged& callback) 247 { 248 onChanged_ = callback; 249 } 250 251 using IndexerRotation = std::function<bool()>; AddIndexerStateQueryCallback(const IndexerRotation & callback)252 void AddIndexerStateQueryCallback(const IndexerRotation& callback) 253 { 254 indexerRotationCallback_ = callback; 255 } 256 IsScrollNeedRotation()257 bool IsScrollNeedRotation() 258 { 259 return !(indexerRotationCallback_ && indexerRotationCallback_()); 260 } 261 SetFirstItemIndex(int32_t firstIndex)262 void SetFirstItemIndex(int32_t firstIndex) 263 { 264 firstIndex_ = firstIndex; 265 if (onChanged_) { 266 onChanged_(firstIndex_); 267 } 268 } 269 GetFirstItemIndex()270 int32_t GetFirstItemIndex() const 271 { 272 return firstIndex_; 273 } 274 275 private: 276 int32_t initialIndex_ = 0; 277 double initialOffset_ = 0.0; 278 OnFirstChanged onChanged_; 279 IndexerRotation indexerRotationCallback_; 280 int32_t firstIndex_ = 0; 281 282 ScrollEventFunc scrollTop_; 283 ScrollEventFunc scrollBottom_; 284 ScrollEventFunc scrollTouchUp_; 285 ScrollEventFunc scrollEnd_; 286 ScrollEventFunc scrollPosition_; 287 ScrollEventFunc scrollEdge_; 288 uint32_t flags_ = POSITION_TOP; 289 }; 290 291 } // namespace OHOS::Ace 292 293 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLL_SCROLL_POSITION_CONTROLLER_H 294