• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 #include "frameworks/bridge/declarative_frontend/jsview/js_sliding_panel.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <iterator>
21 
22 #include "base/log/ace_scoring_log.h"
23 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
24 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
25 #include "bridge/declarative_frontend/jsview/models/sliding_panel_model_impl.h"
26 #include "core/components_ng/base/view_abstract_model_ng.h"
27 #include "core/components_ng/pattern/panel/sliding_panel_model.h"
28 #include "core/components_ng/pattern/panel/sliding_panel_model_ng.h"
29 
30 namespace OHOS::Ace {
31 
32 std::unique_ptr<SlidingPanelModel> SlidingPanelModel::instance_ = nullptr;
33 std::mutex SlidingPanelModel::mutex_;
34 
GetInstance()35 SlidingPanelModel* SlidingPanelModel::GetInstance()
36 {
37     if (!instance_) {
38         std::lock_guard<std::mutex> lock(mutex_);
39         if (!instance_) {
40 #ifdef NG_BUILD
41             instance_.reset(new NG::SlidingPanelModelNG());
42 #else
43             if (Container::IsCurrentUseNewPipeline()) {
44                 instance_.reset(new NG::SlidingPanelModelNG());
45             } else {
46                 instance_.reset(new Framework::SlidingPanelModelImpl());
47             }
48 #endif
49         }
50     }
51     return instance_.get();
52 }
53 
54 } // namespace OHOS::Ace
55 namespace OHOS::Ace::Framework {
56 namespace {
57 
58 const std::vector<PanelMode> PANEL_MODES = { PanelMode::MINI, PanelMode::HALF, PanelMode::FULL, PanelMode::AUTO };
59 const std::vector<PanelType> PANEL_TYPES = { PanelType::MINI_BAR, PanelType::FOLDABLE_BAR, PanelType::TEMP_DISPLAY,
60     PanelType::CUSTOM };
61 const std::vector<VisibleType> PANEL_VISIBLE_TYPES = { VisibleType::GONE, VisibleType::VISIBLE,
62     VisibleType::INVISIBLE };
63 
64 const static bool DEFAULT_HASDRAGBAR = true;
65 const static bool DEFAULT_SHOWCLOSEICON = false;
66 const static PanelMode DEFAULT_PANELMODE = PanelMode::HALF;
67 const static PanelType DEFAULT_PANELTYPE = PanelType::FOLDABLE_BAR;
68 const static int32_t PLATFORM_VERSION_TEN = 10;
69 
70 } // namespace
71 
Create(const JSCallbackInfo & info)72 void JSSlidingPanel::Create(const JSCallbackInfo& info)
73 {
74     if (info.Length() > 0 && info[0]->IsBoolean()) {
75         bool isShow = true;
76         isShow = info[0]->ToBoolean();
77         SlidingPanelModel::GetInstance()->Create(isShow);
78         return;
79     }
80 }
81 
JSBind(BindingTarget globalObj)82 void JSSlidingPanel::JSBind(BindingTarget globalObj)
83 {
84     JSClass<JSSlidingPanel>::Declare("Panel");
85     MethodOptions opt = MethodOptions::NONE;
86     JSClass<JSSlidingPanel>::StaticMethod("create", &JSSlidingPanel::Create, opt);
87     JSClass<JSSlidingPanel>::StaticMethod("pop", &JSSlidingPanel::Pop, opt);
88     JSClass<JSSlidingPanel>::StaticMethod("dragBar", &JSSlidingPanel::SetHasDragBar, opt);
89     JSClass<JSSlidingPanel>::StaticMethod("show", &JSSlidingPanel::SetShow, opt);
90     JSClass<JSSlidingPanel>::StaticMethod("showCloseIcon", &JSSlidingPanel::SetShowCloseIcon, opt);
91     JSClass<JSSlidingPanel>::StaticMethod("mode", &JSSlidingPanel::SetPanelMode, opt);
92     JSClass<JSSlidingPanel>::StaticMethod("type", &JSSlidingPanel::SetPanelType, opt);
93     JSClass<JSSlidingPanel>::StaticMethod("customHeight", &JSSlidingPanel::SetCustomHeight, opt);
94     JSClass<JSSlidingPanel>::StaticMethod("backgroundMask", &JSSlidingPanel::SetBackgroundMask, opt);
95     JSClass<JSSlidingPanel>::StaticMethod("fullHeight", &JSSlidingPanel::SetFullHeight, opt);
96     JSClass<JSSlidingPanel>::StaticMethod("halfHeight", &JSSlidingPanel::SetHalfHeight, opt);
97     JSClass<JSSlidingPanel>::StaticMethod("miniHeight", &JSSlidingPanel::SetMiniHeight, opt);
98     JSClass<JSSlidingPanel>::StaticMethod("backgroundColor", JsBackgroundColor);
99     JSClass<JSSlidingPanel>::StaticMethod("border", JsPanelBorder);
100     JSClass<JSSlidingPanel>::StaticMethod("borderWidth", JsPanelBorderWidth);
101     JSClass<JSSlidingPanel>::StaticMethod("borderColor", JsPanelBorderColor);
102     JSClass<JSSlidingPanel>::StaticMethod("borderStyle", JsPanelBorderStyle);
103     JSClass<JSSlidingPanel>::StaticMethod("borderRadius", JsPanelBorderRadius);
104 
105     JSClass<JSSlidingPanel>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
106     JSClass<JSSlidingPanel>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
107     JSClass<JSSlidingPanel>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
108     JSClass<JSSlidingPanel>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
109     JSClass<JSSlidingPanel>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
110     JSClass<JSSlidingPanel>::StaticMethod("onChange", &JSSlidingPanel::SetOnSizeChange);
111     JSClass<JSSlidingPanel>::StaticMethod("onHeightChange", &JSSlidingPanel::SetOnHeightChange);
112     JSClass<JSSlidingPanel>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
113     JSClass<JSSlidingPanel>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
114 
115     JSClass<JSSlidingPanel>::InheritAndBind<JSContainerBase>(globalObj);
116 }
117 
SetBackgroundMask(const JSCallbackInfo & info)118 void JSSlidingPanel::SetBackgroundMask(const JSCallbackInfo& info)
119 {
120     if (info.Length() < 1) {
121         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
122         return;
123     }
124     Color color;
125     if (!ParseJsColor(info[0], color)) {
126         return;
127     }
128 
129     SlidingPanelModel::GetInstance()->SetBackgroundMask(color);
130 }
131 
ParsePanelRadius(const JSRef<JSVal> & args,BorderRadius & borderRadius)132 void JSSlidingPanel::ParsePanelRadius(const JSRef<JSVal>& args, BorderRadius& borderRadius)
133 {
134     if (!args->IsObject() && !args->IsNumber() && !args->IsString()) {
135         LOGE("args need a object or number or string. %{public}s", args->ToString().c_str());
136         return;
137     }
138 
139     CalcDimension radius;
140     if (ParseJsDimensionVp(args, radius)) {
141         borderRadius.radiusTopLeft = radius;
142         borderRadius.radiusTopRight = radius;
143         borderRadius.radiusBottomLeft = radius;
144         borderRadius.radiusBottomRight = radius;
145         return;
146     }
147     if (args->IsObject()) {
148         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
149         auto valueTopLeft = object->GetProperty("topLeft");
150         if (!valueTopLeft->IsUndefined()) {
151             ParseJsDimensionVp(valueTopLeft, borderRadius.radiusTopLeft);
152         }
153         auto valueTopRight = object->GetProperty("topRight");
154         if (!valueTopRight->IsUndefined()) {
155             ParseJsDimensionVp(valueTopRight, borderRadius.radiusTopRight);
156         }
157         auto valueBottomLeft = object->GetProperty("bottomLeft");
158         if (!valueBottomLeft->IsUndefined()) {
159             ParseJsDimensionVp(valueBottomLeft, borderRadius.radiusBottomLeft);
160         }
161         auto valueBottomRight = object->GetProperty("bottomRight");
162         if (!valueBottomRight->IsUndefined()) {
163             ParseJsDimensionVp(valueBottomRight, borderRadius.radiusBottomRight);
164         }
165         return;
166     }
167     LOGE("args format error. %{public}s", args->ToString().c_str());
168 }
169 
JsPanelBorderRadius(const JSCallbackInfo & info)170 void JSSlidingPanel::JsPanelBorderRadius(const JSCallbackInfo& info)
171 {
172     BorderRadius borderRadius;
173     ParsePanelRadius(info[0], borderRadius);
174 
175     ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius.radiusTopLeft, borderRadius.radiusTopRight,
176         borderRadius.radiusBottomLeft, borderRadius.radiusBottomRight);
177 }
178 
JsBackgroundColor(const JSCallbackInfo & info)179 void JSSlidingPanel::JsBackgroundColor(const JSCallbackInfo& info)
180 {
181     if (info.Length() < 1) {
182         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
183         return;
184     }
185     Color backgroundColor;
186     if (!ParseJsColor(info[0], backgroundColor)) {
187         return;
188     }
189 
190     SlidingPanelModel::GetInstance()->SetBackgroundColor(backgroundColor);
191 }
192 
JsPanelBorderColor(const JSCallbackInfo & info)193 void JSSlidingPanel::JsPanelBorderColor(const JSCallbackInfo& info)
194 {
195     if (info.Length() < 1) {
196         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
197         return;
198     }
199     Color borderColor;
200     if (!ParseJsColor(info[0], borderColor)) {
201         return;
202     }
203 
204     SlidingPanelModel::GetInstance()->SetBorderColor(borderColor);
205 }
206 
JsPanelBorderWidth(const JSCallbackInfo & info)207 void JSSlidingPanel::JsPanelBorderWidth(const JSCallbackInfo& info)
208 {
209     if (info.Length() < 1) {
210         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
211         return;
212     }
213     CalcDimension borderWidth;
214     if (!ParseJsDimensionVp(info[0], borderWidth)) {
215         return;
216     }
217     SlidingPanelModel::GetInstance()->SetBorderWidth(borderWidth);
218 }
219 
JsPanelBorderStyle(int32_t style)220 void JSSlidingPanel::JsPanelBorderStyle(int32_t style)
221 {
222     BorderStyle borderStyle = BorderStyle::SOLID;
223     if (style > 0 && style < 4) {
224         borderStyle = static_cast<BorderStyle>(style);
225     }
226     SlidingPanelModel::GetInstance()->SetBorderStyle(borderStyle);
227 }
228 
JsPanelBorder(const JSCallbackInfo & info)229 void JSSlidingPanel::JsPanelBorder(const JSCallbackInfo& info)
230 {
231     if (info.Length() < 1) {
232         LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
233         return;
234     }
235     if (!info[0]->IsObject()) {
236         LOGE("arg is not a object.");
237         return;
238     }
239 
240     auto argsPtrItem = JSRef<JSObject>::Cast(info[0]);
241     CalcDimension width = CalcDimension(0.0, DimensionUnit::VP);
242     ParseJsDimensionVp(argsPtrItem->GetProperty("width"), width);
243     SlidingPanelModel::GetInstance()->SetBorderWidth(width);
244 
245     BorderRadius borderRadius;
246     ParsePanelRadius(argsPtrItem->GetProperty("radius"), borderRadius);
247     ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius.radiusTopLeft, borderRadius.radiusTopRight,
248         borderRadius.radiusBottomLeft, borderRadius.radiusBottomRight);
249 
250     auto styleJsValue = argsPtrItem->GetProperty("style");
251     auto borderStyle = BorderStyle::SOLID;
252     if (!styleJsValue->IsUndefined() && styleJsValue->IsNumber()) {
253         auto styleValue = styleJsValue->ToNumber<uint32_t>();
254         if (styleValue > 0 && styleValue < 4) {
255             borderStyle = static_cast<BorderStyle>(styleValue);
256         }
257     }
258     SlidingPanelModel::GetInstance()->SetBorderStyle(borderStyle);
259 
260     Color borderColor;
261     ParseJsColor(argsPtrItem->GetProperty("color"), borderColor);
262     SlidingPanelModel::GetInstance()->SetBorderColor(borderColor);
263 }
264 
SetOnSizeChange(const JSCallbackInfo & args)265 void JSSlidingPanel::SetOnSizeChange(const JSCallbackInfo& args)
266 {
267     if (!args[0]->IsFunction()) {
268         return;
269     }
270 
271     auto onSizeChangeNG = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](
272                               const BaseEventInfo* info) {
273         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
274         auto eventInfo = TypeInfoHelper::DynamicCast<SlidingPanelSizeChangeEvent>(info);
275         if (!eventInfo) {
276             return;
277         }
278         auto params = ConvertToJSValues(eventInfo->GetWidth(), eventInfo->GetHeight(), eventInfo->GetMode());
279         ACE_SCORING_EVENT("SlidingPanel.OnSizeChange");
280         func->Call(JSRef<JSObject>(), params.size(), params.data());
281     };
282     SlidingPanelModel::GetInstance()->SetOnSizeChange(onSizeChangeNG);
283 
284     args.ReturnSelf();
285 }
286 
SetOnHeightChange(const JSCallbackInfo & args)287 void JSSlidingPanel::SetOnHeightChange(const JSCallbackInfo& args)
288 {
289     if (args.Length() < 1) {
290         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
291         return;
292     }
293     if (!args[0]->IsFunction()) {
294         return;
295     }
296 
297     auto onHeightChangeCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
298     auto onHeightChange = [execCtx = args.GetExecutionContext(), func = std::move(onHeightChangeCallback)](
299                               int32_t height) {
300         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
301         ACE_SCORING_EVENT("OnHeightChange");
302         JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(height));
303         func->ExecuteJS(1, &param);
304     };
305 
306     SlidingPanelModel::GetInstance()->SetOnHeightChange(std::move(onHeightChange));
307 
308     args.ReturnSelf();
309 }
310 
SetHasDragBar(const JSCallbackInfo & info)311 void JSSlidingPanel::SetHasDragBar(const JSCallbackInfo& info)
312 {
313     if (info.Length() < 1) {
314         LOGE("The info is wrong, it is supposed to have at least 1 argument");
315         return;
316     }
317     auto hasDragBar = DEFAULT_HASDRAGBAR;
318     if (info[0]->IsBoolean()) {
319         hasDragBar = info[0]->ToBoolean();
320     }
321     SlidingPanelModel::GetInstance()->SetHasDragBar(hasDragBar);
322 }
323 
SetShowCloseIcon(const JSCallbackInfo & info)324 void JSSlidingPanel::SetShowCloseIcon(const JSCallbackInfo& info)
325 {
326     if (info.Length() < 1) {
327         LOGE("The info is wrong, it is supposed to have at least 1 argument");
328         return;
329     }
330     auto showCloseIcon = DEFAULT_SHOWCLOSEICON;
331     if (info[0]->IsBoolean()) {
332         showCloseIcon = info[0]->ToBoolean();
333     }
334     SlidingPanelModel::GetInstance()->SetShowCloseIcon(showCloseIcon);
335 }
336 
SetShow(const JSCallbackInfo & info)337 void JSSlidingPanel::SetShow(const JSCallbackInfo& info)
338 {
339     auto pipeline = PipelineBase::GetCurrentContext();
340     CHECK_NULL_VOID(pipeline);
341     if (pipeline->GetMinPlatformVersion() >= PLATFORM_VERSION_TEN && (info[0]->IsUndefined() || info[0]->IsNull())) {
342         SlidingPanelModel::GetInstance()->SetIsShow(true);
343     } else {
344         SlidingPanelModel::GetInstance()->SetIsShow(info[0]->ToBoolean());
345     }
346 }
347 
ParseModeObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal)348 void ParseModeObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
349 {
350     CHECK_NULL_VOID(changeEventVal->IsFunction());
351 
352     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
353     auto onMode = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const BaseEventInfo* baseEventInfo) {
354         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
355         ACE_SCORING_EVENT("SlidingPanel.ModeChangeEvent");
356         auto eventInfo = TypeInfoHelper::DynamicCast<SlidingPanelSizeChangeEvent>(baseEventInfo);
357         if (!eventInfo) {
358             return;
359         }
360         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(static_cast<int32_t>(eventInfo->GetMode())));
361         func->ExecuteJS(1, &newJSVal);
362     };
363     SlidingPanelModel::GetInstance()->SetModeChangeEvent(std::move(onMode));
364 }
365 
SetPanelMode(const JSCallbackInfo & info)366 void JSSlidingPanel::SetPanelMode(const JSCallbackInfo& info)
367 {
368     if (info.Length() < 1 || info.Length() > 2) {
369         LOGE("The arg is wrong, it is supposed to have 1 or 2 arguments");
370         return;
371     }
372 
373     int32_t mode = static_cast<int32_t>(DEFAULT_PANELMODE);
374     if (info.Length() > 0 && info[0]->IsNumber()) {
375         const auto modeNumber = info[0]->ToNumber<int32_t>();
376         if (modeNumber >= 0 && modeNumber < static_cast<int32_t>(PANEL_MODES.size())) {
377             mode = modeNumber;
378         }
379     }
380 
381     if (info.Length() > 1 && info[1]->IsFunction()) {
382         ParseModeObject(info, info[1]);
383     }
384 
385     SlidingPanelModel::GetInstance()->SetPanelMode(PANEL_MODES[mode]);
386 }
387 
SetPanelType(const JSCallbackInfo & info)388 void JSSlidingPanel::SetPanelType(const JSCallbackInfo& info)
389 {
390     if (info.Length() < 1) {
391         LOGE("The info is wrong, it is supposed to have at least 1 argument");
392         return;
393     }
394     auto type = static_cast<int32_t>(DEFAULT_PANELTYPE);
395     if (info[0]->IsNumber()) {
396         const auto typeNumber = info[0]->ToNumber<int32_t>();
397         if (typeNumber >= 0 && typeNumber < static_cast<int32_t>(PANEL_TYPES.size())) {
398             type = typeNumber;
399         }
400     }
401     SlidingPanelModel::GetInstance()->SetPanelType(PANEL_TYPES[type]);
402 }
403 
SetCustomHeight(const JSCallbackInfo & info)404 void JSSlidingPanel::SetCustomHeight(const JSCallbackInfo& info)
405 {
406     if (info.Length() < 1) {
407         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
408         return;
409     }
410     CalcDimension customHeight;
411     if (info[0]->IsString() && info[0]->ToString().find("wrapContent") != std::string::npos) {
412         customHeight = CalcDimension(info[0]->ToString());
413     } else if (!ParseJsDimensionVp(info[0], customHeight)) {
414         customHeight = Dimension(0.0);
415     }
416 
417     SlidingPanelModel::GetInstance()->SetCustomHeight(customHeight);
418 }
419 
SetMiniHeight(const JSCallbackInfo & info)420 void JSSlidingPanel::SetMiniHeight(const JSCallbackInfo& info)
421 {
422     if (info.Length() < 1) {
423         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
424         return;
425     }
426     CalcDimension miniHeight;
427     if (!ParseJsDimensionVp(info[0], miniHeight)) {
428         return;
429     }
430 
431     SlidingPanelModel::GetInstance()->SetMiniHeight(miniHeight);
432 }
433 
SetHalfHeight(const JSCallbackInfo & info)434 void JSSlidingPanel::SetHalfHeight(const JSCallbackInfo& info)
435 {
436     if (info.Length() < 1) {
437         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
438         return;
439     }
440     CalcDimension halfHeight;
441     if (!ParseJsDimensionVp(info[0], halfHeight)) {
442         return;
443     }
444     SlidingPanelModel::GetInstance()->SetHalfHeight(halfHeight);
445 }
446 
SetFullHeight(const JSCallbackInfo & info)447 void JSSlidingPanel::SetFullHeight(const JSCallbackInfo& info)
448 {
449     if (info.Length() < 1) {
450         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
451         return;
452     }
453     CalcDimension fullHeight;
454     if (!ParseJsDimensionVp(info[0], fullHeight)) {
455         return;
456     }
457     SlidingPanelModel::GetInstance()->SetFullHeight(fullHeight);
458 }
459 
Pop()460 void JSSlidingPanel::Pop()
461 {
462     SlidingPanelModel::GetInstance()->Pop();
463 }
464 
465 } // namespace OHOS::Ace::Framework
466