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_tab_content.h"
17
18 #include <optional>
19
20 #include "base/log/ace_scoring_log.h"
21 #include "base/log/ace_trace.h"
22 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
23 #include "bridge/declarative_frontend/jsview/models/tab_content_model_impl.h"
24 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
25 #include "core/components/tab_bar/tab_theme.h"
26 #include "core/components_ng/pattern/tabs/tab_content_model_ng.h"
27 #include "core/components_ng/pattern/tabs/tabs_layout_property.h"
28 #include "core/components_ng/pattern/tabs/tabs_node.h"
29 #include "core/components_ng/property/measure_property.h"
30
31 namespace OHOS::Ace {
32
33 std::unique_ptr<TabContentModel> TabContentModel::instance_ = nullptr;
34 std::mutex TabContentModel::mutex_;
35
36 const std::vector<TextOverflow> TEXT_OVERFLOWS = { TextOverflow::NONE, TextOverflow::CLIP, TextOverflow::ELLIPSIS,
37 TextOverflow::MARQUEE };
38 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
39 const std::vector<TextHeightAdaptivePolicy> HEIGHT_ADAPTIVE_POLICIES = { TextHeightAdaptivePolicy::MAX_LINES_FIRST,
40 TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST, TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST };
41
GetInstance()42 TabContentModel* TabContentModel::GetInstance()
43 {
44 if (!instance_) {
45 std::lock_guard<std::mutex> lock(mutex_);
46 if (!instance_) {
47 #ifdef NG_BUILD
48 instance_.reset(new NG::TabContentModelNG());
49 #else
50 if (Container::IsCurrentUseNewPipeline()) {
51 instance_.reset(new NG::TabContentModelNG());
52 } else {
53 instance_.reset(new Framework::TabContentModelImpl());
54 }
55 #endif
56 }
57 }
58 return instance_.get();
59 }
60
61 } // namespace OHOS::Ace
62
63 namespace OHOS::Ace::Framework {
64
Create(const JSCallbackInfo & info)65 void JSTabContent::Create(const JSCallbackInfo& info)
66 {
67 if (Container::IsCurrentUsePartialUpdate()) {
68 CreateForPartialUpdate(info);
69 return;
70 }
71 TabContentModel::GetInstance()->Create();
72 }
73
CreateForPartialUpdate(const JSCallbackInfo & info)74 void JSTabContent::CreateForPartialUpdate(const JSCallbackInfo& info)
75 {
76 if (info.Length() <= 0 && !info[0]->IsFunction()) {
77 TabContentModel::GetInstance()->Create();
78 return;
79 }
80
81 JSRef<JSVal> builderFunctionJS = info[0];
82 auto builderFunc = [context = info.GetExecutionContext(), builder = std::move(builderFunctionJS)]() {
83 JAVASCRIPT_EXECUTION_SCOPE(context)
84 JSRef<JSFunc>::Cast(builder)->Call(JSRef<JSObject>());
85 };
86 TabContentModel::GetInstance()->Create(std::move(builderFunc));
87 }
88
SetTabBar(const JSCallbackInfo & info)89 void JSTabContent::SetTabBar(const JSCallbackInfo& info)
90 {
91 if (info.Length() <= 0) {
92 return;
93 }
94 auto tabBarInfo = info[0];
95
96 std::string infoStr;
97 if (ParseJsString(tabBarInfo, infoStr)) {
98 TabContentModel::GetInstance()->SetTabBarStyle(TabBarStyle::NOSTYLE);
99 TabContentModel::GetInstance()->SetTabBar(infoStr, std::nullopt, std::nullopt, nullptr, true);
100 return;
101 }
102
103 if (!tabBarInfo->IsObject()) {
104 return;
105 }
106
107 auto paramObject = JSRef<JSObject>::Cast(tabBarInfo);
108 JSRef<JSVal> builderFuncParam = paramObject->GetProperty("builder");
109 if (builderFuncParam->IsFunction()) {
110 auto tabBarBuilder = AceType::MakeRefPtr<JsFunction>(info.This(), JSRef<JSFunc>::Cast(builderFuncParam));
111 auto tabBarBuilderFunc = [execCtx = info.GetExecutionContext(),
112 tabBarBuilderFunc = std::move(tabBarBuilder)]() {
113 if (tabBarBuilderFunc) {
114 ACE_SCOPED_TRACE("JSTabContent::Execute TabBar builder");
115 JAVASCRIPT_EXECUTION_SCOPE(execCtx);
116 tabBarBuilderFunc->ExecuteJS();
117 }
118 };
119 TabContentModel::GetInstance()->SetTabBarStyle(TabBarStyle::NOSTYLE);
120 TabContentModel::GetInstance()->SetTabBar(
121 std::nullopt, std::nullopt, std::nullopt, std::move(tabBarBuilderFunc), false);
122 return;
123 }
124 JSRef<JSVal> typeParam = paramObject->GetProperty("type");
125 if (typeParam->IsString()) {
126 auto type = typeParam->ToString();
127 if (type == "SubTabBarStyle") {
128 SetSubTabBarStyle(paramObject);
129 return;
130 }
131 if (type == "BottomTabBarStyle") {
132 SetBottomTabBarStyle(info);
133 return;
134 }
135 }
136
137 JSRef<JSVal> textParam = paramObject->GetProperty("text");
138 auto isTextEmpty = textParam->IsEmpty() || textParam->IsUndefined() || textParam->IsNull();
139 std::optional<std::string> textOpt = std::nullopt;
140 if (!isTextEmpty) {
141 std::string text;
142 if (ParseJsString(textParam, text)) {
143 textOpt = text;
144 }
145 }
146
147 JSRef<JSVal> iconParam = paramObject->GetProperty("icon");
148 auto isIconEmpty = iconParam->IsEmpty() || iconParam->IsUndefined() || iconParam->IsNull();
149 std::optional<std::string> iconOpt = std::nullopt;
150 if (!isIconEmpty) {
151 std::string icon;
152 if (ParseJsMedia(iconParam, icon)) {
153 iconOpt = icon;
154 }
155 }
156 TabContentModel::GetInstance()->SetTabBarStyle(TabBarStyle::NOSTYLE);
157 TabContentModel::GetInstance()->SetTabBar(textOpt, iconOpt, std::nullopt, nullptr, false);
158 }
159
Pop()160 void JSTabContent::Pop()
161 {
162 TabContentModel::GetInstance()->Pop();
163 }
164
SetIndicator(const JSRef<JSVal> & info)165 void JSTabContent::SetIndicator(const JSRef<JSVal>& info)
166 {
167 JSRef<JSObject> obj = JSRef<JSObject>::New();
168 if (info->IsObject()) {
169 obj = JSRef<JSObject>::Cast(info);
170 }
171 IndicatorStyle indicator;
172 CalcDimension indicatorHeight;
173 CalcDimension indicatorWidth;
174 CalcDimension indicatorBorderRadius;
175 CalcDimension indicatorMarginTop;
176 if (!info->IsObject() || !ConvertFromJSValue(obj->GetProperty("color"), indicator.color)) {
177 RefPtr<TabTheme> tabTheme = GetTheme<TabTheme>();
178 if (tabTheme) {
179 indicator.color = tabTheme->GetActiveIndicatorColor();
180 }
181 }
182 if (!info->IsObject() || !ParseJsDimensionVp(obj->GetProperty("height"), indicatorHeight) ||
183 indicatorHeight.Value() < 0.0f || indicatorHeight.Unit() == DimensionUnit::PERCENT) {
184 RefPtr<TabTheme> tabTheme = GetTheme<TabTheme>();
185 if (tabTheme) {
186 indicator.height = tabTheme->GetActiveIndicatorWidth();
187 }
188 } else {
189 indicator.height = indicatorHeight;
190 }
191 if (!info->IsObject() || !ParseJsDimensionVp(obj->GetProperty("width"), indicatorWidth) ||
192 indicatorWidth.Value() < 0.0f || indicatorWidth.Unit() == DimensionUnit::PERCENT) {
193 indicator.width = 0.0_vp;
194 } else {
195 indicator.width = indicatorWidth;
196 }
197 if (!info->IsObject() || !ParseJsDimensionVp(obj->GetProperty("borderRadius"), indicatorBorderRadius) ||
198 indicatorBorderRadius.Value() < 0.0f || indicatorBorderRadius.Unit() == DimensionUnit::PERCENT) {
199 indicator.borderRadius = 0.0_vp;
200 } else {
201 indicator.borderRadius = indicatorBorderRadius;
202 }
203 if (!info->IsObject() || !ParseJsDimensionVp(obj->GetProperty("marginTop"), indicatorMarginTop) ||
204 indicatorMarginTop.Value() < 0.0f || indicatorMarginTop.Unit() == DimensionUnit::PERCENT) {
205 RefPtr<TabTheme> tabTheme = GetTheme<TabTheme>();
206 if (tabTheme) {
207 indicator.marginTop = tabTheme->GetSubTabIndicatorGap();
208 }
209 } else {
210 indicator.marginTop = indicatorMarginTop;
211 }
212 TabContentModel::GetInstance()->SetIndicator(indicator);
213 }
214
SetBoard(const JSRef<JSVal> & info)215 void JSTabContent::SetBoard(const JSRef<JSVal>& info)
216 {
217 JSRef<JSObject> obj = JSRef<JSObject>::New();
218 if (info->IsObject()) {
219 obj = JSRef<JSObject>::Cast(info);
220 }
221 BoardStyle board;
222 CalcDimension borderRadius;
223 if (!info->IsObject() || !ParseJsDimensionVp(obj->GetProperty("borderRadius"), borderRadius) ||
224 borderRadius.Value() < 0.0f || borderRadius.Unit() == DimensionUnit::PERCENT) {
225 RefPtr<TabTheme> tabTheme = GetTheme<TabTheme>();
226 if (tabTheme) {
227 board.borderRadius = tabTheme->GetFocusIndicatorRadius();
228 }
229 } else {
230 board.borderRadius = borderRadius;
231 }
232 TabContentModel::GetInstance()->SetBoard(board);
233 }
234
SetSelectedMode(const JSRef<JSVal> & info)235 void JSTabContent::SetSelectedMode(const JSRef<JSVal>& info)
236 {
237 int32_t selectedMode;
238 if (!ConvertFromJSValue(info, selectedMode)) {
239 TabContentModel::GetInstance()->SetSelectedMode(SelectedMode::INDICATOR);
240 } else {
241 TabContentModel::GetInstance()->SetSelectedMode(static_cast<SelectedMode>(selectedMode));
242 }
243 }
244
GetFontContent(const JSRef<JSVal> font,LabelStyle & labelStyle,bool isSubTabStyle)245 void JSTabContent::GetFontContent(const JSRef<JSVal> font, LabelStyle& labelStyle, bool isSubTabStyle)
246 {
247 JSRef<JSObject> obj = JSRef<JSObject>::Cast(font);
248 JSRef<JSVal> size = obj->GetProperty("size");
249 CalcDimension fontSize;
250 if (ParseJsDimensionFp(size, fontSize) && NonNegative(fontSize.Value()) &&
251 fontSize.Unit() != DimensionUnit::PERCENT) {
252 labelStyle.fontSize = fontSize;
253 }
254
255 JSRef<JSVal> weight = obj->GetProperty("weight");
256 if (weight->IsString() || weight->IsNumber()) {
257 auto parseResult = ParseFontWeight(weight->ToString());
258 if (parseResult.first || !isSubTabStyle) {
259 labelStyle.fontWeight = parseResult.second;
260 }
261 }
262
263 JSRef<JSVal> family = obj->GetProperty("family");
264 std::vector<std::string> fontFamilies;
265 if (ParseJsFontFamilies(family, fontFamilies)) {
266 labelStyle.fontFamily = fontFamilies;
267 }
268
269 JSRef<JSVal> style = obj->GetProperty("style");
270 if (style->IsNumber()) {
271 int32_t value = style->ToNumber<int32_t>();
272 if (value >= 0 && value < static_cast<int32_t>(FONT_STYLES.size())) {
273 labelStyle.fontStyle = FONT_STYLES[value];
274 }
275 }
276 }
277
SetLabelStyle(const JSRef<JSVal> & info,bool isSubTabStyle)278 void JSTabContent::SetLabelStyle(const JSRef<JSVal>& info, bool isSubTabStyle)
279 {
280 LabelStyle labelStyle;
281 if (!info->IsObject()) {
282 LOGW("info not is Object");
283 } else {
284 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info);
285 JSRef<JSVal> overflowValue = obj->GetProperty("overflow");
286 if (!overflowValue->IsNull() && overflowValue->IsNumber()) {
287 auto overflow = overflowValue->ToNumber<int32_t>();
288 if (overflow >= 0 && overflow < static_cast<int32_t>(TEXT_OVERFLOWS.size())) {
289 labelStyle.textOverflow = TEXT_OVERFLOWS[overflow];
290 }
291 }
292
293 JSRef<JSVal> maxLines = obj->GetProperty("maxLines");
294 if (!maxLines->IsNull() && maxLines->IsNumber() && maxLines->ToNumber<int32_t>() > 0) {
295 labelStyle.maxLines = maxLines->ToNumber<int32_t>();
296 }
297
298 JSRef<JSVal> minFontSizeValue = obj->GetProperty("minFontSize");
299 CalcDimension minFontSize;
300 if (ParseJsDimensionFp(minFontSizeValue, minFontSize) && NonNegative(minFontSize.Value()) &&
301 minFontSize.Unit() != DimensionUnit::PERCENT) {
302 labelStyle.minFontSize = minFontSize;
303 }
304
305 JSRef<JSVal> maxFontSizeValue = obj->GetProperty("maxFontSize");
306 CalcDimension maxFontSize;
307 if (ParseJsDimensionFp(maxFontSizeValue, maxFontSize) && NonNegative(maxFontSize.Value()) &&
308 maxFontSize.Unit() != DimensionUnit::PERCENT) {
309 labelStyle.maxFontSize = maxFontSize;
310 }
311
312 JSRef<JSVal> heightAdaptivePolicyValue = obj->GetProperty("heightAdaptivePolicy");
313 if (!heightAdaptivePolicyValue->IsNull() && heightAdaptivePolicyValue->IsNumber()) {
314 auto heightAdaptivePolicy = heightAdaptivePolicyValue->ToNumber<int32_t>();
315 if (heightAdaptivePolicy >= 0 &&
316 heightAdaptivePolicy < static_cast<int32_t>(HEIGHT_ADAPTIVE_POLICIES.size())) {
317 labelStyle.heightAdaptivePolicy = HEIGHT_ADAPTIVE_POLICIES[heightAdaptivePolicy];
318 }
319 }
320
321 JSRef<JSVal> font = obj->GetProperty("font");
322 if (!font->IsNull() && font->IsObject()) {
323 GetFontContent(font, labelStyle, isSubTabStyle);
324 }
325
326 GetLabelUnselectedContent(obj->GetProperty("unselectedColor"), labelStyle);
327
328 GetLabelSelectedContent(obj->GetProperty("selectedColor"), labelStyle);
329 }
330 CompleteParameters(labelStyle, isSubTabStyle);
331 TabContentModel::GetInstance()->SetLabelStyle(labelStyle);
332 }
333
SetIconStyle(const JSRef<JSVal> & info)334 void JSTabContent::SetIconStyle(const JSRef<JSVal>& info)
335 {
336 IconStyle iconStyle;
337 if (info->IsObject()) {
338 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info);
339 Color unselectedColor;
340 JSRef<JSVal> unselectedColorValue = obj->GetProperty("unselectedColor");
341 if (ConvertFromJSValue(unselectedColorValue, unselectedColor)) {
342 iconStyle.unselectedColor = unselectedColor;
343 }
344
345 Color selectedColor;
346 JSRef<JSVal> selectedColorValue = obj->GetProperty("selectedColor");
347 if (ConvertFromJSValue(selectedColorValue, selectedColor)) {
348 iconStyle.selectedColor = selectedColor;
349 }
350 }
351 TabContentModel::GetInstance()->SetIconStyle(iconStyle);
352 }
353
GetLabelUnselectedContent(const JSRef<JSVal> unselectedColorValue,LabelStyle & labelStyle)354 void JSTabContent::GetLabelUnselectedContent(const JSRef<JSVal> unselectedColorValue, LabelStyle& labelStyle)
355 {
356 Color unselectedColor;
357 if (ConvertFromJSValue(unselectedColorValue, unselectedColor)) {
358 labelStyle.unselectedColor = unselectedColor;
359 }
360 }
361
GetLabelSelectedContent(const JSRef<JSVal> selectedColorValue,LabelStyle & labelStyle)362 void JSTabContent::GetLabelSelectedContent(const JSRef<JSVal> selectedColorValue, LabelStyle& labelStyle)
363 {
364 Color selectedColor;
365 if (ConvertFromJSValue(selectedColorValue, selectedColor)) {
366 labelStyle.selectedColor = selectedColor;
367 }
368 }
369
ParseJsLengthMetrics(const JSRef<JSObject> & obj,CalcDimension & result)370 bool ParseJsLengthMetrics(const JSRef<JSObject>& obj, CalcDimension& result)
371 {
372 if (!obj->HasProperty("value")) {
373 return false;
374 }
375 auto value = obj->GetProperty("value");
376 if (!value->IsNumber()) {
377 return false;
378 }
379 auto unit = DimensionUnit::VP;
380 auto jsUnit = obj->GetProperty("unit");
381 if (jsUnit->IsNumber()) {
382 unit = static_cast<DimensionUnit>(jsUnit->ToNumber<int32_t>());
383 }
384 CalcDimension dimension(value->ToNumber<double>(), unit);
385 result = dimension;
386 return true;
387 }
388
SetPadding(const JSRef<JSVal> & info,bool isSubTabStyle)389 void JSTabContent::SetPadding(const JSRef<JSVal>& info, bool isSubTabStyle)
390 {
391 CalcDimension length;
392 NG::PaddingProperty padding;
393 bool useLocalizedPadding = false;
394 if (ParseJsDimensionVp(info, length) && NonNegative(length.Value()) && length.Unit() != DimensionUnit::PERCENT) {
395 padding.left = NG::CalcLength(length);
396 padding.right = NG::CalcLength(length);
397 padding.top = NG::CalcLength(length);
398 padding.bottom = NG::CalcLength(length);
399 TabContentModel::GetInstance()->SetPadding(padding);
400 return;
401 }
402
403 RefPtr<TabTheme> tabTheme = GetTheme<TabTheme>();
404 if (tabTheme) {
405 if (isSubTabStyle) {
406 padding.top = NG::CalcLength(tabTheme->GetSubTabTopPadding());
407 padding.bottom = NG::CalcLength(tabTheme->GetSubTabBottomPadding());
408 padding.left = NG::CalcLength(tabTheme->GetSubTabHorizontalPadding());
409 padding.right = NG::CalcLength(tabTheme->GetSubTabHorizontalPadding());
410 } else {
411 padding.top = NG::CalcLength(0.0_vp);
412 padding.bottom = NG::CalcLength(0.0_vp);
413 padding.left = NG::CalcLength(tabTheme->GetBottomTabHorizontalPadding());
414 padding.right = NG::CalcLength(tabTheme->GetBottomTabHorizontalPadding());
415 }
416 }
417 if (info->IsObject()) {
418 JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(info);
419 CalcDimension left;
420 if (ParseJsDimensionVp(paddingObj->GetProperty("left"), left) && NonNegative(left.Value()) &&
421 left.Unit() != DimensionUnit::PERCENT) {
422 padding.left = NG::CalcLength(left);
423 }
424 CalcDimension right;
425 if (ParseJsDimensionVp(paddingObj->GetProperty("right"), right) && NonNegative(right.Value()) &&
426 right.Unit() != DimensionUnit::PERCENT) {
427 padding.right = NG::CalcLength(right);
428 }
429 CalcDimension top;
430 if (ParseJsDimensionVp(paddingObj->GetProperty("top"), top) && NonNegative(top.Value()) &&
431 top.Unit() != DimensionUnit::PERCENT) {
432 padding.top = NG::CalcLength(top);
433 }
434 CalcDimension bottom;
435 if (ParseJsDimensionVp(paddingObj->GetProperty("bottom"), bottom) && NonNegative(bottom.Value()) &&
436 bottom.Unit() != DimensionUnit::PERCENT) {
437 padding.bottom = NG::CalcLength(bottom);
438 }
439 }
440 if (info->IsObject()) {
441 JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(info);
442 CalcDimension start;
443 CalcDimension end;
444 CalcDimension top;
445 CalcDimension bottom;
446 if (paddingObj->GetProperty("start")->IsObject()) {
447 JSRef<JSObject> startObj = JSRef<JSObject>::Cast(paddingObj->GetProperty("start"));
448 if (ParseJsLengthMetrics(startObj, start)) {
449 padding.left = NG::CalcLength(start);
450 useLocalizedPadding = true;
451 }
452 }
453 if (paddingObj->GetProperty("end")->IsObject()) {
454 JSRef<JSObject> endObj = JSRef<JSObject>::Cast(paddingObj->GetProperty("end"));
455 if (ParseJsLengthMetrics(endObj, end)) {
456 padding.right = NG::CalcLength(end);
457 useLocalizedPadding = true;
458 }
459 }
460 if (paddingObj->GetProperty("top")->IsObject()) {
461 JSRef<JSObject> topObj = JSRef<JSObject>::Cast(paddingObj->GetProperty("top"));
462 if (ParseJsLengthMetrics(topObj, top)) {
463 padding.top = NG::CalcLength(top);
464 useLocalizedPadding = true;
465 }
466 }
467 if (paddingObj->GetProperty("bottom")->IsObject()) {
468 JSRef<JSObject> bottomObj = JSRef<JSObject>::Cast(paddingObj->GetProperty("bottom"));
469 if (ParseJsLengthMetrics(bottomObj, bottom)) {
470 padding.bottom = NG::CalcLength(bottom);
471 useLocalizedPadding = true;
472 }
473 }
474 }
475 TabContentModel::GetInstance()->SetPadding(padding);
476 TabContentModel::GetInstance()->SetUseLocalizedPadding(useLocalizedPadding);
477 }
478
SetId(const JSRef<JSVal> & info)479 void JSTabContent::SetId(const JSRef<JSVal>& info)
480 {
481 std::string id;
482 if (!ParseJsString(info, id)) {
483 return;
484 }
485 TabContentModel::GetInstance()->SetId(id);
486 }
487
CompleteParameters(LabelStyle & labelStyle,bool isSubTabStyle)488 void JSTabContent::CompleteParameters(LabelStyle& labelStyle, bool isSubTabStyle)
489 {
490 auto tabTheme = GetTheme<TabTheme>();
491 if (!tabTheme) {
492 return;
493 }
494 if (!labelStyle.maxLines.has_value()) {
495 labelStyle.maxLines = 1;
496 }
497 if (!labelStyle.minFontSize.has_value()) {
498 labelStyle.minFontSize = 0.0_vp;
499 }
500 if (!labelStyle.maxFontSize.has_value()) {
501 labelStyle.maxFontSize = 0.0_vp;
502 }
503 if (!labelStyle.fontSize.has_value()) {
504 if (isSubTabStyle) {
505 labelStyle.fontSize = tabTheme->GetSubTabTextDefaultFontSize();
506 } else if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
507 labelStyle.fontSize = tabTheme->GetBottomTabTextSize();
508 }
509 }
510 if (!labelStyle.fontWeight.has_value() && !isSubTabStyle) {
511 labelStyle.fontWeight = FontWeight::MEDIUM;
512 }
513 if (!labelStyle.fontStyle.has_value()) {
514 labelStyle.fontStyle = FontStyle::NORMAL;
515 }
516 if (!labelStyle.heightAdaptivePolicy.has_value()) {
517 labelStyle.heightAdaptivePolicy = TextHeightAdaptivePolicy::MAX_LINES_FIRST;
518 }
519 if (!labelStyle.textOverflow.has_value()) {
520 labelStyle.textOverflow = TextOverflow::ELLIPSIS;
521 }
522 }
523
SetBuilderNode(const JSRef<JSObject> & paramObject)524 void SetBuilderNode(const JSRef<JSObject>& paramObject)
525 {
526 JSRef<JSVal> contentParam = paramObject->GetProperty("content");
527 if (!contentParam->IsObject()) {
528 return;
529 }
530 auto contentObject = JSRef<JSObject>::Cast(contentParam);
531 JSRef<JSVal> builderNodeParam = contentObject->GetProperty("builderNode_");
532 if (!builderNodeParam->IsObject()) {
533 return;
534 }
535 auto builderNodeObject = JSRef<JSObject>::Cast(builderNodeParam);
536 JSRef<JSVal> nodeptr = builderNodeObject->GetProperty("nodePtr_");
537 if (nodeptr.IsEmpty()) {
538 return;
539 }
540 const auto* vm = nodeptr->GetEcmaVM();
541 auto* node = nodeptr->GetLocalHandle()->ToNativePointer(vm)->Value();
542 auto* frameNode = reinterpret_cast<NG::FrameNode*>(node);
543 CHECK_NULL_VOID(frameNode);
544 RefPtr<NG::FrameNode> refPtrFrameNode = AceType::Claim(frameNode);
545 TabContentModel::GetInstance()->SetCustomStyleNode(refPtrFrameNode);
546 }
547
SetSubTabBarStyle(const JSRef<JSObject> & paramObject)548 void JSTabContent::SetSubTabBarStyle(const JSRef<JSObject>& paramObject)
549 {
550 JSRef<JSVal> contentParam = paramObject->GetProperty("content");
551 SetBuilderNode(paramObject);
552
553 auto isContentEmpty = contentParam->IsEmpty() || contentParam->IsUndefined() || contentParam->IsNull();
554 if (isContentEmpty) {
555 LOGW("The content param is empty");
556 }
557 std::optional<std::string> contentOpt;
558 std::string content;
559 if (ParseJsString(contentParam, content)) {
560 contentOpt = content;
561 }
562
563 JSRef<JSVal> indicatorParam = paramObject->GetProperty("indicator");
564 SetIndicator(indicatorParam);
565
566 JSRef<JSVal> selectedModeParam = paramObject->GetProperty("selectedMode");
567 SetSelectedMode(selectedModeParam);
568
569 JSRef<JSVal> boardParam = paramObject->GetProperty("board");
570 SetBoard(boardParam);
571
572 JSRef<JSVal> labelStyleParam = paramObject->GetProperty("labelStyle");
573 SetLabelStyle(labelStyleParam, true);
574
575 JSRef<JSVal> paddingParam = paramObject->GetProperty("padding");
576 SetPadding(paddingParam, true);
577
578 JSRef<JSVal> idParam = paramObject->GetProperty("id");
579 SetId(idParam);
580
581 TabContentModel::GetInstance()->SetTabBarStyle(TabBarStyle::SUBTABBATSTYLE);
582 TabContentModel::GetInstance()->SetTabBar(contentOpt, std::nullopt, std::nullopt, nullptr, false);
583 }
584
SetLayoutMode(const JSRef<JSVal> & info)585 void JSTabContent::SetLayoutMode(const JSRef<JSVal>& info)
586 {
587 int32_t layoutMode;
588 if (!ConvertFromJSValue(info, layoutMode)) {
589 TabContentModel::GetInstance()->SetLayoutMode(LayoutMode::VERTICAL);
590 } else {
591 TabContentModel::GetInstance()->SetLayoutMode(static_cast<LayoutMode>(layoutMode));
592 }
593 }
594
SetVerticalAlign(const JSRef<JSVal> & info)595 void JSTabContent::SetVerticalAlign(const JSRef<JSVal>& info)
596 {
597 auto align = FlexAlign::CENTER;
598 if (info->IsNumber()) {
599 auto value = info->ToNumber<int32_t>();
600 if (value >= static_cast<int32_t>(FlexAlign::FLEX_START) &&
601 value <= static_cast<int32_t>(FlexAlign::FLEX_END)) {
602 align = static_cast<FlexAlign>(value);
603 }
604 }
605 TabContentModel::GetInstance()->SetVerticalAlign(align);
606 }
607
SetSymmetricExtensible(const JSRef<JSVal> & info)608 void JSTabContent::SetSymmetricExtensible(const JSRef<JSVal>& info)
609 {
610 bool isExtensible = false;
611 ParseJsBool(info, isExtensible);
612 TabContentModel::GetInstance()->SetSymmetricExtensible(isExtensible);
613 }
614
SetBottomTabBarStyle(const JSCallbackInfo & info)615 void JSTabContent::SetBottomTabBarStyle(const JSCallbackInfo& info)
616 {
617 auto paramObject = JSRef<JSObject>::Cast(info[0]);
618 JSRef<JSVal> textParam = paramObject->GetProperty("text");
619 std::optional<std::string> textOpt = std::nullopt;
620 std::string text;
621 if (ParseJsString(textParam, text)) {
622 textOpt = text;
623 }
624
625 JSRef<JSVal> iconParam = paramObject->GetProperty("icon");
626 std::optional<std::string> iconOpt = std::nullopt;
627 std::string icon;
628 std::optional<TabBarSymbol> tabBarSymbol = std::nullopt;
629 if (ParseJsMedia(iconParam, icon)) {
630 iconOpt = icon;
631 } else if (iconParam->IsObject()) {
632 JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(iconParam);
633 JSRef<JSVal> normalModifier = jsObj->GetProperty("normal");
634 JSRef<JSVal> selectedModifier = jsObj->GetProperty("selected");
635 if (normalModifier->IsObject()) {
636 TabBarSymbol symbolApply;
637 JSViewAbstract::SetTabBarSymbolOptionApply(info, symbolApply, normalModifier, selectedModifier);
638 if (selectedModifier->IsObject()) {
639 symbolApply.selectedFlag = true;
640 }
641 tabBarSymbol = symbolApply;
642 }
643 }
644
645 JSRef<JSVal> paddingParam = paramObject->GetProperty("padding");
646 SetPadding(paddingParam, false);
647
648 JSRef<JSVal> layoutParam = paramObject->GetProperty("layoutMode");
649 SetLayoutMode(layoutParam);
650
651 JSRef<JSVal> verticalAlignParam = paramObject->GetProperty("verticalAlign");
652 SetVerticalAlign(verticalAlignParam);
653
654 JSRef<JSVal> extensibleParam = paramObject->GetProperty("symmetricExtensible");
655 SetSymmetricExtensible(extensibleParam);
656
657 JSRef<JSVal> labelStyleParam = paramObject->GetProperty("labelStyle");
658 SetLabelStyle(labelStyleParam, false);
659
660 SetIconStyle(paramObject->GetProperty("iconStyle"));
661
662 JSRef<JSVal> idParam = paramObject->GetProperty("id");
663 SetId(idParam);
664
665 TabContentModel::GetInstance()->SetTabBarStyle(TabBarStyle::BOTTOMTABBATSTYLE);
666 TabContentModel::GetInstance()->SetTabBar(textOpt, iconOpt, tabBarSymbol, nullptr, false);
667 }
668
SetOnWillShow(const JSCallbackInfo & info)669 void JSTabContent::SetOnWillShow(const JSCallbackInfo& info)
670 {
671 if (info.Length() < 1 || !info[0]->IsFunction()) {
672 return;
673 }
674 auto willShowHandler = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
675 WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
676 auto onWillShow = [executionContext = info.GetExecutionContext(), func = std::move(willShowHandler)]() {
677 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
678 ACE_SCORING_EVENT("TabContent.onWillShow");
679 func->Execute();
680 };
681 TabContentModel::GetInstance()->SetOnWillShow(std::move(onWillShow));
682 }
683
SetOnWillHide(const JSCallbackInfo & info)684 void JSTabContent::SetOnWillHide(const JSCallbackInfo& info)
685 {
686 if (info.Length() < 1 || !info[0]->IsFunction()) {
687 return;
688 }
689 auto willHideHandler = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
690 WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
691 auto onWillHide = [executionContext = info.GetExecutionContext(), func = std::move(willHideHandler)]() {
692 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
693 ACE_SCORING_EVENT("TabContent.onWillHide");
694 func->Execute();
695 };
696 TabContentModel::GetInstance()->SetOnWillHide(std::move(onWillHide));
697 }
698
JSBind(BindingTarget globalObj)699 void JSTabContent::JSBind(BindingTarget globalObj)
700 {
701 JSClass<JSTabContent>::Declare("TabContent");
702 JSClass<JSTabContent>::StaticMethod("create", &JSTabContent::Create);
703 JSClass<JSTabContent>::StaticMethod("pop", &JSTabContent::Pop);
704 JSClass<JSTabContent>::StaticMethod("tabBar", &JSTabContent::SetTabBar);
705 JSClass<JSTabContent>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
706 JSClass<JSTabContent>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
707 JSClass<JSTabContent>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
708 JSClass<JSTabContent>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
709 JSClass<JSTabContent>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
710 JSClass<JSTabContent>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
711 JSClass<JSTabContent>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
712 JSClass<JSTabContent>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
713 JSClass<JSTabContent>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
714 JSClass<JSTabContent>::StaticMethod("width", &JSTabContent::SetTabContentWidth);
715 JSClass<JSTabContent>::StaticMethod("height", &JSTabContent::SetTabContentHeight);
716 JSClass<JSTabContent>::StaticMethod("size", &JSTabContent::SetTabContentSize);
717 JSClass<JSTabContent>::StaticMethod("onWillShow", &JSTabContent::SetOnWillShow);
718 JSClass<JSTabContent>::StaticMethod("onWillHide", &JSTabContent::SetOnWillHide);
719 JSClass<JSTabContent>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
720 JSClass<JSTabContent>::InheritAndBind<JSContainerBase>(globalObj);
721 }
722
723 } // namespace OHOS::Ace::Framework
724