1 /*
2  * Copyright (c) 2020-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 OHOS_ACELITE_EVENT_LISTENER_H
17 #define OHOS_ACELITE_EVENT_LISTENER_H
18 
19 #include "ace_log.h"
20 #include "async_task_manager.h"
21 #include "event_util.h"
22 #include "js_fwk_common.h"
23 #include "keys.h"
24 #include "non_copyable.h"
25 #include "ui_checkbox.h"
26 #include "ui_list.h"
27 #include "ui_radio_button.h"
28 #include "ui_scroll_view.h"
29 #include "ui_slider.h"
30 #include "ui_toggle_button.h"
31 #include "ui_edit_text.h"
32 
33 namespace OHOS {
34 namespace ACELite {
35 class StateChangeListener final : public UICheckBox::OnChangeListener {
36 public:
37     ACE_DISALLOW_COPY_AND_MOVE(StateChangeListener);
StateChangeListener(jerry_value_t fn)38     explicit StateChangeListener(jerry_value_t fn)
39         : fn_(jerry_acquire_value(fn)), state_(false), isChanging_(false) {}
40 
OnChange(UICheckBox::UICheckBoxState state)41     bool OnChange(UICheckBox::UICheckBoxState state) override
42     {
43         bool stateRes = (state == UICheckBox::UICheckBoxState::SELECTED);
44         if (stateRes == state_) {
45             return true;
46         }
47         state_ = stateRes;
48         if (isChanging_) {
49             return false;
50         }
51         isChanging_ = true;
52         jerry_value_t args[1];
53         jerry_value_t resultProp = jerry_create_boolean(state_);
54         args[0] = jerry_create_object();
55         const char * const checked = "checked";
56         ReleaseJerryValue(jerryx_set_property_str(args[0], checked, resultProp), resultProp, VA_ARG_END_FLAG);
57         jerry_value_t globalObject = jerry_get_global_object();
58         jerry_value_t appViewModel = jerryx_get_property_str(globalObject, ATTR_APP);
59         if (jerry_value_is_function(fn_)) {
60             CallJSFunctionAutoRelease(fn_, appViewModel, args, 1);
61         }
62         ReleaseJerryValue(globalObject, appViewModel, args[0], VA_ARG_END_FLAG);
63         isChanging_ = false;
64         return true;
65     }
66 
SetState(bool state)67     void SetState(bool state)
68     {
69         state_ = state;
70     }
71 
~StateChangeListener()72     ~StateChangeListener()
73     {
74         jerry_release_value(fn_);
75     }
76 
77 private:
78     jerry_value_t fn_;
79     bool state_;
80     bool isChanging_; // the flag to avoid change event cycle execute
81 };
82 
83 
84 class ValueChangeListener final : public OHOS::UIEditText::OnChangeListener {
85 public:
86     ACE_DISALLOW_COPY_AND_MOVE(ValueChangeListener);
ValueChangeListener(jerry_value_t fn)87     explicit ValueChangeListener(jerry_value_t fn)
88         : fn_(jerry_acquire_value(fn)) {}
89 
~ValueChangeListener()90     ~ValueChangeListener()
91     {
92         jerry_release_value(fn_);
93     }
94 
95     void OnChange(UIView& view, const char* value) override;
96 private:
97     jerry_value_t fn_;
98 };
99 
100 
101 class ViewOnClickListener final : public UIView::OnClickListener {
102 public:
103     ACE_DISALLOW_COPY_AND_MOVE(ViewOnClickListener);
104 
ViewOnClickListener(jerry_value_t vm,jerry_value_t fn,bool isStopPropagation)105     ViewOnClickListener(jerry_value_t vm, jerry_value_t fn, bool isStopPropagation)
106         : changeListener_(nullptr),
107           vm_(jerry_acquire_value(vm)),
108           fn_(jerry_acquire_value(fn)),
109           isStopPropagation_(isStopPropagation) {}
110 
~ViewOnClickListener()111     ~ViewOnClickListener()
112     {
113         AsyncTaskManager::GetInstance().CancelWithContext(this);
114         jerry_release_value(vm_);
115         jerry_release_value(fn_);
116     }
117 
OnClick(UIView & view,const ClickEvent & event)118     bool OnClick(UIView& view, const ClickEvent &event) override
119     {
120         if (changeListener_) {
121             UICheckBox *checkbox = reinterpret_cast<UICheckBox *>(&view);
122             changeListener_->OnChange(checkbox->GetState());
123         }
124         if (JSUndefined::Is(fn_)) {
125             return isStopPropagation_;
126         }
127         JSValue arg = EventUtil::CreateEvent(EventUtil::EVENT_CLICK, view, event);
128         EventUtil::InvokeCallback(vm_, fn_, arg, this);
129 
130         return isStopPropagation_;
131     }
132 
SetComponentListener(StateChangeListener * changeListener)133     void SetComponentListener(StateChangeListener *changeListener)
134     {
135         changeListener_ = changeListener;
136     }
137 
138 private:
139     StateChangeListener *changeListener_;
140     jerry_value_t vm_;
141     jerry_value_t fn_;
142     bool isStopPropagation_;
143 };
144 
145 class ViewOnLongPressListener final : public UIView::OnLongPressListener {
146 public:
147     ACE_DISALLOW_COPY_AND_MOVE(ViewOnLongPressListener);
ViewOnLongPressListener(jerry_value_t vm,jerry_value_t fn,bool isStopPropagation)148     ViewOnLongPressListener(jerry_value_t vm, jerry_value_t fn, bool isStopPropagation)
149         : vm_(jerry_acquire_value(vm)), fn_(jerry_acquire_value(fn)), isStopPropagation_(isStopPropagation) {}
150 
~ViewOnLongPressListener()151     ~ViewOnLongPressListener()
152     {
153         AsyncTaskManager::GetInstance().CancelWithContext(this);
154         jerry_release_value(vm_);
155         jerry_release_value(fn_);
156     }
157 
OnLongPress(UIView & view,const LongPressEvent & event)158     bool OnLongPress(UIView& view, const LongPressEvent &event) override
159     {
160         if (jerry_value_is_undefined(fn_)) {
161             return isStopPropagation_;
162         }
163 
164         JSValue arg = EventUtil::CreateEvent(EventUtil::EVENT_LONGPRESS, view, event);
165         EventUtil::InvokeCallback(vm_, fn_, arg, this);
166 
167         return isStopPropagation_;
168     }
169     jerry_value_t vm_;
170     jerry_value_t fn_;
171     bool isStopPropagation_;
172 };
173 
174 #ifdef JS_EXTRA_EVENT_SUPPORT
175 
176 class KeyBoardEventListener final : public RootView::OnKeyActListener {
177 public:
178     ACE_DISALLOW_COPY_AND_MOVE(KeyBoardEventListener);
179     KeyBoardEventListener(jerry_value_t fn, const uint16_t id);
180     ~KeyBoardEventListener();
181     bool OnKeyAct(UIView &view, const KeyEvent &event) override;
182 
183 private:
184     jerry_value_t fn_;
185     uint16_t id_;
186 };
187 #endif
188 
189 class ViewOnTouchListener final : public UIView::OnDragListener {
190 public:
191     ACE_DISALLOW_COPY_AND_MOVE(ViewOnTouchListener);
ViewOnTouchListener(jerry_value_t vm,bool isStopPropagation)192     ViewOnTouchListener(jerry_value_t vm, bool isStopPropagation)
193         : vm_(jerry_acquire_value(vm)),
194           bindTouchStartFunc_(UNDEFINED),
195           bindTouchMoveFunc_(UNDEFINED),
196           bindTouchEndFunc_(UNDEFINED),
197           bindSwipeFunc_(UNDEFINED),
198           isStopPropagation_(isStopPropagation)
199     {
200     }
201 
~ViewOnTouchListener()202     ~ViewOnTouchListener()
203     {
204         AsyncTaskManager::GetInstance().CancelWithContext(this);
205         jerry_release_value(vm_);
206         jerry_release_value(bindTouchStartFunc_);
207         jerry_release_value(bindTouchMoveFunc_);
208         jerry_release_value(bindTouchEndFunc_);
209         jerry_release_value(bindSwipeFunc_);
210     }
211 
212     void SetStopPropagation(bool isStopPropogation);
213     bool OnDragStart(UIView& view, const DragEvent& event) override;
214     bool OnDrag(UIView& view, const DragEvent& event) override;
215     bool OnDragEnd(UIView& view, const DragEvent &event) override;
216     void SetBindTouchStartFuncName(jerry_value_t bindTouchStartFunc);
217     void SetBindTouchMoveFuncName(jerry_value_t bindTouchMoveFunc);
218     void SetBindTouchEndFuncName(jerry_value_t bindTouchEndFunc);
219     void SetBindSwipeFuncName(jerry_value_t bindSwipeFunc);
220 
221 private:
222     jerry_value_t vm_;
223     jerry_value_t bindTouchStartFunc_;
224     jerry_value_t bindTouchMoveFunc_;
225     jerry_value_t bindTouchEndFunc_;
226     jerry_value_t bindSwipeFunc_;
227     bool isStopPropagation_;
228 };
229 
230 class SliderEventListener final : public UISlider::UISliderEventListener {
231 public:
232     ACE_DISALLOW_COPY_AND_MOVE(SliderEventListener);
SliderEventListener()233     SliderEventListener() : bindChangeFunc_(UNDEFINED) {}
~SliderEventListener()234     ~SliderEventListener()
235     {
236         jerry_release_value(bindChangeFunc_);
237     }
OnChange(int32_t progress)238     void OnChange(int32_t progress) override
239     {
240         jerry_value_t knobValue = jerry_create_number(progress);
241         jerry_value_t args[1];
242         args[0] = jerry_create_object();
243         jerry_value_t result1 = jerryx_set_property_str(args[0], "value", knobValue);
244         // progress will be deprecated in next versions.
245         jerry_value_t result2 = jerryx_set_property_str(args[0], "progress", knobValue);
246         if (!jerry_value_is_error(result1) && !jerry_value_is_error(result2)) {
247             CallJSFunctionAutoRelease(bindChangeFunc_, UNDEFINED, args, 1);
248         }
249         ReleaseJerryValue(result1, result2, args[0], knobValue, VA_ARG_END_FLAG);
250     }
251 
SetBindChangeFuncName(jerry_value_t bindChageFunc)252     void SetBindChangeFuncName(jerry_value_t bindChageFunc)
253     {
254         bindChangeFunc_ = jerry_acquire_value(bindChageFunc);
255     }
256 
257 private:
258     jerry_value_t bindChangeFunc_;
259 };
260 
261 class ListEventListener final : public ListScrollListener {
262 public:
263     ACE_DISALLOW_COPY_AND_MOVE(ListEventListener);
ListEventListener()264     ListEventListener()
265         : bindScrollStartFunc_(UNDEFINED),
266           bindScrollEndFunc_(UNDEFINED),
267           bindScrollSelectedFunc_(UNDEFINED),
268           bindScrollTopFunc_(UNDEFINED),
269           bindScrollBottomFunc_(UNDEFINED)
270     {
271     }
~ListEventListener()272     ~ListEventListener()
273     {
274         ReleaseJerryValue(bindScrollStartFunc_, bindScrollEndFunc_, bindScrollSelectedFunc_, bindScrollTopFunc_,
275             bindScrollBottomFunc_, VA_ARG_END_FLAG);
276     }
277 
278     void EventExcute(const int16_t index, jerry_value_t bindScrollFunc) const;
279 
280 // list specific event switch
281 #ifdef FEATURE_LIST_SPECIFIC_EVENT_ENABLE
OnScrollStart(int16_t index,UIView * view)282     void OnScrollStart(int16_t index, UIView *view) override
283     {
284         EventExcute(index, bindScrollStartFunc_);
285     }
OnItemSelected(int16_t index,UIView * view)286     void OnItemSelected(int16_t index, UIView *view) override
287     {
288         EventExcute(index, bindScrollSelectedFunc_);
289     }
SetBindScrollStartFuncName(jerry_value_t bindScrollStartFunc)290     void SetBindScrollStartFuncName(jerry_value_t bindScrollStartFunc)
291     {
292         if (!jerry_value_is_undefined(bindScrollStartFunc)) {
293             bindScrollStartFunc_ = jerry_acquire_value(bindScrollStartFunc);
294         }
295     }
SetBindScrollItemSelectedFuncName(jerry_value_t bindScrollItemSelectedFunc)296     void SetBindScrollItemSelectedFuncName(jerry_value_t bindScrollItemSelectedFunc)
297     {
298         if (!jerry_value_is_undefined(bindScrollItemSelectedFunc)) {
299             bindScrollSelectedFunc_ = jerry_acquire_value(bindScrollItemSelectedFunc);
300         }
301     }
302 #endif // FEATURE_LIST_SPECIFIC_EVENT_ENABLE
303 
OnScrollEnd(int16_t index,UIView * view)304     void OnScrollEnd(int16_t index, UIView* view) override
305     {
306         EventExcute(index, bindScrollEndFunc_);
307     }
308 
SetBindScrollEndFuncName(jerry_value_t bindScrollEndFunc)309     void SetBindScrollEndFuncName(jerry_value_t bindScrollEndFunc)
310     {
311         if (!jerry_value_is_undefined(bindScrollEndFunc)) {
312             bindScrollEndFunc_ = jerry_acquire_value(bindScrollEndFunc);
313         }
314     }
315 
OnScrollTop(int16_t index,UIView * view)316     void OnScrollTop(int16_t index, UIView* view) override
317     {
318         EventExcute(index, bindScrollTopFunc_);
319     }
320 
SetBindScrollTopFuncName(jerry_value_t bindScrollTopFunc)321     void SetBindScrollTopFuncName(jerry_value_t bindScrollTopFunc)
322     {
323         if (!jerry_value_is_undefined(bindScrollTopFunc)) {
324             bindScrollTopFunc_ = jerry_acquire_value(bindScrollTopFunc);
325         }
326     }
327 
OnScrollBottom(int16_t index,UIView * view)328     void OnScrollBottom(int16_t index, UIView* view) override
329     {
330         EventExcute(index, bindScrollBottomFunc_);
331     }
332 
SetBindScrollBottomFuncName(jerry_value_t bindScrollBottomFunc)333     void SetBindScrollBottomFuncName(jerry_value_t bindScrollBottomFunc)
334     {
335         if (!jerry_value_is_undefined(bindScrollBottomFunc)) {
336             bindScrollBottomFunc_ = jerry_acquire_value(bindScrollBottomFunc);
337         }
338     }
339 
340 private:
341     static constexpr int8_t ARGS_LEN = 2;
342     jerry_value_t bindScrollStartFunc_;
343     jerry_value_t bindScrollEndFunc_;
344     jerry_value_t bindScrollSelectedFunc_;
345     jerry_value_t bindScrollTopFunc_;
346     jerry_value_t bindScrollBottomFunc_;
347 };
348 } // namespace ACELite
349 } // namespace OHOS
350 #endif // OHOS_ACELITE_EVENT_LISTENER_H
351