• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_side_bar.h"
17 
18 #include "base/geometry/dimension.h"
19 #include "base/log/ace_scoring_log.h"
20 #include "base/log/log.h"
21 #include "core/components/button/button_component.h"
22 #include "core/components/side_bar/render_side_bar_container.h"
23 #include "core/components_ng/base/view_stack_processor.h"
24 #include "core/components_ng/pattern/side_bar/side_bar_container_view.h"
25 #include "frameworks/bridge/declarative_frontend/jsview/js_view_common_def.h"
26 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
27 
28 namespace OHOS::Ace::Framework {
29 namespace {
30 constexpr Dimension DEFAULT_CONTROL_BUTTON_WIDTH = 32.0_vp;
31 constexpr Dimension DEFAULT_CONTROL_BUTTON_HEIGHT = 32.0_vp;
32 constexpr Dimension DEFAULT_SIDE_BAR_WIDTH = 200.0_vp;
33 constexpr Dimension DEFAULT_MIN_SIDE_BAR_WIDTH = 200.0_vp;
34 constexpr Dimension DEFAULT_MAX_SIDE_BAR_WIDTH = 280.0_vp;
35 
36 enum class WidthType : uint32_t {
37     SIDEBAR_WIDTH = 0,
38     MIN_SIDEBAR_WIDTH,
39     MAX_SIDEBAR_WIDTH,
40 };
41 
ParseAndSetWidth(const JSCallbackInfo & info,WidthType widthType)42 void ParseAndSetWidth(const JSCallbackInfo& info, WidthType widthType)
43 {
44     if (info.Length() < 1) {
45         LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
46         return;
47     }
48 
49     Dimension value;
50     if (!JSViewAbstract::ParseJsDimensionVp(info[0], value)) {
51         return;
52     }
53 
54     if (Container::IsCurrentUseNewPipeline()) {
55         switch (widthType) {
56             case WidthType::SIDEBAR_WIDTH:
57                 NG::SideBarContainerView::SetSideBarWidth(value.IsNonNegative() ? value : DEFAULT_SIDE_BAR_WIDTH);
58                 break;
59             case WidthType::MIN_SIDEBAR_WIDTH:
60                 NG::SideBarContainerView::SetMinSideBarWidth(
61                     value.IsNonNegative() ? value : DEFAULT_MIN_SIDE_BAR_WIDTH);
62                 break;
63             case WidthType::MAX_SIDEBAR_WIDTH:
64                 NG::SideBarContainerView::SetMaxSideBarWidth(
65                     value.IsNonNegative() ? value : DEFAULT_MAX_SIDE_BAR_WIDTH);
66                 break;
67             default:
68                 break;
69         }
70         return;
71     }
72 
73     if (LessNotEqual(value.Value(), 0.0)) {
74         LOGW("JSSideBar::ParseAndSetWidth info[0] value is less than 0, the default is set to 0.");
75         value.SetValue(0.0);
76     }
77 
78     auto stack = ViewStackProcessor::GetInstance();
79     auto component = AceType::DynamicCast<OHOS::Ace::SideBarContainerComponent>(stack->GetMainComponent());
80     if (!component) {
81         LOGE("side bar is null");
82         return;
83     }
84 
85     if (value.Unit() == DimensionUnit::PERCENT) {
86         component->SetIsPercentSize(value.Unit() == DimensionUnit::PERCENT);
87     }
88 
89     switch (widthType) {
90         case WidthType::SIDEBAR_WIDTH:
91             component->SetSideBarWidth(value);
92             break;
93         case WidthType::MIN_SIDEBAR_WIDTH:
94             component->SetSideBarMinWidth(value);
95             break;
96         case WidthType::MAX_SIDEBAR_WIDTH:
97             component->SetSideBarMaxWidth(value);
98             break;
99         default:
100             break;
101     }
102 }
103 
104 } // namespace
105 
Create(const JSCallbackInfo & info)106 void JSSideBar::Create(const JSCallbackInfo& info)
107 {
108     if (Container::IsCurrentUseNewPipeline()) {
109         CreateForNG(info);
110         return;
111     }
112 
113     SideBarContainerType style = SideBarContainerType::EMBED;
114     if (!info[0]->IsNull()) {
115         if (info[0]->IsBoolean()) {
116             style = static_cast<SideBarContainerType>(info[0]->ToBoolean());
117         } else if (info[0]->IsNumber()) {
118             style = static_cast<SideBarContainerType>(info[0]->ToNumber<int>());
119         } else {
120             LOGE("The arg is wrong");
121             return;
122         }
123     }
124 
125     std::list<RefPtr<Component>> children;
126     auto sideBarContainer = AceType::MakeRefPtr<OHOS::Ace::SideBarContainerComponent>(children);
127     ViewStackProcessor::GetInstance()->ClaimElementId(sideBarContainer);
128     sideBarContainer->SetMainStackSize(MainStackSize::MAX);
129     sideBarContainer->SetSideBarContainerType(style);
130 
131     auto stack = ViewStackProcessor::GetInstance();
132     stack->Push(sideBarContainer);
133     JSInteractableView::SetFocusable(false);
134     JSInteractableView::SetFocusNode(true);
135 }
136 
CreateForNG(const JSCallbackInfo & info)137 void JSSideBar::CreateForNG(const JSCallbackInfo& info)
138 {
139     NG::SideBarContainerView::Create();
140 
141     SideBarContainerType style = SideBarContainerType::EMBED;
142     if (!info[0]->IsNull()) {
143         if (info[0]->IsBoolean()) {
144             style = static_cast<SideBarContainerType>(info[0]->ToBoolean());
145         } else if (info[0]->IsNumber()) {
146             style = static_cast<SideBarContainerType>(info[0]->ToNumber<int>());
147         } else {
148             LOGE("JSSideBar::CreateForNG The SideBarContainerType arg is wrong");
149             return;
150         }
151     }
152 
153     NG::SideBarContainerView::SetSideBarContainerType(style);
154 }
155 
SetShowControlButton(bool isShow)156 void JSSideBar::SetShowControlButton(bool isShow)
157 {
158     if (Container::IsCurrentUseNewPipeline()) {
159         NG::SideBarContainerView::SetShowControlButton(isShow);
160         return;
161     }
162 
163     auto stack = ViewStackProcessor::GetInstance();
164     auto component = AceType::DynamicCast<OHOS::Ace::SideBarContainerComponent>(stack->GetMainComponent());
165     if (!component) {
166         LOGE("side bar is null");
167         return;
168     }
169 
170     component->SetShowControlButton(isShow);
171 }
172 
JsSideBarPosition(const JSCallbackInfo & info)173 void JSSideBar::JsSideBarPosition(const JSCallbackInfo& info)
174 {
175     if (info.Length() < 1) {
176         LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
177         return;
178     }
179     SideBarPosition sideBarPosition = SideBarPosition::START;
180     if (info[0]->IsNumber()) {
181         sideBarPosition = static_cast<SideBarPosition>(info[0]->ToNumber<int>());
182     } else {
183         LOGE("The arg is wrong");
184         return;
185     }
186 
187     if (Container::IsCurrentUseNewPipeline()) {
188         NG::SideBarContainerView::SetSideBarPosition(sideBarPosition);
189         return;
190     }
191 
192     auto stack = ViewStackProcessor::GetInstance();
193     auto component = AceType::DynamicCast<SideBarContainerComponent>(stack->GetMainComponent());
194     if (!component) {
195         LOGE("side bar is null");
196         return;
197     }
198 
199     component->SetSideBarPosition(sideBarPosition);
200 }
201 
JSBind(BindingTarget globalObj)202 void JSSideBar::JSBind(BindingTarget globalObj)
203 {
204     JSClass<JSSideBar>::Declare("SideBarContainer");
205     MethodOptions opt = MethodOptions::NONE;
206     JSClass<JSSideBar>::StaticMethod("create", &JSSideBar::Create, opt);
207     JSClass<JSSideBar>::StaticMethod("pop", &JSSideBar::Pop);
208     JSClass<JSSideBar>::StaticMethod("showSideBar", &JSSideBar::JsShowSideBar);
209     JSClass<JSSideBar>::StaticMethod("controlButton", &JSSideBar::JsControlButton);
210     JSClass<JSSideBar>::StaticMethod("showControlButton", &JSSideBar::SetShowControlButton);
211     JSClass<JSSideBar>::StaticMethod("onChange", &JSSideBar::OnChange);
212     JSClass<JSSideBar>::StaticMethod("sideBarWidth", &JSSideBar::JsSideBarWidth);
213     JSClass<JSSideBar>::StaticMethod("minSideBarWidth", &JSSideBar::JsMinSideBarWidth);
214     JSClass<JSSideBar>::StaticMethod("maxSideBarWidth", &JSSideBar::JsMaxSideBarWidth);
215     JSClass<JSSideBar>::StaticMethod("autoHide", &JSSideBar::JsAutoHide);
216     JSClass<JSSideBar>::StaticMethod("sideBarPosition", &JSSideBar::JsSideBarPosition);
217     JSClass<JSSideBar>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
218     JSClass<JSSideBar>::StaticMethod("width", SetWidth);
219     JSClass<JSSideBar>::StaticMethod("height", SetHeight);
220     JSClass<JSSideBar>::StaticMethod("size", SetSize);
221     JSClass<JSSideBar>::StaticMethod("width", &JSStack::SetWidth);
222     JSClass<JSSideBar>::StaticMethod("height", &JSStack::SetHeight);
223     JSClass<JSSideBar>::StaticMethod("size", &JSStack::SetSize);
224     JSClass<JSSideBar>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
225     JSClass<JSSideBar>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
226     JSClass<JSSideBar>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
227     JSClass<JSSideBar>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
228     JSClass<JSSideBar>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
229     JSClass<JSSideBar>::Inherit<JSContainerBase>();
230     JSClass<JSSideBar>::Inherit<JSViewAbstract>();
231     JSClass<JSSideBar>::Bind(globalObj);
232 }
233 
OnChange(const JSCallbackInfo & info)234 void JSSideBar::OnChange(const JSCallbackInfo& info)
235 {
236     if (Container::IsCurrentUseNewPipeline()) {
237         if (info.Length() < 1 || !info[0]->IsFunction()) {
238             LOGE("JSSideBar::OnChange info param is wrong.");
239             return;
240         }
241 
242         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
243         auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](bool isShow) {
244             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
245             ACE_SCORING_EVENT("SideBarContainer.onChange");
246             auto newJSVal = JSRef<JSVal>::Make(ToJSValue(isShow));
247             func->ExecuteJS(1, &newJSVal);
248         };
249         NG::SideBarContainerView::SetOnChange(std::move(onChange));
250         return;
251     }
252 
253     if (!JSViewBindEvent(&SideBarContainerComponent::SetOnChange, info)) {
254         LOGE("Failed to bind event");
255     }
256     info.ReturnSelf();
257 }
258 
JsSideBarWidth(const JSCallbackInfo & info)259 void JSSideBar::JsSideBarWidth(const JSCallbackInfo& info)
260 {
261     ParseAndSetWidth(info, WidthType::SIDEBAR_WIDTH);
262 }
263 
JsMaxSideBarWidth(const JSCallbackInfo & info)264 void JSSideBar::JsMaxSideBarWidth(const JSCallbackInfo& info)
265 {
266     ParseAndSetWidth(info, WidthType::MAX_SIDEBAR_WIDTH);
267 }
268 
JsMinSideBarWidth(const JSCallbackInfo & info)269 void JSSideBar::JsMinSideBarWidth(const JSCallbackInfo& info)
270 {
271     ParseAndSetWidth(info, WidthType::MIN_SIDEBAR_WIDTH);
272 }
273 
JsShowSideBar(bool isShow)274 void JSSideBar::JsShowSideBar(bool isShow)
275 {
276     if (Container::IsCurrentUseNewPipeline()) {
277         NG::SideBarContainerView::SetShowSideBar(isShow);
278         return;
279     }
280 
281     auto stack = ViewStackProcessor::GetInstance();
282     auto component = AceType::DynamicCast<OHOS::Ace::SideBarContainerComponent>(stack->GetMainComponent());
283     if (!component) {
284         LOGE("side bar is null");
285         return;
286     }
287     component->SetShowSideBar(isShow);
288 }
289 
JsControlButton(const JSCallbackInfo & info)290 void JSSideBar::JsControlButton(const JSCallbackInfo& info)
291 {
292     if (Container::IsCurrentUseNewPipeline()) {
293         JsControlButtonForNG(info);
294         return;
295     }
296 
297     auto stack = ViewStackProcessor::GetInstance();
298     auto component = AceType::DynamicCast<OHOS::Ace::SideBarContainerComponent>(stack->GetMainComponent());
299     if (!component) {
300         LOGE("side bar is null");
301         return;
302     }
303 
304     if (!info[0]->IsNull() && info[0]->IsObject()) {
305         JSRef<JSObject> value = JSRef<JSObject>::Cast(info[0]);
306         JSRef<JSVal> width = value->GetProperty("width");
307         JSRef<JSVal> height = value->GetProperty("height");
308         JSRef<JSVal> left = value->GetProperty("left");
309         JSRef<JSVal> top = value->GetProperty("top");
310         JSRef<JSVal> icons = value->GetProperty("icons");
311 
312         if (!width->IsNull() && width->IsNumber()) {
313             auto controlButtonWidth = width->ToNumber<double>();
314             if (LessNotEqual(controlButtonWidth, 0.0)) {
315                 controlButtonWidth = DEFAULT_CONTROL_BUTTON_WIDTH.Value();
316             }
317             component->SetButtonWidth(controlButtonWidth);
318         }
319 
320         if (!height->IsNull() && height->IsNumber()) {
321             auto controlButtonHeight = height->ToNumber<double>();
322             if (LessNotEqual(controlButtonHeight, 0.0)) {
323                 controlButtonHeight = DEFAULT_CONTROL_BUTTON_HEIGHT.Value();
324             }
325             component->SetButtonHeight(controlButtonHeight);
326         }
327 
328         if (!left->IsNull() && left->IsNumber()) {
329             component->SetButtonLeft(left->ToNumber<double>());
330         }
331 
332         if (!top->IsNull() && top->IsNumber()) {
333             component->SetButtonTop(top->ToNumber<double>());
334         }
335 
336         if (!icons->IsNull() && icons->IsObject()) {
337             JSRef<JSObject> iconsVal = JSRef<JSObject>::Cast(icons);
338             JSRef<JSVal> showIcon = iconsVal->GetProperty("shown");
339             JSRef<JSVal> switchingIcon = iconsVal->GetProperty("switching");
340             JSRef<JSVal> hiddenIcon = iconsVal->GetProperty("hidden");
341             std::string showIconStr;
342             if (!showIcon->IsNull() && ParseJsMedia(showIcon, showIconStr)) {
343                 component->SetShowIcon(showIconStr);
344             }
345             std::string hiddenIconStr;
346             if (!hiddenIcon->IsNull() && ParseJsMedia(hiddenIcon, hiddenIconStr)) {
347                 component->SetHiddenIcon(hiddenIconStr);
348             }
349             std::string switchingIconStr;
350             if (!switchingIcon->IsNull() && ParseJsMedia(switchingIcon, switchingIconStr)) {
351                 component->SetSwitchIcon(switchingIconStr);
352             }
353         }
354     }
355 }
356 
JsControlButtonForNG(const JSCallbackInfo & info)357 void JSSideBar::JsControlButtonForNG(const JSCallbackInfo& info)
358 {
359     if (info.Length() < 1) {
360         LOGE("JSSideBar::JsControlButtonForNG The arg is wrong, it is supposed to have at least 1 arguments");
361         return;
362     }
363 
364     if (!info[0]->IsNull() && info[0]->IsObject()) {
365         JSRef<JSObject> value = JSRef<JSObject>::Cast(info[0]);
366         JSRef<JSVal> width = value->GetProperty("width");
367         JSRef<JSVal> height = value->GetProperty("height");
368         JSRef<JSVal> left = value->GetProperty("left");
369         JSRef<JSVal> top = value->GetProperty("top");
370         JSRef<JSVal> icons = value->GetProperty("icons");
371 
372         if (!width->IsNull() && width->IsNumber()) {
373             auto controlButtonWidth = Dimension(width->ToNumber<double>(), DimensionUnit::VP);
374             if (LessNotEqual(controlButtonWidth.Value(), 0.0)) {
375                 controlButtonWidth = DEFAULT_CONTROL_BUTTON_WIDTH;
376             }
377             NG::SideBarContainerView::SetControlButtonWidth(controlButtonWidth);
378         }
379 
380         if (!height->IsNull() && height->IsNumber()) {
381             auto controlButtonHeight = Dimension(height->ToNumber<double>(), DimensionUnit::VP);
382             if (LessNotEqual(controlButtonHeight.Value(), 0.0)) {
383                 controlButtonHeight = DEFAULT_CONTROL_BUTTON_HEIGHT;
384             }
385             NG::SideBarContainerView::SetControlButtonHeight(controlButtonHeight);
386         }
387 
388         if (!left->IsNull() && left->IsNumber()) {
389             NG::SideBarContainerView::SetControlButtonLeft(Dimension(left->ToNumber<double>(), DimensionUnit::VP));
390         }
391 
392         if (!top->IsNull() && top->IsNumber()) {
393             NG::SideBarContainerView::SetControlButtonTop(Dimension(top->ToNumber<double>(), DimensionUnit::VP));
394         }
395 
396         if (!icons->IsNull() && icons->IsObject()) {
397             JSRef<JSObject> iconsVal = JSRef<JSObject>::Cast(icons);
398             JSRef<JSVal> showIcon = iconsVal->GetProperty("shown");
399             JSRef<JSVal> switchingIcon = iconsVal->GetProperty("switching");
400             JSRef<JSVal> hiddenIcon = iconsVal->GetProperty("hidden");
401             std::string showIconStr;
402             if (!showIcon->IsNull() && ParseJsMedia(showIcon, showIconStr)) {
403                 NG::SideBarContainerView::SetControlButtonShowIconStr(showIconStr);
404             }
405             std::string hiddenIconStr;
406             if (!hiddenIcon->IsNull() && ParseJsMedia(hiddenIcon, hiddenIconStr)) {
407                 NG::SideBarContainerView::SetControlButtonHiddenIconStr(hiddenIconStr);
408             }
409             std::string switchingIconStr;
410             if (!switchingIcon->IsNull() && ParseJsMedia(switchingIcon, switchingIconStr)) {
411                 NG::SideBarContainerView::SetControlButtonSwitchingIconStr(switchingIconStr);
412             }
413         }
414     }
415 }
416 
JsAutoHide(bool autoHide)417 void JSSideBar::JsAutoHide(bool autoHide)
418 {
419     if (Container::IsCurrentUseNewPipeline()) {
420         NG::SideBarContainerView::SetAutoHide(autoHide);
421         return;
422     }
423 
424     auto stack = ViewStackProcessor::GetInstance();
425     auto component = AceType::DynamicCast<OHOS::Ace::SideBarContainerComponent>(stack->GetMainComponent());
426     if (!component) {
427         LOGE("side bar is null");
428         return;
429     }
430     component->SetAutoHide(autoHide);
431 }
432 
Pop()433 void JSSideBar::Pop()
434 {
435     if (Container::IsCurrentUseNewPipeline()) {
436         NG::SideBarContainerView::Pop();
437         NG::ViewStackProcessor::GetInstance()->PopContainer();
438         return;
439     }
440 
441     ViewStackProcessor::GetInstance()->PopContainer();
442 }
443 
444 } // namespace OHOS::Ace::Framework
445