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 29 namespace OHOS::Ace::NG { 30 31 enum class Direction { 32 PRE = 0, 33 NEXT, 34 }; 35 using ChangeIndicatorEvent = std::function<void()>; 36 using ChangeEvent = std::function<void(int32_t index)>; 37 using ChangeEventPtr = std::shared_ptr<ChangeEvent>; 38 using ChangeEventWithPreIndex = std::function<void(int32_t preIndex, int32_t currentIndex)>; 39 using ChangeEventWithPreIndexPtr = std::shared_ptr<ChangeEventWithPreIndex>; 40 using ChangeDoneEvent = std::function<void()>; 41 42 class SwiperEventHub : public EventHub { 43 DECLARE_ACE_TYPE(SwiperEventHub, EventHub) 44 45 public: 46 SwiperEventHub() = default; 47 ~SwiperEventHub() override = default; 48 49 /* Using shared_ptr to enable event modification without adding again */ AddOnChangeEvent(const ChangeEventPtr & changeEvent)50 void AddOnChangeEvent(const ChangeEventPtr& changeEvent) 51 { 52 changeEvents_.emplace_back(changeEvent); 53 } 54 AddOnChangeEventWithPreIndex(const ChangeEventWithPreIndexPtr & changeEventWithPreIndex)55 void AddOnChangeEventWithPreIndex(const ChangeEventWithPreIndexPtr& changeEventWithPreIndex) 56 { 57 changeEventsWithPreIndex_.emplace_back(changeEventWithPreIndex); 58 } 59 SetIndicatorOnChange(ChangeIndicatorEvent && changeEvent)60 void SetIndicatorOnChange(ChangeIndicatorEvent&& changeEvent) 61 { 62 changeIndicatorEvent_ = std::move(changeEvent); 63 } 64 SetChangeDoneEvent(ChangeDoneEvent && changeDoneEvent)65 void SetChangeDoneEvent(ChangeDoneEvent&& changeDoneEvent) 66 { 67 changeDoneEvent_ = std::move(changeDoneEvent); 68 } 69 AddAnimationStartEvent(const AnimationStartEventPtr & animationStartEvent)70 void AddAnimationStartEvent(const AnimationStartEventPtr& animationStartEvent) 71 { 72 animationStartEvents_.emplace_back(animationStartEvent); 73 } 74 AddAnimationEndEvent(const AnimationEndEventPtr & animationEndEvent)75 void AddAnimationEndEvent(const AnimationEndEventPtr& animationEndEvent) 76 { 77 animationEndEvents_.emplace_back(animationEndEvent); 78 } 79 SetGestureSwipeEvent(GestureSwipeEvent && gestureSwipeEvent)80 void SetGestureSwipeEvent(GestureSwipeEvent&& gestureSwipeEvent) 81 { 82 gestureSwipeEvent_ = std::move(gestureSwipeEvent); 83 } 84 FireChangeDoneEvent(bool direction)85 void FireChangeDoneEvent(bool direction) 86 { 87 if (changeDoneEvent_) { 88 if (direction) { 89 direction_ = Direction::NEXT; 90 } else { 91 direction_ = Direction::PRE; 92 } 93 changeDoneEvent_(); 94 } 95 } 96 FireChangeEvent(int32_t preIndex,int32_t currentIndex)97 void FireChangeEvent(int32_t preIndex, int32_t currentIndex) const 98 { 99 ACE_SCOPED_TRACE("Swiper FireChangeEvent, preIndex: %d currentIndex: %d eventSize: %zu", 100 preIndex, currentIndex, changeEvents_.size() + changeEventsWithPreIndex_.size()); 101 if (!changeEvents_.empty()) { 102 std::for_each( 103 changeEvents_.begin(), changeEvents_.end(), [currentIndex](const ChangeEventPtr& changeEvent) { 104 auto event = *changeEvent; 105 event(currentIndex); 106 }); 107 } 108 if (!changeEventsWithPreIndex_.empty()) { 109 std::for_each(changeEventsWithPreIndex_.begin(), changeEventsWithPreIndex_.end(), 110 [preIndex, currentIndex](const ChangeEventWithPreIndexPtr& changeEventWithPreIndex) { 111 auto event = *changeEventWithPreIndex; 112 event(preIndex, currentIndex); 113 }); 114 } 115 116 if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) { 117 Recorder::EventParamsBuilder builder; 118 auto host = GetFrameNode(); 119 if (host) { 120 auto id = host->GetInspectorIdValue(""); 121 builder.SetId(id).SetType(host->GetHostTag()).SetDescription(host->GetAutoEventParamValue("")); 122 if (!id.empty()) { 123 Recorder::NodeDataCache::Get().PutInt(host, id, currentIndex); 124 } 125 } 126 builder.SetIndex(currentIndex); 127 Recorder::EventRecorder::Get().OnChange(std::move(builder)); 128 } 129 } 130 FireIndicatorChangeEvent(int32_t index)131 void FireIndicatorChangeEvent(int32_t index) const 132 { 133 if (changeIndicatorEvent_) { 134 changeIndicatorEvent_(); 135 } 136 } 137 GetDirection()138 Direction GetDirection() 139 { 140 return direction_; 141 } 142 FireAnimationStartEvent(int32_t index,int32_t targetIndex,const AnimationCallbackInfo & info)143 void FireAnimationStartEvent(int32_t index, int32_t targetIndex, const AnimationCallbackInfo& info) 144 { 145 if (!animationStartEvents_.empty()) { 146 std::for_each(animationStartEvents_.begin(), animationStartEvents_.end(), 147 [index, targetIndex, info](const AnimationStartEventPtr& animationStartEvent) { 148 auto event = *animationStartEvent; 149 event(index, targetIndex, info); 150 }); 151 } 152 // animationEnd callback need to be fired after animationStart callback, use flag for protection. 153 ++aniStartCalledCount_; 154 if (delayCallback_) { 155 TAG_LOGI(AceLogTag::ACE_SWIPER, "the timing of the animation callback has been corrected"); 156 delayCallback_(); 157 delayCallback_ = nullptr; 158 } 159 } 160 FireAnimationEndEvent(int32_t index,const AnimationCallbackInfo & info)161 void FireAnimationEndEvent(int32_t index, const AnimationCallbackInfo& info) 162 { 163 if (aniStartCalledCount_ <= 0) { 164 delayCallback_ = [weak = WeakClaim(this), index, info]() { 165 auto hub = weak.Upgrade(); 166 CHECK_NULL_VOID(hub); 167 hub->FireAnimationEndEvent(index, info); 168 }; 169 return; 170 } 171 if (!animationEndEvents_.empty()) { 172 std::for_each(animationEndEvents_.begin(), animationEndEvents_.end(), 173 [index, info](const AnimationEndEventPtr& animationEndEvent) { 174 auto event = *animationEndEvent; 175 event(index, info); 176 }); 177 } 178 --aniStartCalledCount_; 179 } 180 FireAnimationEndOnForceEvent(int32_t index,const AnimationCallbackInfo & info)181 void FireAnimationEndOnForceEvent(int32_t index, const AnimationCallbackInfo& info) 182 { 183 if (aniStartCalledCount_ <= 0) { 184 delayCallback_ = [weak = WeakClaim(this), index, info]() { 185 auto hub = weak.Upgrade(); 186 CHECK_NULL_VOID(hub); 187 hub->FireAnimationEndOnForceEvent(index, info); 188 }; 189 return; 190 } 191 if (!animationEndEvents_.empty()) { 192 auto context = GetFrameNode()->GetContext(); 193 CHECK_NULL_VOID(context); 194 context->AddBuildFinishCallBack([this, index, info]() { 195 std::for_each(animationEndEvents_.begin(), animationEndEvents_.end(), 196 [index, info](const AnimationEndEventPtr& animationEndEvent) { 197 auto event = *animationEndEvent; 198 event(index, info); 199 }); 200 }); 201 } 202 --aniStartCalledCount_; 203 } 204 FireGestureSwipeEvent(int32_t index,const AnimationCallbackInfo & info)205 void FireGestureSwipeEvent(int32_t index, const AnimationCallbackInfo& info) const 206 { 207 if (gestureSwipeEvent_) { 208 // gestureSwipeEvent_ may be overwrite in its invoke, so copy it first 209 auto event = gestureSwipeEvent_; 210 event(index, info); 211 } 212 } 213 214 private: 215 Direction direction_; 216 std::list<ChangeEventPtr> changeEvents_; 217 std::list<ChangeEventWithPreIndexPtr> changeEventsWithPreIndex_; 218 ChangeDoneEvent changeDoneEvent_; 219 ChangeIndicatorEvent changeIndicatorEvent_; 220 std::list<AnimationStartEventPtr> animationStartEvents_; 221 std::list<AnimationEndEventPtr> animationEndEvents_; 222 GestureSwipeEvent gestureSwipeEvent_; 223 int32_t aniStartCalledCount_ = 0; 224 std::function<void()> delayCallback_; 225 }; 226 227 } // namespace OHOS::Ace::NG 228 229 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_SWIPER_EVENT_HUB_H