1 /*
2  * Copyright (c) 2022-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_side_bar.h"
17 
18 #include "base/geometry/dimension.h"
19 #include "base/image/pixel_map.h"
20 #include "base/log/ace_scoring_log.h"
21 #include "base/log/log.h"
22 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
23 #include "bridge/declarative_frontend/engine/js_types.h"
24 #include "bridge/declarative_frontend/jsview/js_utils.h"
25 #include "core/components_ng/base/view_stack_processor.h"
26 #include "core/components_ng/pattern/side_bar/side_bar_container_model_ng.h"
27 #include "frameworks/bridge/declarative_frontend/jsview/js_view_common_def.h"
28 #include "frameworks/bridge/declarative_frontend/jsview/models/side_bar_container_model_impl.h"
29 
30 namespace OHOS::Ace {
31 std::unique_ptr<SideBarContainerModel> SideBarContainerModel::instance_ = nullptr;
32 std::mutex SideBarContainerModel::mutex_;
33 
GetInstance()34 SideBarContainerModel* SideBarContainerModel::GetInstance()
35 {
36     if (!instance_) {
37         std::lock_guard<std::mutex> lock(mutex_);
38         if (!instance_) {
39 #ifdef NG_BUILD
40             instance_.reset(new NG::SideBarContainerModelNG());
41 #else
42             if (Container::IsCurrentUseNewPipeline()) {
43                 instance_.reset(new NG::SideBarContainerModelNG());
44             } else {
45                 instance_.reset(new Framework::SideBarContainerModelImpl());
46             }
47 #endif
48         }
49     }
50     return instance_.get();
51 }
52 } // namespace OHOS::Ace
53 
54 namespace OHOS::Ace::Framework {
55 namespace {
56 constexpr Dimension DEFAULT_CONTROL_BUTTON_WIDTH = 32.0_vp;
57 constexpr Dimension DEFAULT_CONTROL_BUTTON_HEIGHT = 32.0_vp;
58 constexpr Dimension DEFAULT_CONTROL_BUTTON_TOP = 48.0_vp;
59 constexpr Dimension DEFAULT_DIVIDER_STROKE_WIDTH = 1.0_vp;
60 constexpr Dimension DEFAULT_DIVIDER_START_MARGIN = 0.0_vp;
61 constexpr Dimension DEFAULT_DIVIDER_END_MARGIN = 0.0_vp;
62 static Dimension DEFAULT_SIDE_BAR_WIDTH = 200.0_vp;
63 static Dimension DEFAULT_MIN_SIDE_BAR_WIDTH = 200.0_vp;
64 constexpr Dimension DEFAULT_MAX_SIDE_BAR_WIDTH = 280.0_vp;
65 constexpr Color DEFAULT_DIVIDER_COLOR = Color(0x08000000);
66 
ParseAndSetWidth(const JSCallbackInfo & info,WidthType widthType)67 void ParseAndSetWidth(const JSCallbackInfo& info, WidthType widthType)
68 {
69     if (info.Length() < 1) {
70         return;
71     }
72 
73     CalcDimension value;
74     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
75         DEFAULT_SIDE_BAR_WIDTH = 240.0_vp;
76         DEFAULT_MIN_SIDE_BAR_WIDTH = 240.0_vp;
77     }
78 
79     auto isValid = Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)
80                        ? JSViewAbstract::ParseJsDimensionVpNG(info[0], value)
81                        : JSViewAbstract::ParseJsDimensionVp(info[0], value);
82     if (!isValid) {
83         switch (widthType) {
84             case WidthType::SIDEBAR_WIDTH:
85                 value = DEFAULT_SIDE_BAR_WIDTH;
86                 break;
87             case WidthType::MIN_SIDEBAR_WIDTH:
88                 value = DEFAULT_MIN_SIDE_BAR_WIDTH;
89                 break;
90             case WidthType::MAX_SIDEBAR_WIDTH:
91                 value = DEFAULT_MAX_SIDE_BAR_WIDTH;
92                 break;
93             default:
94                 break;
95         }
96     }
97     SideBarContainerModel::GetInstance()->ParseAndSetWidth(widthType, value);
98 }
99 } // namespace
100 
Create(const JSCallbackInfo & info)101 void JSSideBar::Create(const JSCallbackInfo& info)
102 {
103     SideBarContainerModel::GetInstance()->Create();
104     SideBarContainerType style = SideBarContainerType::EMBED;
105     if (!info[0]->IsNull()) {
106         if (info[0]->IsBoolean()) {
107             style = static_cast<SideBarContainerType>(info[0]->ToBoolean());
108         } else if (info[0]->IsNumber()) {
109             style = static_cast<SideBarContainerType>(info[0]->ToNumber<int>());
110         } else {
111             return;
112         }
113     }
114     SideBarContainerModel::GetInstance()->SetSideBarContainerType(style);
115 }
116 
SetShowControlButton(const JSCallbackInfo & info)117 void JSSideBar::SetShowControlButton(const JSCallbackInfo& info)
118 {
119     if (info.Length() < 1) {
120         return;
121     }
122     if (info[0]->IsNull() || info[0]->IsUndefined()) {
123         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
124             // showControlButton set default true when input illegal value
125             SideBarContainerModel::GetInstance()->SetShowControlButton(true);
126         }
127         return;
128     }
129     if (info[0]->IsBoolean()) {
130         SideBarContainerModel::GetInstance()->SetShowControlButton(info[0]->ToBoolean());
131     }
132 }
133 
JsSideBarPosition(const JSCallbackInfo & info)134 void JSSideBar::JsSideBarPosition(const JSCallbackInfo& info)
135 {
136     if (info.Length() < 1) {
137         return;
138     }
139     if (info[0]->IsNull() || info[0]->IsUndefined()) {
140         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
141             // sideBarPosition set default START when input illegal value
142             SideBarContainerModel::GetInstance()->SetSideBarPosition(SideBarPosition::START);
143         }
144         return;
145     }
146     if (info[0]->IsNumber() && info[0]->ToNumber<int32_t>() >= 0 && info[0]->ToNumber<int32_t>() <= 1) {
147         SideBarContainerModel::GetInstance()->SetSideBarPosition(
148             static_cast<SideBarPosition>(info[0]->ToNumber<int32_t>()));
149     }
150 }
151 
JSBind(BindingTarget globalObj)152 void JSSideBar::JSBind(BindingTarget globalObj)
153 {
154     JSClass<JSSideBar>::Declare("SideBarContainer");
155     MethodOptions opt = MethodOptions::NONE;
156     JSClass<JSSideBar>::StaticMethod("create", &JSSideBar::Create, opt);
157     JSClass<JSSideBar>::StaticMethod("showSideBar", &JSSideBar::JsShowSideBar);
158     JSClass<JSSideBar>::StaticMethod("controlButton", &JSSideBar::JsControlButton);
159     JSClass<JSSideBar>::StaticMethod("showControlButton", &JSSideBar::SetShowControlButton);
160     JSClass<JSSideBar>::StaticMethod("onChange", &JSSideBar::OnChange);
161     JSClass<JSSideBar>::StaticMethod("sideBarWidth", &JSSideBar::JsSideBarWidth);
162     JSClass<JSSideBar>::StaticMethod("minSideBarWidth", &JSSideBar::JsMinSideBarWidth);
163     JSClass<JSSideBar>::StaticMethod("maxSideBarWidth", &JSSideBar::JsMaxSideBarWidth);
164     JSClass<JSSideBar>::StaticMethod("autoHide", &JSSideBar::JsAutoHide);
165     JSClass<JSSideBar>::StaticMethod("sideBarPosition", &JSSideBar::JsSideBarPosition);
166     JSClass<JSSideBar>::StaticMethod("divider", &JSSideBar::JsDivider);
167     JSClass<JSSideBar>::StaticMethod("minContentWidth", &JSSideBar::JsMinContentWidth);
168     JSClass<JSSideBar>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
169     JSClass<JSSideBar>::StaticMethod("width", SetWidth);
170     JSClass<JSSideBar>::StaticMethod("height", SetHeight);
171     JSClass<JSSideBar>::StaticMethod("size", SetSize);
172     JSClass<JSSideBar>::StaticMethod("width", &JSStack::SetWidth);
173     JSClass<JSSideBar>::StaticMethod("height", &JSStack::SetHeight);
174     JSClass<JSSideBar>::StaticMethod("size", &JSStack::SetSize);
175     JSClass<JSSideBar>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
176     JSClass<JSSideBar>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
177     JSClass<JSSideBar>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
178     JSClass<JSSideBar>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
179     JSClass<JSSideBar>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
180     JSClass<JSSideBar>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
181     JSClass<JSSideBar>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
182     JSClass<JSSideBar>::InheritAndBind<JSContainerBase>(globalObj);
183 }
184 
OnChange(const JSCallbackInfo & info)185 void JSSideBar::OnChange(const JSCallbackInfo& info)
186 {
187     if (info.Length() < 1 || !info[0]->IsFunction()) {
188         return;
189     }
190 
191     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
192     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
193     auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](bool isShow) {
194         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
195         ACE_SCORING_EVENT("SideBarContainer.onChange");
196         PipelineContext::SetCallBackNode(node);
197         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(isShow));
198         func->ExecuteJS(1, &newJSVal);
199     };
200     SideBarContainerModel::GetInstance()->SetOnChange(std::move(onChange));
201     info.ReturnSelf();
202 }
203 
JsSideBarWidth(const JSCallbackInfo & info)204 void JSSideBar::JsSideBarWidth(const JSCallbackInfo& info)
205 {
206     ParseAndSetWidth(info, WidthType::SIDEBAR_WIDTH);
207 }
208 
JsMaxSideBarWidth(const JSCallbackInfo & info)209 void JSSideBar::JsMaxSideBarWidth(const JSCallbackInfo& info)
210 {
211     ParseAndSetWidth(info, WidthType::MAX_SIDEBAR_WIDTH);
212 }
213 
JsMinSideBarWidth(const JSCallbackInfo & info)214 void JSSideBar::JsMinSideBarWidth(const JSCallbackInfo& info)
215 {
216     ParseAndSetWidth(info, WidthType::MIN_SIDEBAR_WIDTH);
217 }
218 
ParseShowSideBarObject(const JSCallbackInfo & args,const JSRef<JSVal> & changeEventVal)219 void ParseShowSideBarObject(const JSCallbackInfo& args, const JSRef<JSVal>& changeEventVal)
220 {
221     CHECK_NULL_VOID(changeEventVal->IsFunction());
222 
223     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
224     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
225     auto onChangeEvent = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
226                              bool isShow) {
227         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
228         ACE_SCORING_EVENT("SideBarContainer.onChangeEvent");
229         PipelineContext::SetCallBackNode(node);
230         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(isShow));
231         func->ExecuteJS(1, &newJSVal);
232     };
233     SideBarContainerModel::GetInstance()->SetOnChangeEvent(std::move(onChangeEvent));
234 }
235 
JsShowSideBar(const JSCallbackInfo & info)236 void JSSideBar::JsShowSideBar(const JSCallbackInfo& info)
237 {
238     if (info.Length() < 1 || info.Length() > 2) {
239         return;
240     }
241 
242     bool isShow = true;
243     if (info.Length() > 0 && info[0]->IsBoolean()) {
244         isShow = info[0]->ToBoolean();
245     }
246 
247     SideBarContainerModel::GetInstance()->SetShowSideBar(isShow);
248     if (info.Length() > 1 && info[1]->IsFunction()) {
249         ParseShowSideBarObject(info, info[1]);
250     }
251 }
252 
SetControlButtonIcon(SideBarControlButtonType iconType,JSRef<JSVal> icon)253 void JSSideBar::SetControlButtonIcon(SideBarControlButtonType iconType, JSRef<JSVal> icon)
254 {
255     if (icon->IsUndefined() || icon->IsNull()) {
256         return;
257     }
258     std::string iconPath;
259     auto isStrType = ParseJsMedia(icon, iconPath);
260     RefPtr<PixelMap> pixMap = nullptr;
261 #if defined(PIXEL_MAP_SUPPORTED)
262     if (!isStrType) {
263         pixMap = CreatePixelMapFromNapiValue(icon);
264     }
265 #endif
266     if (isStrType || pixMap != nullptr) {
267         switch (iconType) {
268             case SideBarControlButtonType::SHOWN:
269                 SideBarContainerModel::GetInstance()->SetControlButtonShowIconInfo(iconPath, !isStrType, pixMap);
270                 break;
271             case SideBarControlButtonType::HIDDEN:
272                 SideBarContainerModel::GetInstance()->SetControlButtonHiddenIconInfo(iconPath, !isStrType, pixMap);
273                 break;
274             case SideBarControlButtonType::SWITCHING:
275                 SideBarContainerModel::GetInstance()->SetControlButtonSwitchingIconInfo(iconPath, !isStrType, pixMap);
276                 break;
277             default:
278                 break;
279         }
280     }
281 }
282 
JsControlButton(const JSCallbackInfo & info)283 void JSSideBar::JsControlButton(const JSCallbackInfo& info)
284 {
285     if (info.Length() < 1) {
286         return;
287     }
288     if (info[0]->IsNull() || info[0]->IsUndefined()) {
289         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
290             // controlButton icon set default style and position when input illegal value
291             SideBarContainerModel::GetInstance()->SetControlButtonWidth(DEFAULT_CONTROL_BUTTON_WIDTH);
292             SideBarContainerModel::GetInstance()->SetControlButtonHeight(DEFAULT_CONTROL_BUTTON_HEIGHT);
293             SideBarContainerModel::GetInstance()->ResetControlButtonLeft();
294             SideBarContainerModel::GetInstance()->SetControlButtonTop(DEFAULT_CONTROL_BUTTON_TOP);
295             SideBarContainerModel::GetInstance()->ResetControlButtonIconInfo();
296         }
297         return;
298     }
299     if (info[0]->IsObject()) {
300         JSRef<JSObject> value = JSRef<JSObject>::Cast(info[0]);
301         if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TEN)) {
302             ParseControlButtonOG(value);
303         } else {
304             ParseControlButtonNG(value);
305         }
306 
307         JSRef<JSVal> icons = value->GetProperty("icons");
308         if (icons->IsNull() || icons->IsUndefined()) {
309             if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
310                 // controlButton icon set default style when input illegal value
311                 SideBarContainerModel::GetInstance()->ResetControlButtonIconInfo();
312             }
313             return;
314         }
315         if (icons->IsObject()) {
316             JSRef<JSObject> iconsVal = JSRef<JSObject>::Cast(icons);
317             JSRef<JSVal> showIcon = iconsVal->GetProperty("shown");
318             JSRef<JSVal> switchingIcon = iconsVal->GetProperty("switching");
319             JSRef<JSVal> hiddenIcon = iconsVal->GetProperty("hidden");
320             SetControlButtonIcon(SideBarControlButtonType::SHOWN, showIcon);
321             SetControlButtonIcon(SideBarControlButtonType::HIDDEN, hiddenIcon);
322             SetControlButtonIcon(SideBarControlButtonType::SWITCHING, switchingIcon);
323         }
324     }
325 }
326 
JsDivider(const JSCallbackInfo & info)327 void JSSideBar::JsDivider(const JSCallbackInfo& info)
328 {
329     if (info.Length() < 1) {
330         return;
331     }
332     if (info[0]->IsNull() || info[0]->IsUndefined()) {
333         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
334             // sideBar divider set default width when input illegal value
335             SideBarContainerModel::GetInstance()->SetDividerStrokeWidth(DEFAULT_DIVIDER_STROKE_WIDTH);
336         } else if (info[0]->IsNull()) {
337             SideBarContainerModel::GetInstance()->SetDividerStrokeWidth(0.0_vp);
338         }
339         return;
340     }
341     if (info[0]->IsObject()) {
342         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
343 
344         Dimension strokeWidth = DEFAULT_DIVIDER_STROKE_WIDTH;
345         if (!ConvertFromJSValueNG(obj->GetProperty("strokeWidth"), strokeWidth) || (strokeWidth.Value() < 0.0f)) {
346             strokeWidth = DEFAULT_DIVIDER_STROKE_WIDTH;
347         }
348         SideBarContainerModel::GetInstance()->SetDividerStrokeWidth(strokeWidth);
349 
350         Color color = DEFAULT_DIVIDER_COLOR;
351         if (!ConvertFromJSValue(obj->GetProperty("color"), color)) {
352             color = DEFAULT_DIVIDER_COLOR;
353         }
354         SideBarContainerModel::GetInstance()->SetDividerColor(color);
355 
356         Dimension startMargin = DEFAULT_DIVIDER_START_MARGIN;
357         if (!ConvertFromJSValueNG(obj->GetProperty("startMargin"), startMargin) || (startMargin.Value() < 0.0f)) {
358             startMargin = DEFAULT_DIVIDER_START_MARGIN;
359         }
360         SideBarContainerModel::GetInstance()->SetDividerStartMargin(startMargin);
361 
362         Dimension endMargin = DEFAULT_DIVIDER_END_MARGIN;
363         if (!ConvertFromJSValueNG(obj->GetProperty("endMargin"), endMargin) || (endMargin.Value() < 0.0f)) {
364             endMargin = DEFAULT_DIVIDER_END_MARGIN;
365         }
366         SideBarContainerModel::GetInstance()->SetDividerEndMargin(endMargin);
367     }
368 }
369 
JsMinContentWidth(const JSCallbackInfo & info)370 void JSSideBar::JsMinContentWidth(const JSCallbackInfo& info)
371 {
372     if (info.Length() < 1) {
373         return;
374     }
375     if (info[0]->IsNull()) {
376         SideBarContainerModel::GetInstance()->SetMinContentWidth(-1.0_vp);
377         return;
378     }
379     CalcDimension minContentWidth;
380     if (!JSViewAbstract::ParseJsDimensionVp(info[0], minContentWidth)) {
381         SideBarContainerModel::GetInstance()->SetMinContentWidth(-1.0_vp);
382         return;
383     }
384     SideBarContainerModel::GetInstance()->SetMinContentWidth(minContentWidth);
385 }
386 
JsAutoHide(bool autoHide)387 void JSSideBar::JsAutoHide(bool autoHide)
388 {
389     SideBarContainerModel::GetInstance()->SetAutoHide(autoHide);
390 }
391 
ParseControlButtonOG(JSRef<JSObject> value)392 void JSSideBar::ParseControlButtonOG(JSRef<JSObject> value)
393 {
394     JSRef<JSVal> width = value->GetProperty("width");
395     JSRef<JSVal> height = value->GetProperty("height");
396     JSRef<JSVal> left = value->GetProperty("left");
397     JSRef<JSVal> top = value->GetProperty("top");
398 
399     if (!width->IsNull() && width->IsNumber()) {
400         auto controlButtonWidth = CalcDimension(width->ToNumber<double>(), DimensionUnit::VP);
401         if (LessNotEqual(controlButtonWidth.Value(), 0.0)) {
402             controlButtonWidth = DEFAULT_CONTROL_BUTTON_WIDTH;
403         }
404         SideBarContainerModel::GetInstance()->SetControlButtonWidth(controlButtonWidth);
405     }
406 
407     if (!height->IsNull() && height->IsNumber()) {
408         auto controlButtonHeight = CalcDimension(height->ToNumber<double>(), DimensionUnit::VP);
409         if (LessNotEqual(controlButtonHeight.Value(), 0.0)) {
410             controlButtonHeight = DEFAULT_CONTROL_BUTTON_HEIGHT;
411         }
412         SideBarContainerModel::GetInstance()->SetControlButtonHeight(controlButtonHeight);
413     }
414 
415     if (!left->IsNull() && left->IsNumber()) {
416         SideBarContainerModel::GetInstance()->SetControlButtonLeft(
417             Dimension(left->ToNumber<double>(), DimensionUnit::VP));
418     }
419 
420     if (!top->IsNull() && top->IsNumber()) {
421         SideBarContainerModel::GetInstance()->SetControlButtonTop(
422             Dimension(top->ToNumber<double>(), DimensionUnit::VP));
423     }
424 }
425 
ParseControlButtonNG(JSRef<JSObject> value)426 void JSSideBar::ParseControlButtonNG(JSRef<JSObject> value)
427 {
428     JSRef<JSVal> width = value->GetProperty("width");
429     JSRef<JSVal> height = value->GetProperty("height");
430     JSRef<JSVal> left = value->GetProperty("left");
431     JSRef<JSVal> top = value->GetProperty("top");
432 
433     auto controlButtonWidth = DEFAULT_CONTROL_BUTTON_WIDTH;
434     if (width->IsNumber() && GreatOrEqual(width->ToNumber<double>(), 0.0)) {
435         controlButtonWidth = CalcDimension(width->ToNumber<double>(), DimensionUnit::VP);
436     }
437     SideBarContainerModel::GetInstance()->SetControlButtonWidth(controlButtonWidth);
438 
439     auto controlButtonHeight = DEFAULT_CONTROL_BUTTON_HEIGHT;
440     if (height->IsNumber() && GreatOrEqual(height->ToNumber<double>(), 0.0)) {
441         controlButtonHeight = CalcDimension(height->ToNumber<double>(), DimensionUnit::VP);
442     }
443     SideBarContainerModel::GetInstance()->SetControlButtonHeight(controlButtonHeight);
444 
445     if (left->IsNumber() && GreatOrEqual(left->ToNumber<double>(), 0.0)) {
446         auto controlButtonLeft = CalcDimension(left->ToNumber<double>(), DimensionUnit::VP);
447         SideBarContainerModel::GetInstance()->SetControlButtonLeft(controlButtonLeft);
448     } else {
449         SideBarContainerModel::GetInstance()->ResetControlButtonLeft();
450     }
451 
452     auto controlButtonTop = DEFAULT_CONTROL_BUTTON_TOP;
453     if (top->IsNumber() && GreatOrEqual(top->ToNumber<double>(), 0.0)) {
454         controlButtonTop = CalcDimension(top->ToNumber<double>(), DimensionUnit::VP);
455     }
456     SideBarContainerModel::GetInstance()->SetControlButtonTop(controlButtonTop);
457 }
458 
459 } // namespace OHOS::Ace::Framework
460