• 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/base/view_stack_model.h"
28 #include "core/components_ng/pattern/panel/sliding_panel_model.h"
29 #include "core/components_ng/pattern/panel/sliding_panel_model_ng.h"
30 
31 namespace OHOS::Ace {
32 
33 std::unique_ptr<SlidingPanelModel> SlidingPanelModel::instance_ = nullptr;
34 std::mutex SlidingPanelModel::mutex_;
35 
GetInstance()36 SlidingPanelModel* SlidingPanelModel::GetInstance()
37 {
38     if (!instance_) {
39         std::lock_guard<std::mutex> lock(mutex_);
40         if (!instance_) {
41 #ifdef NG_BUILD
42             instance_.reset(new NG::SlidingPanelModelNG());
43 #else
44             if (Container::IsCurrentUseNewPipeline()) {
45                 instance_.reset(new NG::SlidingPanelModelNG());
46             } else {
47                 instance_.reset(new Framework::SlidingPanelModelImpl());
48             }
49 #endif
50         }
51     }
52     return instance_.get();
53 }
54 
55 } // namespace OHOS::Ace
56 namespace OHOS::Ace::Framework {
57 namespace {
58 
59 const std::vector<PanelMode> PANEL_MODES = { PanelMode::MINI, PanelMode::HALF, PanelMode::FULL, PanelMode::AUTO };
60 const std::vector<PanelType> PANEL_TYPES = { PanelType::MINI_BAR, PanelType::FOLDABLE_BAR, PanelType::TEMP_DISPLAY,
61     PanelType::CUSTOM };
62 const std::vector<VisibleType> PANEL_VISIBLE_TYPES = { VisibleType::GONE, VisibleType::VISIBLE,
63     VisibleType::INVISIBLE };
64 
65 const static bool DEFAULT_HASDRAGBAR = true;
66 const static bool DEFAULT_SHOWCLOSEICON = false;
67 const static PanelMode DEFAULT_PANELMODE = PanelMode::HALF;
68 const static PanelType DEFAULT_PANELTYPE = PanelType::FOLDABLE_BAR;
69 const std::string DEFAULT_BACKGROUND_MASK = "#08182431";
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("onAttach", &JSInteractableView::JsOnAttach);
113     JSClass<JSSlidingPanel>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
114     JSClass<JSSlidingPanel>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
115     JSClass<JSSlidingPanel>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
116 
117     JSClass<JSSlidingPanel>::InheritAndBind<JSContainerBase>(globalObj);
118 }
119 
SetBackgroundMask(const JSCallbackInfo & info)120 void JSSlidingPanel::SetBackgroundMask(const JSCallbackInfo& info)
121 {
122     Color color;
123     if (info.Length() < 1) {
124         color = Color::FromString(DEFAULT_BACKGROUND_MASK);
125     } else if (!ParseJsColor(info[0], color)) {
126         color = Color::FromString(DEFAULT_BACKGROUND_MASK);
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         return;
136     }
137 
138     CalcDimension radius;
139     if (ParseJsDimensionVp(args, radius)) {
140         borderRadius.radiusTopLeft = radius;
141         borderRadius.radiusTopRight = radius;
142         borderRadius.radiusBottomLeft = radius;
143         borderRadius.radiusBottomRight = radius;
144         return;
145     }
146     if (args->IsObject()) {
147         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
148         auto valueTopLeft = object->GetProperty("topLeft");
149         if (!valueTopLeft->IsUndefined()) {
150             ParseJsDimensionVp(valueTopLeft, borderRadius.radiusTopLeft);
151         }
152         auto valueTopRight = object->GetProperty("topRight");
153         if (!valueTopRight->IsUndefined()) {
154             ParseJsDimensionVp(valueTopRight, borderRadius.radiusTopRight);
155         }
156         auto valueBottomLeft = object->GetProperty("bottomLeft");
157         if (!valueBottomLeft->IsUndefined()) {
158             ParseJsDimensionVp(valueBottomLeft, borderRadius.radiusBottomLeft);
159         }
160         auto valueBottomRight = object->GetProperty("bottomRight");
161         if (!valueBottomRight->IsUndefined()) {
162             ParseJsDimensionVp(valueBottomRight, borderRadius.radiusBottomRight);
163         }
164         return;
165     }
166 }
167 
JsPanelBorderRadius(const JSCallbackInfo & info)168 void JSSlidingPanel::JsPanelBorderRadius(const JSCallbackInfo& info)
169 {
170     BorderRadius borderRadius;
171     ParsePanelRadius(info[0], borderRadius);
172 
173     ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius.radiusTopLeft, borderRadius.radiusTopRight,
174         borderRadius.radiusBottomLeft, borderRadius.radiusBottomRight);
175 }
176 
JsBackgroundColor(const JSCallbackInfo & info)177 void JSSlidingPanel::JsBackgroundColor(const JSCallbackInfo& info)
178 {
179     if (info.Length() < 1) {
180         return;
181     }
182     Color backgroundColor;
183     if (!ParseJsColor(info[0], backgroundColor)) {
184         return;
185     }
186 
187     SlidingPanelModel::GetInstance()->SetBackgroundColor(backgroundColor);
188 }
189 
JsPanelBorderColor(const JSCallbackInfo & info)190 void JSSlidingPanel::JsPanelBorderColor(const JSCallbackInfo& info)
191 {
192     if (info.Length() < 1) {
193         return;
194     }
195     Color borderColor;
196     if (!ParseJsColor(info[0], borderColor)) {
197         return;
198     }
199 
200     SlidingPanelModel::GetInstance()->SetBorderColor(borderColor);
201 }
202 
JsPanelBorderWidth(const JSCallbackInfo & info)203 void JSSlidingPanel::JsPanelBorderWidth(const JSCallbackInfo& info)
204 {
205     if (info.Length() < 1) {
206         return;
207     }
208     CalcDimension borderWidth;
209     if (!ParseJsDimensionVp(info[0], borderWidth)) {
210         return;
211     }
212     SlidingPanelModel::GetInstance()->SetBorderWidth(borderWidth);
213 }
214 
JsPanelBorderStyle(int32_t style)215 void JSSlidingPanel::JsPanelBorderStyle(int32_t style)
216 {
217     BorderStyle borderStyle = BorderStyle::SOLID;
218     if (style > 0 && style < 4) {
219         borderStyle = static_cast<BorderStyle>(style);
220     }
221     SlidingPanelModel::GetInstance()->SetBorderStyle(borderStyle);
222 }
223 
JsPanelBorder(const JSCallbackInfo & info)224 void JSSlidingPanel::JsPanelBorder(const JSCallbackInfo& info)
225 {
226     if (info.Length() < 1) {
227         return;
228     }
229     if (!info[0]->IsObject()) {
230         return;
231     }
232 
233     auto argsPtrItem = JSRef<JSObject>::Cast(info[0]);
234     CalcDimension width = CalcDimension(0.0, DimensionUnit::VP);
235     ParseJsDimensionVp(argsPtrItem->GetProperty("width"), width);
236     SlidingPanelModel::GetInstance()->SetBorderWidth(width);
237 
238     BorderRadius borderRadius;
239     ParsePanelRadius(argsPtrItem->GetProperty("radius"), borderRadius);
240     ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius.radiusTopLeft, borderRadius.radiusTopRight,
241         borderRadius.radiusBottomLeft, borderRadius.radiusBottomRight);
242 
243     auto styleJsValue = argsPtrItem->GetProperty("style");
244     auto borderStyle = BorderStyle::SOLID;
245     if (!styleJsValue->IsUndefined() && styleJsValue->IsNumber()) {
246         auto styleValue = styleJsValue->ToNumber<uint32_t>();
247         if (styleValue > 0 && styleValue < 4) {
248             borderStyle = static_cast<BorderStyle>(styleValue);
249         }
250     }
251     SlidingPanelModel::GetInstance()->SetBorderStyle(borderStyle);
252 
253     Color borderColor;
254     ParseJsColor(argsPtrItem->GetProperty("color"), borderColor);
255     SlidingPanelModel::GetInstance()->SetBorderColor(borderColor);
256 }
257 
SetOnSizeChange(const JSCallbackInfo & args)258 void JSSlidingPanel::SetOnSizeChange(const JSCallbackInfo& args)
259 {
260     if (!args[0]->IsFunction()) {
261         return;
262     }
263 
264     auto onSizeChangeNG = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](
265                               const BaseEventInfo* info) {
266         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
267         auto eventInfo = TypeInfoHelper::DynamicCast<SlidingPanelSizeChangeEvent>(info);
268         if (!eventInfo) {
269             return;
270         }
271         auto params = ConvertToJSValues(eventInfo->GetWidth(), eventInfo->GetHeight(), eventInfo->GetMode());
272         ACE_SCORING_EVENT("SlidingPanel.OnSizeChange");
273         func->Call(JSRef<JSObject>(), params.size(), params.data());
274     };
275     SlidingPanelModel::GetInstance()->SetOnSizeChange(onSizeChangeNG);
276 
277     args.ReturnSelf();
278 }
279 
SetOnHeightChange(const JSCallbackInfo & args)280 void JSSlidingPanel::SetOnHeightChange(const JSCallbackInfo& args)
281 {
282     if (args.Length() < 1) {
283         return;
284     }
285     if (!args[0]->IsFunction()) {
286         return;
287     }
288 
289     auto onHeightChangeCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
290     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
291     auto onHeightChange = [execCtx = args.GetExecutionContext(), func = std::move(onHeightChangeCallback),
292                               node = targetNode](int32_t height) {
293         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
294         ACE_SCORING_EVENT("OnHeightChange");
295         PipelineContext::SetCallBackNode(node);
296         JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(height));
297         func->ExecuteJS(1, &param);
298     };
299 
300     SlidingPanelModel::GetInstance()->SetOnHeightChange(std::move(onHeightChange));
301 
302     args.ReturnSelf();
303 }
304 
SetHasDragBar(const JSCallbackInfo & info)305 void JSSlidingPanel::SetHasDragBar(const JSCallbackInfo& info)
306 {
307     if (info.Length() < 1) {
308         return;
309     }
310     auto hasDragBar = DEFAULT_HASDRAGBAR;
311     if (info[0]->IsBoolean()) {
312         hasDragBar = info[0]->ToBoolean();
313     }
314     SlidingPanelModel::GetInstance()->SetHasDragBar(hasDragBar);
315 }
316 
SetShowCloseIcon(const JSCallbackInfo & info)317 void JSSlidingPanel::SetShowCloseIcon(const JSCallbackInfo& info)
318 {
319     if (info.Length() < 1) {
320         return;
321     }
322     auto showCloseIcon = DEFAULT_SHOWCLOSEICON;
323     if (info[0]->IsBoolean()) {
324         showCloseIcon = info[0]->ToBoolean();
325     }
326     SlidingPanelModel::GetInstance()->SetShowCloseIcon(showCloseIcon);
327 }
328 
SetShow(const JSCallbackInfo & info)329 void JSSlidingPanel::SetShow(const JSCallbackInfo& info)
330 {
331     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN) &&
332         (info[0]->IsUndefined() || info[0]->IsNull())) {
333         SlidingPanelModel::GetInstance()->SetIsShow(true);
334     } else {
335         SlidingPanelModel::GetInstance()->SetIsShow(info[0]->ToBoolean());
336     }
337 }
338 
ParseModeObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal)339 void ParseModeObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
340 {
341     CHECK_NULL_VOID(changeEventVal->IsFunction());
342 
343     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
344     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
345     auto onMode = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
346                       const BaseEventInfo* baseEventInfo) {
347         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
348         ACE_SCORING_EVENT("SlidingPanel.ModeChangeEvent");
349         auto eventInfo = TypeInfoHelper::DynamicCast<SlidingPanelSizeChangeEvent>(baseEventInfo);
350         if (!eventInfo) {
351             return;
352         }
353         PipelineContext::SetCallBackNode(node);
354         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(static_cast<int32_t>(eventInfo->GetMode())));
355         func->ExecuteJS(1, &newJSVal);
356     };
357     SlidingPanelModel::GetInstance()->SetModeChangeEvent(std::move(onMode));
358 }
359 
SetPanelMode(const JSCallbackInfo & info)360 void JSSlidingPanel::SetPanelMode(const JSCallbackInfo& info)
361 {
362     if (info.Length() < 1 || info.Length() > 2) {
363         return;
364     }
365 
366     int32_t mode = static_cast<int32_t>(DEFAULT_PANELMODE);
367     if (info.Length() > 0 && info[0]->IsNumber()) {
368         const auto modeNumber = info[0]->ToNumber<int32_t>();
369         if (modeNumber >= 0 && modeNumber < static_cast<int32_t>(PANEL_MODES.size())) {
370             mode = modeNumber;
371         }
372     }
373 
374     if (info.Length() > 1 && info[1]->IsFunction()) {
375         ParseModeObject(info, info[1]);
376     }
377 
378     SlidingPanelModel::GetInstance()->SetPanelMode(PANEL_MODES[mode]);
379 }
380 
SetPanelType(const JSCallbackInfo & info)381 void JSSlidingPanel::SetPanelType(const JSCallbackInfo& info)
382 {
383     if (info.Length() < 1) {
384         return;
385     }
386     auto type = static_cast<int32_t>(DEFAULT_PANELTYPE);
387     if (info[0]->IsNumber()) {
388         const auto typeNumber = info[0]->ToNumber<int32_t>();
389         if (typeNumber >= 0 && typeNumber < static_cast<int32_t>(PANEL_TYPES.size())) {
390             type = typeNumber;
391         }
392     }
393     SlidingPanelModel::GetInstance()->SetPanelType(PANEL_TYPES[type]);
394 }
395 
SetCustomHeight(const JSCallbackInfo & info)396 void JSSlidingPanel::SetCustomHeight(const JSCallbackInfo& info)
397 {
398     if (info.Length() < 1) {
399         return;
400     }
401     CalcDimension customHeight;
402     if (info[0]->IsString() && info[0]->ToString().find("wrapContent") != std::string::npos) {
403         customHeight = CalcDimension(info[0]->ToString());
404     } else if (!ParseJsDimensionVp(info[0], customHeight)) {
405         customHeight = Dimension(0.0);
406     }
407 
408     SlidingPanelModel::GetInstance()->SetCustomHeight(customHeight);
409 }
410 
SetMiniHeight(const JSCallbackInfo & info)411 void JSSlidingPanel::SetMiniHeight(const JSCallbackInfo& info)
412 {
413     if (info.Length() < 1) {
414         return;
415     }
416     CalcDimension miniHeight;
417     if (!ParseJsDimensionVp(info[0], miniHeight)) {
418         return;
419     }
420 
421     SlidingPanelModel::GetInstance()->SetMiniHeight(miniHeight);
422 }
423 
SetHalfHeight(const JSCallbackInfo & info)424 void JSSlidingPanel::SetHalfHeight(const JSCallbackInfo& info)
425 {
426     if (info.Length() < 1) {
427         return;
428     }
429     CalcDimension halfHeight;
430     if (!ParseJsDimensionVp(info[0], halfHeight)) {
431         return;
432     }
433     SlidingPanelModel::GetInstance()->SetHalfHeight(halfHeight);
434 }
435 
SetFullHeight(const JSCallbackInfo & info)436 void JSSlidingPanel::SetFullHeight(const JSCallbackInfo& info)
437 {
438     if (info.Length() < 1) {
439         return;
440     }
441     CalcDimension fullHeight;
442     if (!ParseJsDimensionVp(info[0], fullHeight)) {
443         return;
444     }
445     SlidingPanelModel::GetInstance()->SetFullHeight(fullHeight);
446 }
447 
Pop()448 void JSSlidingPanel::Pop()
449 {
450     if (ViewStackModel::GetInstance()->IsPrebuilding()) {
451         return ViewStackModel::GetInstance()->PushPrebuildCompCmd("[JSSlidingPanel][pop]", &JSSlidingPanel::Pop);
452     }
453     SlidingPanelModel::GetInstance()->Pop();
454 }
455 
456 } // namespace OHOS::Ace::Framework
457