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