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