1 /* 2 * Copyright (c) 2022 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_SWIPER_SWIPER_EVENT_HUB_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_SWIPER_EVENT_HUB_H 18 19 #include <algorithm> 20 #include <memory> 21 22 #include "base/memory/ace_type.h" 23 #include "core/common/recorder/event_recorder.h" 24 #include "core/common/recorder/node_data_cache.h" 25 #include "core/components_ng/base/frame_node.h" 26 #include "core/components_ng/event/event_hub.h" 27 #include "core/components_ng/pattern/swiper/swiper_model.h" 28 #include "core/pipeline_ng/pipeline_context.h" 29 30 namespace OHOS::Ace::NG { 31 32 enum class Direction { 33 PRE = 0, 34 NEXT, 35 }; 36 using ChangeIndicatorEvent = std::function<void()>; 37 using IndicatorIndexChangeEvent = std::function<void(int32_t index)>; 38 using ChangeEvent = std::function<void(int32_t index)>; 39 using ChangeEventPtr = std::shared_ptr<ChangeEvent>; 40 using ChangeEventWithPreIndex = std::function<void(int32_t preIndex, int32_t currentIndex)>; 41 using ChangeEventWithPreIndexPtr = std::shared_ptr<ChangeEventWithPreIndex>; 42 using ChangeDoneEvent = std::function<void()>; 43 44 class SwiperEventHub : public EventHub { 45 DECLARE_ACE_TYPE(SwiperEventHub, EventHub) 46 47 public: 48 SwiperEventHub() = default; 49 ~SwiperEventHub() override = default; 50 51 /* Using shared_ptr to enable event modification without adding again */ AddOnChangeEvent(const ChangeEventPtr & changeEvent)52 void AddOnChangeEvent(const ChangeEventPtr& changeEvent) 53 { 54 changeEvents_.emplace_back(changeEvent); 55 } 56 AddOnChangeEventWithPreIndex(const ChangeEventWithPreIndexPtr & changeEventWithPreIndex)57 void AddOnChangeEventWithPreIndex(const ChangeEventWithPreIndexPtr& changeEventWithPreIndex) 58 { 59 changeEventsWithPreIndex_.emplace_back(changeEventWithPreIndex); 60 } 61 SetIndicatorOnChange(ChangeIndicatorEvent && changeEvent)62 void SetIndicatorOnChange(ChangeIndicatorEvent&& changeEvent) 63 { 64 changeIndicatorEvent_ = std::move(changeEvent); 65 } 66 SetIndicatorIndexChangeEvent(IndicatorIndexChangeEvent && indicatorIndexChangeEvent)67 void SetIndicatorIndexChangeEvent(IndicatorIndexChangeEvent&& indicatorIndexChangeEvent) 68 { 69 indicatorIndexChangeEvent_ = std::move(indicatorIndexChangeEvent); 70 } 71 SetChangeDoneEvent(ChangeDoneEvent && changeDoneEvent)72 void SetChangeDoneEvent(ChangeDoneEvent&& changeDoneEvent) 73 { 74 changeDoneEvent_ = std::move(changeDoneEvent); 75 } 76 AddAnimationStartEvent(const AnimationStartEventPtr & animationStartEvent)77 void AddAnimationStartEvent(const AnimationStartEventPtr& animationStartEvent) 78 { 79 animationStartEvents_.emplace_back(animationStartEvent); 80 } 81 AddAnimationEndEvent(const AnimationEndEventPtr & animationEndEvent)82 void AddAnimationEndEvent(const AnimationEndEventPtr& animationEndEvent) 83 { 84 animationEndEvents_.emplace_back(animationEndEvent); 85 } 86 SetGestureSwipeEvent(GestureSwipeEvent && gestureSwipeEvent)87 void SetGestureSwipeEvent(GestureSwipeEvent&& gestureSwipeEvent) 88 { 89 gestureSwipeEvent_ = std::move(gestureSwipeEvent); 90 } 91 AddOnSlectedEvent(const ChangeEventPtr & changeEvent)92 void AddOnSlectedEvent(const ChangeEventPtr& changeEvent) 93 { 94 selectedEvents_.emplace_back(changeEvent); 95 } 96 FireChangeDoneEvent(bool direction)97 void FireChangeDoneEvent(bool direction) 98 { 99 if (changeDoneEvent_) { 100 if (direction) { 101 direction_ = Direction::NEXT; 102 } else { 103 direction_ = Direction::PRE; 104 } 105 changeDoneEvent_(); 106 } 107 } 108 AddOnUnselectedEvent(const ChangeEventPtr & changeEvent)109 void AddOnUnselectedEvent(const ChangeEventPtr& changeEvent) 110 { 111 unselectedEvents_.emplace_back(changeEvent); 112 } 113 FireUnselectedEvent(int32_t index)114 void FireUnselectedEvent(int32_t index) 115 { 116 auto frameNode = GetFrameNode(); 117 TAG_LOGI(AceLogTag::ACE_SWIPER, "Swiper FireUnselectedEvent id:%{public}d, index:%{public}d", 118 frameNode ? frameNode->GetId() : -1, index); 119 ACE_SCOPED_TRACE("Swiper FireUnselectedEvent, id: %d, index: %d", frameNode ? frameNode->GetId() : -1, index); 120 if (!unselectedEvents_.empty()) { 121 std::for_each(unselectedEvents_.begin(), unselectedEvents_.end(), 122 [index](const ChangeEventPtr& changeEvent) { 123 if (!changeEvent || !(*changeEvent)) { 124 return; 125 } 126 auto event = *changeEvent; 127 event(index); 128 }); 129 } 130 } 131 FireChangeEvent(int32_t preIndex,int32_t currentIndex,bool isInLayout)132 void FireChangeEvent(int32_t preIndex, int32_t currentIndex, bool isInLayout) 133 { 134 if (isInLayout) { 135 auto frameNode = GetFrameNode(); 136 CHECK_NULL_VOID(frameNode); 137 auto pipeline = frameNode->GetContext(); 138 CHECK_NULL_VOID(pipeline); 139 pipeline->AddAfterLayoutTask([weak = WeakClaim(this), preIndex, currentIndex]() { 140 auto eventHub = weak.Upgrade(); 141 CHECK_NULL_VOID(eventHub); 142 eventHub->FireJSChangeEvent(preIndex, currentIndex); 143 }); 144 } else { 145 FireJSChangeEvent(preIndex, currentIndex); 146 } 147 148 if (!changeEventsWithPreIndex_.empty()) { 149 std::for_each(changeEventsWithPreIndex_.begin(), changeEventsWithPreIndex_.end(), 150 [preIndex, currentIndex](const ChangeEventWithPreIndexPtr& changeEventWithPreIndex) { 151 if (!changeEventWithPreIndex || !(*changeEventWithPreIndex)) { 152 return; 153 } 154 auto event = *changeEventWithPreIndex; 155 event(preIndex, currentIndex); 156 }); 157 } 158 159 if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) { 160 Recorder::EventParamsBuilder builder; 161 auto host = GetFrameNode(); 162 if (host) { 163 auto id = host->GetInspectorIdValue(""); 164 builder.SetId(id) 165 .SetType(host->GetHostTag()) 166 .SetDescription(host->GetAutoEventParamValue("")) 167 .SetHost(host); 168 if (!id.empty()) { 169 Recorder::NodeDataCache::Get().PutInt(host, id, currentIndex); 170 } 171 } 172 builder.SetIndex(currentIndex); 173 Recorder::EventRecorder::Get().OnChange(std::move(builder)); 174 } 175 } 176 FireIndicatorChangeEvent(int32_t index)177 void FireIndicatorChangeEvent(int32_t index) const 178 { 179 if (changeIndicatorEvent_) { 180 changeIndicatorEvent_(); 181 } 182 } 183 FireIndicatorIndexChangeEvent(int32_t index)184 void FireIndicatorIndexChangeEvent(int32_t index) const 185 { 186 if (indicatorIndexChangeEvent_) { 187 indicatorIndexChangeEvent_(index); 188 } 189 } 190 GetDirection()191 Direction GetDirection() 192 { 193 return direction_; 194 } 195 FireAnimationStartEvent(int32_t index,int32_t targetIndex,const AnimationCallbackInfo & info)196 void FireAnimationStartEvent(int32_t index, int32_t targetIndex, const AnimationCallbackInfo& info) 197 { 198 if (!animationStartEvents_.empty()) { 199 std::for_each(animationStartEvents_.begin(), animationStartEvents_.end(), 200 [index, targetIndex, info](const AnimationStartEventPtr& animationStartEvent) { 201 if (!animationStartEvent || !(*animationStartEvent)) { 202 return; 203 } 204 auto event = *animationStartEvent; 205 event(index, targetIndex, info); 206 }); 207 } 208 // animationEnd callback need to be fired after animationStart callback, use flag for protection. 209 ++aniStartCalledCount_; 210 if (delayCallback_) { 211 auto frameNode = GetFrameNode(); 212 TAG_LOGI(AceLogTag::ACE_SWIPER, "the timing of the animation callback has been corrected id:%{public}d", 213 frameNode ? frameNode->GetId() : -1); 214 delayCallback_(); 215 delayCallback_ = nullptr; 216 } 217 } 218 FireAnimationEndEvent(int32_t index,const AnimationCallbackInfo & info)219 void FireAnimationEndEvent(int32_t index, const AnimationCallbackInfo& info) 220 { 221 if (aniStartCalledCount_ <= 0) { 222 delayCallback_ = [weak = WeakClaim(this), index, info]() { 223 auto hub = weak.Upgrade(); 224 CHECK_NULL_VOID(hub); 225 hub->FireAnimationEndEvent(index, info); 226 }; 227 return; 228 } 229 if (!animationEndEvents_.empty()) { 230 std::for_each(animationEndEvents_.begin(), animationEndEvents_.end(), 231 [index, info](const AnimationEndEventPtr& animationEndEvent) { 232 if (!animationEndEvent || !(*animationEndEvent)) { 233 return; 234 } 235 auto event = *animationEndEvent; 236 event(index, info); 237 }); 238 } 239 --aniStartCalledCount_; 240 } 241 FireAnimationEndOnForceEvent(int32_t index,const AnimationCallbackInfo & info)242 void FireAnimationEndOnForceEvent(int32_t index, const AnimationCallbackInfo& info) 243 { 244 if (aniStartCalledCount_ <= 0) { 245 delayCallback_ = [weak = WeakClaim(this), index, info]() { 246 auto hub = weak.Upgrade(); 247 CHECK_NULL_VOID(hub); 248 hub->FireAnimationEndOnForceEvent(index, info); 249 }; 250 return; 251 } 252 if (animationEndEvents_.empty()) { 253 --aniStartCalledCount_; 254 return; 255 } 256 auto context = GetFrameNode()->GetContext(); 257 CHECK_NULL_VOID(context); 258 context->AddBuildFinishCallBack([this, index, info]() { 259 std::for_each(animationEndEvents_.begin(), animationEndEvents_.end(), 260 [index, info](const AnimationEndEventPtr& animationEndEvent) { 261 if (!animationEndEvent || !(*animationEndEvent)) { 262 return; 263 } 264 auto event = *animationEndEvent; 265 event(index, info); 266 }); 267 }); 268 --aniStartCalledCount_; 269 } 270 FireGestureSwipeEvent(int32_t index,const AnimationCallbackInfo & info)271 void FireGestureSwipeEvent(int32_t index, const AnimationCallbackInfo& info) const 272 { 273 if (gestureSwipeEvent_) { 274 // gestureSwipeEvent_ may be overwrite in its invoke, so copy it first 275 auto event = gestureSwipeEvent_; 276 event(index, info); 277 } 278 } 279 FireSelectedEvent(int32_t index)280 void FireSelectedEvent(int32_t index) 281 { 282 auto frameNode = GetFrameNode(); 283 ACE_SCOPED_TRACE("Swiper FireSelectedEvent, id: %d, index: %d", frameNode ? frameNode->GetId() : -1, index); 284 if (!selectedEvents_.empty()) { 285 std::for_each(selectedEvents_.begin(), selectedEvents_.end(), [index](const ChangeEventPtr& changeEvent) { 286 if (!changeEvent || !(*changeEvent)) { 287 return; 288 } 289 auto event = *changeEvent; 290 event(index); 291 }); 292 } 293 } 294 295 private: FireJSChangeEvent(int32_t preIndex,int32_t index)296 void FireJSChangeEvent(int32_t preIndex, int32_t index) 297 { 298 auto frameNode = GetFrameNode(); 299 ACE_SCOPED_TRACE("Swiper FireChangeEvent, id: %d, preIndex: %d, index: %d", frameNode ? frameNode->GetId() : -1, 300 preIndex, index); 301 if (changeEvents_.empty()) { 302 return; 303 } 304 std::for_each(changeEvents_.begin(), changeEvents_.end(), [index](const ChangeEventPtr& changeEvent) { 305 if (!changeEvent || !(*changeEvent)) { 306 return; 307 } 308 auto event = *changeEvent; 309 event(index); 310 }); 311 } 312 313 Direction direction_; 314 std::list<ChangeEventPtr> unselectedEvents_; 315 std::list<ChangeEventPtr> changeEvents_; 316 std::list<ChangeEventPtr> selectedEvents_; 317 std::list<ChangeEventWithPreIndexPtr> changeEventsWithPreIndex_; 318 ChangeDoneEvent changeDoneEvent_; 319 ChangeIndicatorEvent changeIndicatorEvent_; 320 IndicatorIndexChangeEvent indicatorIndexChangeEvent_; 321 std::list<AnimationStartEventPtr> animationStartEvents_; 322 std::list<AnimationEndEventPtr> animationEndEvents_; 323 GestureSwipeEvent gestureSwipeEvent_; 324 int32_t aniStartCalledCount_ = 0; 325 std::function<void()> delayCallback_; 326 }; 327 328 } // namespace OHOS::Ace::NG 329 330 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_SWIPER_EVENT_HUB_H