• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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