• 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 std::string DEFAULT_BACKGROUND_MASK = "#08182431";
69 } // namespace
70 
Create(const JSCallbackInfo & info)71 void JSSlidingPanel::Create(const JSCallbackInfo& info)
72 {
73     if (info.Length() > 0 && info[0]->IsBoolean()) {
74         bool isShow = true;
75         isShow = info[0]->ToBoolean();
76         SlidingPanelModel::GetInstance()->Create(isShow);
77         return;
78     }
79 }
80 
JSBind(BindingTarget globalObj)81 void JSSlidingPanel::JSBind(BindingTarget globalObj)
82 {
83     JSClass<JSSlidingPanel>::Declare("Panel");
84     MethodOptions opt = MethodOptions::NONE;
85     JSClass<JSSlidingPanel>::StaticMethod("create", &JSSlidingPanel::Create, opt);
86     JSClass<JSSlidingPanel>::StaticMethod("pop", &JSSlidingPanel::Pop, opt);
87     JSClass<JSSlidingPanel>::StaticMethod("dragBar", &JSSlidingPanel::SetHasDragBar, opt);
88     JSClass<JSSlidingPanel>::StaticMethod("show", &JSSlidingPanel::SetShow, opt);
89     JSClass<JSSlidingPanel>::StaticMethod("showCloseIcon", &JSSlidingPanel::SetShowCloseIcon, opt);
90     JSClass<JSSlidingPanel>::StaticMethod("mode", &JSSlidingPanel::SetPanelMode, opt);
91     JSClass<JSSlidingPanel>::StaticMethod("type", &JSSlidingPanel::SetPanelType, opt);
92     JSClass<JSSlidingPanel>::StaticMethod("customHeight", &JSSlidingPanel::SetCustomHeight, opt);
93     JSClass<JSSlidingPanel>::StaticMethod("backgroundMask", &JSSlidingPanel::SetBackgroundMask, opt);
94     JSClass<JSSlidingPanel>::StaticMethod("fullHeight", &JSSlidingPanel::SetFullHeight, opt);
95     JSClass<JSSlidingPanel>::StaticMethod("halfHeight", &JSSlidingPanel::SetHalfHeight, opt);
96     JSClass<JSSlidingPanel>::StaticMethod("miniHeight", &JSSlidingPanel::SetMiniHeight, opt);
97     JSClass<JSSlidingPanel>::StaticMethod("backgroundColor", JsBackgroundColor);
98     JSClass<JSSlidingPanel>::StaticMethod("border", JsPanelBorder);
99     JSClass<JSSlidingPanel>::StaticMethod("borderWidth", JsPanelBorderWidth);
100     JSClass<JSSlidingPanel>::StaticMethod("borderColor", JsPanelBorderColor);
101     JSClass<JSSlidingPanel>::StaticMethod("borderStyle", JsPanelBorderStyle);
102     JSClass<JSSlidingPanel>::StaticMethod("borderRadius", JsPanelBorderRadius);
103 
104     JSClass<JSSlidingPanel>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
105     JSClass<JSSlidingPanel>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
106     JSClass<JSSlidingPanel>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
107     JSClass<JSSlidingPanel>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
108     JSClass<JSSlidingPanel>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
109     JSClass<JSSlidingPanel>::StaticMethod("onChange", &JSSlidingPanel::SetOnSizeChange);
110     JSClass<JSSlidingPanel>::StaticMethod("onHeightChange", &JSSlidingPanel::SetOnHeightChange);
111     JSClass<JSSlidingPanel>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
112     JSClass<JSSlidingPanel>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
113 
114     JSClass<JSSlidingPanel>::InheritAndBind<JSContainerBase>(globalObj);
115 }
116 
SetBackgroundMask(const JSCallbackInfo & info)117 void JSSlidingPanel::SetBackgroundMask(const JSCallbackInfo& info)
118 {
119     Color color;
120     if (info.Length() < 1) {
121         color = Color::FromString(DEFAULT_BACKGROUND_MASK);
122     } else if (!ParseJsColor(info[0], color)) {
123         color = Color::FromString(DEFAULT_BACKGROUND_MASK);
124     }
125 
126     SlidingPanelModel::GetInstance()->SetBackgroundMask(color);
127 }
128 
ParsePanelRadius(const JSRef<JSVal> & args,BorderRadius & borderRadius)129 void JSSlidingPanel::ParsePanelRadius(const JSRef<JSVal>& args, BorderRadius& borderRadius)
130 {
131     if (!args->IsObject() && !args->IsNumber() && !args->IsString()) {
132         return;
133     }
134 
135     CalcDimension radius;
136     if (ParseJsDimensionVp(args, radius)) {
137         borderRadius.radiusTopLeft = radius;
138         borderRadius.radiusTopRight = radius;
139         borderRadius.radiusBottomLeft = radius;
140         borderRadius.radiusBottomRight = radius;
141         return;
142     }
143     if (args->IsObject()) {
144         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
145         auto valueTopLeft = object->GetProperty("topLeft");
146         if (!valueTopLeft->IsUndefined()) {
147             ParseJsDimensionVp(valueTopLeft, borderRadius.radiusTopLeft);
148         }
149         auto valueTopRight = object->GetProperty("topRight");
150         if (!valueTopRight->IsUndefined()) {
151             ParseJsDimensionVp(valueTopRight, borderRadius.radiusTopRight);
152         }
153         auto valueBottomLeft = object->GetProperty("bottomLeft");
154         if (!valueBottomLeft->IsUndefined()) {
155             ParseJsDimensionVp(valueBottomLeft, borderRadius.radiusBottomLeft);
156         }
157         auto valueBottomRight = object->GetProperty("bottomRight");
158         if (!valueBottomRight->IsUndefined()) {
159             ParseJsDimensionVp(valueBottomRight, borderRadius.radiusBottomRight);
160         }
161         return;
162     }
163 }
164 
JsPanelBorderRadius(const JSCallbackInfo & info)165 void JSSlidingPanel::JsPanelBorderRadius(const JSCallbackInfo& info)
166 {
167     BorderRadius borderRadius;
168     ParsePanelRadius(info[0], borderRadius);
169 
170     ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius.radiusTopLeft, borderRadius.radiusTopRight,
171         borderRadius.radiusBottomLeft, borderRadius.radiusBottomRight);
172 }
173 
JsBackgroundColor(const JSCallbackInfo & info)174 void JSSlidingPanel::JsBackgroundColor(const JSCallbackInfo& info)
175 {
176     if (info.Length() < 1) {
177         return;
178     }
179     Color backgroundColor;
180     if (!ParseJsColor(info[0], backgroundColor)) {
181         return;
182     }
183 
184     SlidingPanelModel::GetInstance()->SetBackgroundColor(backgroundColor);
185 }
186 
JsPanelBorderColor(const JSCallbackInfo & info)187 void JSSlidingPanel::JsPanelBorderColor(const JSCallbackInfo& info)
188 {
189     if (info.Length() < 1) {
190         return;
191     }
192     Color borderColor;
193     if (!ParseJsColor(info[0], borderColor)) {
194         return;
195     }
196 
197     SlidingPanelModel::GetInstance()->SetBorderColor(borderColor);
198 }
199 
JsPanelBorderWidth(const JSCallbackInfo & info)200 void JSSlidingPanel::JsPanelBorderWidth(const JSCallbackInfo& info)
201 {
202     if (info.Length() < 1) {
203         return;
204     }
205     CalcDimension borderWidth;
206     if (!ParseJsDimensionVp(info[0], borderWidth)) {
207         return;
208     }
209     SlidingPanelModel::GetInstance()->SetBorderWidth(borderWidth);
210 }
211 
JsPanelBorderStyle(int32_t style)212 void JSSlidingPanel::JsPanelBorderStyle(int32_t style)
213 {
214     BorderStyle borderStyle = BorderStyle::SOLID;
215     if (style > 0 && style < 4) {
216         borderStyle = static_cast<BorderStyle>(style);
217     }
218     SlidingPanelModel::GetInstance()->SetBorderStyle(borderStyle);
219 }
220 
JsPanelBorder(const JSCallbackInfo & info)221 void JSSlidingPanel::JsPanelBorder(const JSCallbackInfo& info)
222 {
223     if (info.Length() < 1) {
224         return;
225     }
226     if (!info[0]->IsObject()) {
227         return;
228     }
229 
230     auto argsPtrItem = JSRef<JSObject>::Cast(info[0]);
231     CalcDimension width = CalcDimension(0.0, DimensionUnit::VP);
232     ParseJsDimensionVp(argsPtrItem->GetProperty("width"), width);
233     SlidingPanelModel::GetInstance()->SetBorderWidth(width);
234 
235     BorderRadius borderRadius;
236     ParsePanelRadius(argsPtrItem->GetProperty("radius"), borderRadius);
237     ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius.radiusTopLeft, borderRadius.radiusTopRight,
238         borderRadius.radiusBottomLeft, borderRadius.radiusBottomRight);
239 
240     auto styleJsValue = argsPtrItem->GetProperty("style");
241     auto borderStyle = BorderStyle::SOLID;
242     if (!styleJsValue->IsUndefined() && styleJsValue->IsNumber()) {
243         auto styleValue = styleJsValue->ToNumber<uint32_t>();
244         if (styleValue > 0 && styleValue < 4) {
245             borderStyle = static_cast<BorderStyle>(styleValue);
246         }
247     }
248     SlidingPanelModel::GetInstance()->SetBorderStyle(borderStyle);
249 
250     Color borderColor;
251     ParseJsColor(argsPtrItem->GetProperty("color"), borderColor);
252     SlidingPanelModel::GetInstance()->SetBorderColor(borderColor);
253 }
254 
SetOnSizeChange(const JSCallbackInfo & args)255 void JSSlidingPanel::SetOnSizeChange(const JSCallbackInfo& args)
256 {
257     if (!args[0]->IsFunction()) {
258         return;
259     }
260 
261     auto onSizeChangeNG = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](
262                               const BaseEventInfo* info) {
263         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
264         auto eventInfo = TypeInfoHelper::DynamicCast<SlidingPanelSizeChangeEvent>(info);
265         if (!eventInfo) {
266             return;
267         }
268         auto params = ConvertToJSValues(eventInfo->GetWidth(), eventInfo->GetHeight(), eventInfo->GetMode());
269         ACE_SCORING_EVENT("SlidingPanel.OnSizeChange");
270         func->Call(JSRef<JSObject>(), params.size(), params.data());
271     };
272     SlidingPanelModel::GetInstance()->SetOnSizeChange(onSizeChangeNG);
273 
274     args.ReturnSelf();
275 }
276 
SetOnHeightChange(const JSCallbackInfo & args)277 void JSSlidingPanel::SetOnHeightChange(const JSCallbackInfo& args)
278 {
279     if (args.Length() < 1) {
280         return;
281     }
282     if (!args[0]->IsFunction()) {
283         return;
284     }
285 
286     auto onHeightChangeCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
287     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
288     auto onHeightChange = [execCtx = args.GetExecutionContext(), func = std::move(onHeightChangeCallback),
289                               node = targetNode](int32_t height) {
290         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
291         ACE_SCORING_EVENT("OnHeightChange");
292         PipelineContext::SetCallBackNode(node);
293         JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(height));
294         func->ExecuteJS(1, &param);
295     };
296 
297     SlidingPanelModel::GetInstance()->SetOnHeightChange(std::move(onHeightChange));
298 
299     args.ReturnSelf();
300 }
301 
SetHasDragBar(const JSCallbackInfo & info)302 void JSSlidingPanel::SetHasDragBar(const JSCallbackInfo& info)
303 {
304     if (info.Length() < 1) {
305         return;
306     }
307     auto hasDragBar = DEFAULT_HASDRAGBAR;
308     if (info[0]->IsBoolean()) {
309         hasDragBar = info[0]->ToBoolean();
310     }
311     SlidingPanelModel::GetInstance()->SetHasDragBar(hasDragBar);
312 }
313 
SetShowCloseIcon(const JSCallbackInfo & info)314 void JSSlidingPanel::SetShowCloseIcon(const JSCallbackInfo& info)
315 {
316     if (info.Length() < 1) {
317         return;
318     }
319     auto showCloseIcon = DEFAULT_SHOWCLOSEICON;
320     if (info[0]->IsBoolean()) {
321         showCloseIcon = info[0]->ToBoolean();
322     }
323     SlidingPanelModel::GetInstance()->SetShowCloseIcon(showCloseIcon);
324 }
325 
SetShow(const JSCallbackInfo & info)326 void JSSlidingPanel::SetShow(const JSCallbackInfo& info)
327 {
328     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN) &&
329         (info[0]->IsUndefined() || info[0]->IsNull())) {
330         SlidingPanelModel::GetInstance()->SetIsShow(true);
331     } else {
332         SlidingPanelModel::GetInstance()->SetIsShow(info[0]->ToBoolean());
333     }
334 }
335 
ParseModeObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal)336 void ParseModeObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
337 {
338     CHECK_NULL_VOID(changeEventVal->IsFunction());
339 
340     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
341     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
342     auto onMode = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
343                       const BaseEventInfo* baseEventInfo) {
344         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
345         ACE_SCORING_EVENT("SlidingPanel.ModeChangeEvent");
346         auto eventInfo = TypeInfoHelper::DynamicCast<SlidingPanelSizeChangeEvent>(baseEventInfo);
347         if (!eventInfo) {
348             return;
349         }
350         PipelineContext::SetCallBackNode(node);
351         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(static_cast<int32_t>(eventInfo->GetMode())));
352         func->ExecuteJS(1, &newJSVal);
353     };
354     SlidingPanelModel::GetInstance()->SetModeChangeEvent(std::move(onMode));
355 }
356 
SetPanelMode(const JSCallbackInfo & info)357 void JSSlidingPanel::SetPanelMode(const JSCallbackInfo& info)
358 {
359     if (info.Length() < 1 || info.Length() > 2) {
360         return;
361     }
362 
363     int32_t mode = static_cast<int32_t>(DEFAULT_PANELMODE);
364     if (info.Length() > 0 && info[0]->IsNumber()) {
365         const auto modeNumber = info[0]->ToNumber<int32_t>();
366         if (modeNumber >= 0 && modeNumber < static_cast<int32_t>(PANEL_MODES.size())) {
367             mode = modeNumber;
368         }
369     }
370 
371     if (info.Length() > 1 && info[1]->IsFunction()) {
372         ParseModeObject(info, info[1]);
373     }
374 
375     SlidingPanelModel::GetInstance()->SetPanelMode(PANEL_MODES[mode]);
376 }
377 
SetPanelType(const JSCallbackInfo & info)378 void JSSlidingPanel::SetPanelType(const JSCallbackInfo& info)
379 {
380     if (info.Length() < 1) {
381         return;
382     }
383     auto type = static_cast<int32_t>(DEFAULT_PANELTYPE);
384     if (info[0]->IsNumber()) {
385         const auto typeNumber = info[0]->ToNumber<int32_t>();
386         if (typeNumber >= 0 && typeNumber < static_cast<int32_t>(PANEL_TYPES.size())) {
387             type = typeNumber;
388         }
389     }
390     SlidingPanelModel::GetInstance()->SetPanelType(PANEL_TYPES[type]);
391 }
392 
SetCustomHeight(const JSCallbackInfo & info)393 void JSSlidingPanel::SetCustomHeight(const JSCallbackInfo& info)
394 {
395     if (info.Length() < 1) {
396         return;
397     }
398     CalcDimension customHeight;
399     if (info[0]->IsString() && info[0]->ToString().find("wrapContent") != std::string::npos) {
400         customHeight = CalcDimension(info[0]->ToString());
401     } else if (!ParseJsDimensionVp(info[0], customHeight)) {
402         customHeight = Dimension(0.0);
403     }
404 
405     SlidingPanelModel::GetInstance()->SetCustomHeight(customHeight);
406 }
407 
SetMiniHeight(const JSCallbackInfo & info)408 void JSSlidingPanel::SetMiniHeight(const JSCallbackInfo& info)
409 {
410     if (info.Length() < 1) {
411         return;
412     }
413     CalcDimension miniHeight;
414     if (!ParseJsDimensionVp(info[0], miniHeight)) {
415         return;
416     }
417 
418     SlidingPanelModel::GetInstance()->SetMiniHeight(miniHeight);
419 }
420 
SetHalfHeight(const JSCallbackInfo & info)421 void JSSlidingPanel::SetHalfHeight(const JSCallbackInfo& info)
422 {
423     if (info.Length() < 1) {
424         return;
425     }
426     CalcDimension halfHeight;
427     if (!ParseJsDimensionVp(info[0], halfHeight)) {
428         return;
429     }
430     SlidingPanelModel::GetInstance()->SetHalfHeight(halfHeight);
431 }
432 
SetFullHeight(const JSCallbackInfo & info)433 void JSSlidingPanel::SetFullHeight(const JSCallbackInfo& info)
434 {
435     if (info.Length() < 1) {
436         return;
437     }
438     CalcDimension fullHeight;
439     if (!ParseJsDimensionVp(info[0], fullHeight)) {
440         return;
441     }
442     SlidingPanelModel::GetInstance()->SetFullHeight(fullHeight);
443 }
444 
Pop()445 void JSSlidingPanel::Pop()
446 {
447     SlidingPanelModel::GetInstance()->Pop();
448 }
449 
450 } // namespace OHOS::Ace::Framework
451