1 /*
2 * Copyright (c) 2021-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 #include "frameworks/bridge/declarative_frontend/jsview/js_sliding_panel.h"
17
18 #include <algorithm>
19 #include <iterator>
20
21 #include "base/log/ace_scoring_log.h"
22 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
23 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
24 #include "bridge/declarative_frontend/jsview/models/sliding_panel_model_impl.h"
25 #include "core/components_ng/base/view_abstract_model_ng.h"
26 #include "core/components_ng/pattern/panel/sliding_panel_model.h"
27 #include "core/components_ng/pattern/panel/sliding_panel_model_ng.h"
28
29 namespace OHOS::Ace {
30
31 std::unique_ptr<SlidingPanelModel> SlidingPanelModel::instance_ = nullptr;
32
GetInstance()33 SlidingPanelModel* SlidingPanelModel::GetInstance()
34 {
35 if (!instance_) {
36 #ifdef NG_BUILD
37 instance_.reset(new NG::SlidingPanelModelNG());
38 #else
39 if (Container::IsCurrentUseNewPipeline()) {
40 instance_.reset(new NG::SlidingPanelModelNG());
41 } else {
42 instance_.reset(new Framework::SlidingPanelModelImpl());
43 }
44 #endif
45 }
46 return instance_.get();
47 }
48
49 } // namespace OHOS::Ace
50 namespace OHOS::Ace::Framework {
51 namespace {
52
53 const std::vector<PanelMode> PANEL_MODES = { PanelMode::MINI, PanelMode::HALF, PanelMode::FULL, PanelMode::AUTO };
54 const std::vector<PanelType> PANEL_TYPES = { PanelType::MINI_BAR, PanelType::FOLDABLE_BAR, PanelType::TEMP_DISPLAY };
55 const std::vector<VisibleType> PANEL_VISIBLE_TYPES = { VisibleType::GONE, VisibleType::VISIBLE,
56 VisibleType::INVISIBLE };
57
58 } // namespace
59
Create(const JSCallbackInfo & info)60 void JSSlidingPanel::Create(const JSCallbackInfo& info)
61 {
62 if (info.Length() > 0 && info[0]->IsBoolean()) {
63 bool isShow = true;
64 isShow = info[0]->ToBoolean();
65 SlidingPanelModel::GetInstance()->Create(isShow);
66 return;
67 }
68 }
69
JSBind(BindingTarget globalObj)70 void JSSlidingPanel::JSBind(BindingTarget globalObj)
71 {
72 JSClass<JSSlidingPanel>::Declare("Panel");
73 MethodOptions opt = MethodOptions::NONE;
74 JSClass<JSSlidingPanel>::StaticMethod("create", &JSSlidingPanel::Create, opt);
75 JSClass<JSSlidingPanel>::StaticMethod("pop", &JSSlidingPanel::Pop, opt);
76 JSClass<JSSlidingPanel>::StaticMethod("dragBar", &JSSlidingPanel::SetHasDragBar, opt);
77 JSClass<JSSlidingPanel>::StaticMethod("show", &JSSlidingPanel::SetShow, opt);
78 JSClass<JSSlidingPanel>::StaticMethod("mode", &JSSlidingPanel::SetPanelMode, opt);
79 JSClass<JSSlidingPanel>::StaticMethod("type", &JSSlidingPanel::SetPanelType, opt);
80 JSClass<JSSlidingPanel>::StaticMethod("backgroundMask", &JSSlidingPanel::SetBackgroundMask, opt);
81 JSClass<JSSlidingPanel>::StaticMethod("fullHeight", &JSSlidingPanel::SetFullHeight, opt);
82 JSClass<JSSlidingPanel>::StaticMethod("halfHeight", &JSSlidingPanel::SetHalfHeight, opt);
83 JSClass<JSSlidingPanel>::StaticMethod("miniHeight", &JSSlidingPanel::SetMiniHeight, opt);
84 JSClass<JSSlidingPanel>::StaticMethod("backgroundColor", JsBackgroundColor);
85 JSClass<JSSlidingPanel>::StaticMethod("border", JsPanelBorder);
86 JSClass<JSSlidingPanel>::StaticMethod("borderWidth", JsPanelBorderWidth);
87 JSClass<JSSlidingPanel>::StaticMethod("borderColor", JsPanelBorderColor);
88 JSClass<JSSlidingPanel>::StaticMethod("borderStyle", JsPanelBorderStyle);
89 JSClass<JSSlidingPanel>::StaticMethod("borderRadius", JsPanelBorderRadius);
90
91 JSClass<JSSlidingPanel>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
92 JSClass<JSSlidingPanel>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
93 JSClass<JSSlidingPanel>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
94 JSClass<JSSlidingPanel>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
95 JSClass<JSSlidingPanel>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
96 JSClass<JSSlidingPanel>::StaticMethod("onChange", &JSSlidingPanel::SetOnSizeChange);
97 JSClass<JSSlidingPanel>::StaticMethod("onHeightChange", &JSSlidingPanel::SetOnHeightChange);
98
99 JSClass<JSSlidingPanel>::Inherit<JSContainerBase>();
100 JSClass<JSSlidingPanel>::Inherit<JSViewAbstract>();
101 JSClass<JSSlidingPanel>::Bind<>(globalObj);
102 }
103
SetBackgroundMask(const JSCallbackInfo & info)104 void JSSlidingPanel::SetBackgroundMask(const JSCallbackInfo& info)
105 {
106 if (info.Length() < 1) {
107 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
108 return;
109 }
110 Color color;
111 if (!ParseJsColor(info[0], color)) {
112 return;
113 }
114
115 SlidingPanelModel::GetInstance()->SetBackgroundMask(color);
116 }
117
ParsePanelRadius(const JSRef<JSVal> & args,BorderRadius & borderRadius)118 void JSSlidingPanel::ParsePanelRadius(const JSRef<JSVal>& args, BorderRadius& borderRadius)
119 {
120 if (!args->IsObject() && !args->IsNumber() && !args->IsString()) {
121 LOGE("args need a object or number or string. %{public}s", args->ToString().c_str());
122 return;
123 }
124
125 Dimension radius;
126 if (ParseJsDimensionVp(args, radius)) {
127 borderRadius.radiusTopLeft = radius;
128 borderRadius.radiusTopRight = radius;
129 borderRadius.radiusBottomLeft = radius;
130 borderRadius.radiusBottomRight = radius;
131 return;
132 }
133 if (args->IsObject()) {
134 JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
135 auto valueTopLeft = object->GetProperty("topLeft");
136 if (!valueTopLeft->IsUndefined()) {
137 ParseJsDimensionVp(valueTopLeft, borderRadius.radiusTopLeft);
138 }
139 auto valueTopRight = object->GetProperty("topRight");
140 if (!valueTopRight->IsUndefined()) {
141 ParseJsDimensionVp(valueTopRight, borderRadius.radiusTopRight);
142 }
143 auto valueBottomLeft = object->GetProperty("bottomLeft");
144 if (!valueBottomLeft->IsUndefined()) {
145 ParseJsDimensionVp(valueBottomLeft, borderRadius.radiusBottomLeft);
146 }
147 auto valueBottomRight = object->GetProperty("bottomRight");
148 if (!valueBottomRight->IsUndefined()) {
149 ParseJsDimensionVp(valueBottomRight, borderRadius.radiusBottomRight);
150 }
151 return;
152 }
153 LOGE("args format error. %{public}s", args->ToString().c_str());
154 }
155
JsPanelBorderRadius(const JSCallbackInfo & info)156 void JSSlidingPanel::JsPanelBorderRadius(const JSCallbackInfo& info)
157 {
158 BorderRadius borderRadius;
159 ParsePanelRadius(info[0], borderRadius);
160
161 ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius.radiusTopLeft, borderRadius.radiusTopRight,
162 borderRadius.radiusBottomLeft, borderRadius.radiusBottomRight);
163 }
164
JsBackgroundColor(const JSCallbackInfo & info)165 void JSSlidingPanel::JsBackgroundColor(const JSCallbackInfo& info)
166 {
167 if (info.Length() < 1) {
168 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
169 return;
170 }
171 Color backgroundColor;
172 if (!ParseJsColor(info[0], backgroundColor)) {
173 return;
174 }
175
176 SlidingPanelModel::GetInstance()->SetBackgroundColor(backgroundColor);
177 }
178
JsPanelBorderColor(const JSCallbackInfo & info)179 void JSSlidingPanel::JsPanelBorderColor(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 borderColor;
186 if (!ParseJsColor(info[0], borderColor)) {
187 return;
188 }
189
190 SlidingPanelModel::GetInstance()->SetBorderColor(borderColor);
191 }
192
JsPanelBorderWidth(const JSCallbackInfo & info)193 void JSSlidingPanel::JsPanelBorderWidth(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 Dimension borderWidth;
200 if (!ParseJsDimensionVp(info[0], borderWidth)) {
201 return;
202 }
203 SlidingPanelModel::GetInstance()->SetBorderWidth(borderWidth);
204 }
205
JsPanelBorderStyle(int32_t style)206 void JSSlidingPanel::JsPanelBorderStyle(int32_t style)
207 {
208 BorderStyle borderStyle = BorderStyle::SOLID;
209 if (style > 0 && style < 4) {
210 borderStyle = static_cast<BorderStyle>(style);
211 }
212 SlidingPanelModel::GetInstance()->SetBorderStyle(borderStyle);
213 }
214
JsPanelBorder(const JSCallbackInfo & info)215 void JSSlidingPanel::JsPanelBorder(const JSCallbackInfo& info)
216 {
217 if (info.Length() < 1) {
218 LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
219 return;
220 }
221 if (!info[0]->IsObject()) {
222 LOGE("arg is not a object.");
223 return;
224 }
225
226 auto argsPtrItem = JSRef<JSObject>::Cast(info[0]);
227 Dimension width = Dimension(0.0, DimensionUnit::VP);
228 ParseJsDimensionVp(argsPtrItem->GetProperty("width"), width);
229 SlidingPanelModel::GetInstance()->SetBorderWidth(width);
230
231 BorderRadius borderRadius;
232 ParsePanelRadius(argsPtrItem->GetProperty("radius"), borderRadius);
233 ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius.radiusTopLeft, borderRadius.radiusTopRight,
234 borderRadius.radiusBottomLeft, borderRadius.radiusBottomRight);
235
236 auto styleJsValue = argsPtrItem->GetProperty("style");
237 auto borderStyle = BorderStyle::SOLID;
238 if (!styleJsValue->IsUndefined() && styleJsValue->IsNumber()) {
239 auto styleValue = styleJsValue->ToNumber<uint32_t>();
240 if (styleValue > 0 && styleValue < 4) {
241 borderStyle = static_cast<BorderStyle>(styleValue);
242 }
243 }
244 SlidingPanelModel::GetInstance()->SetBorderStyle(borderStyle);
245
246 Color borderColor;
247 ParseJsColor(argsPtrItem->GetProperty("color"), borderColor);
248 SlidingPanelModel::GetInstance()->SetBorderColor(borderColor);
249 }
250
SetOnSizeChange(const JSCallbackInfo & args)251 void JSSlidingPanel::SetOnSizeChange(const JSCallbackInfo& args)
252 {
253 if (!args[0]->IsFunction()) {
254 return;
255 }
256
257 auto onSizeChangeNG = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](
258 const BaseEventInfo* info) {
259 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
260 auto eventInfo = TypeInfoHelper::DynamicCast<SlidingPanelSizeChangeEvent>(info);
261 if (!eventInfo) {
262 return;
263 }
264 auto params = ConvertToJSValues(eventInfo->GetWidth(), eventInfo->GetHeight(), eventInfo->GetMode());
265 ACE_SCORING_EVENT("SlidingPanel.OnSizeChange");
266 func->Call(JSRef<JSObject>(), params.size(), params.data());
267 };
268 SlidingPanelModel::GetInstance()->SetOnSizeChange(onSizeChangeNG);
269
270 args.ReturnSelf();
271 }
272
SetOnHeightChange(const JSCallbackInfo & args)273 void JSSlidingPanel::SetOnHeightChange(const JSCallbackInfo& args)
274 {
275 if (args.Length() < 1) {
276 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
277 return;
278 }
279 if (!args[0]->IsFunction()) {
280 return;
281 }
282
283 auto onHeightChangeCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
284 auto onHeightChange = [execCtx = args.GetExecutionContext(), func = std::move(onHeightChangeCallback)](
285 int32_t height) {
286 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
287 ACE_SCORING_EVENT("OnHeightChange");
288 JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(height));
289 func->ExecuteJS(1, ¶m);
290 };
291
292 SlidingPanelModel::GetInstance()->SetOnHeightChange(std::move(onHeightChange));
293
294 args.ReturnSelf();
295 }
296
SetHasDragBar(bool hasDragBar)297 void JSSlidingPanel::SetHasDragBar(bool hasDragBar)
298 {
299 SlidingPanelModel::GetInstance()->SetHasDragBar(hasDragBar);
300 }
301
SetShow(bool isShow)302 void JSSlidingPanel::SetShow(bool isShow)
303 {
304 SlidingPanelModel::GetInstance()->SetIsShow(isShow);
305 }
306
SetPanelMode(int32_t mode)307 void JSSlidingPanel::SetPanelMode(int32_t mode)
308 {
309 if (mode < 0 || mode >= static_cast<int32_t>(PANEL_MODES.size())) {
310 return;
311 }
312
313 SlidingPanelModel::GetInstance()->SetPanelMode(PANEL_MODES[mode]);
314 }
315
SetPanelType(int32_t type)316 void JSSlidingPanel::SetPanelType(int32_t type)
317 {
318 if (type < 0 || type >= static_cast<int32_t>(PANEL_TYPES.size())) {
319 return;
320 }
321
322 SlidingPanelModel::GetInstance()->SetPanelType(PANEL_TYPES[type]);
323 }
324
SetMiniHeight(const JSCallbackInfo & info)325 void JSSlidingPanel::SetMiniHeight(const JSCallbackInfo& info)
326 {
327 if (info.Length() < 1) {
328 LOGE("The arg is wrong, it is supposed to have at least 1 argument");
329 return;
330 }
331 Dimension miniHeight;
332 if (!ParseJsDimensionVp(info[0], miniHeight)) {
333 return;
334 }
335
336 SlidingPanelModel::GetInstance()->SetMiniHeight(miniHeight);
337 }
338
SetHalfHeight(const JSCallbackInfo & info)339 void JSSlidingPanel::SetHalfHeight(const JSCallbackInfo& info)
340 {
341 if (info.Length() < 1) {
342 LOGE("The arg is wrong, it is supposed to have at least 1 argument");
343 return;
344 }
345 Dimension halfHeight;
346 if (!ParseJsDimensionVp(info[0], halfHeight)) {
347 return;
348 }
349 SlidingPanelModel::GetInstance()->SetHalfHeight(halfHeight);
350 }
351
SetFullHeight(const JSCallbackInfo & info)352 void JSSlidingPanel::SetFullHeight(const JSCallbackInfo& info)
353 {
354 if (info.Length() < 1) {
355 LOGE("The arg is wrong, it is supposed to have at least 1 argument");
356 return;
357 }
358 Dimension fullHeight;
359 if (!ParseJsDimensionVp(info[0], fullHeight)) {
360 return;
361 }
362 SlidingPanelModel::GetInstance()->SetFullHeight(fullHeight);
363 }
364
Pop()365 void JSSlidingPanel::Pop()
366 {
367 SlidingPanelModel::GetInstance()->Pop();
368 }
369
370 } // namespace OHOS::Ace::Framework
371