• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_trace.h"
21 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
22 #include "bridge/declarative_frontend/jsview/models/tab_content_model_impl.h"
23 #include "core/components/tab_bar/tab_theme.h"
24 #include "core/components_ng/pattern/tabs/tab_content_model_ng.h"
25 #include "core/components_ng/property/measure_property.h"
26 
27 namespace OHOS::Ace {
28 
29 std::unique_ptr<TabContentModel> TabContentModel::instance_ = nullptr;
30 std::mutex TabContentModel::mutex_;
31 
32 const std::vector<TextOverflow> TEXT_OVERFLOWS = { TextOverflow::NONE, TextOverflow::CLIP, TextOverflow::ELLIPSIS,
33     TextOverflow::MARQUEE };
34 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
35 const std::vector<TextHeightAdaptivePolicy> HEIGHT_ADAPTIVE_POLICIES = { TextHeightAdaptivePolicy::MAX_LINES_FIRST,
36     TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST, TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST };
37 
GetInstance()38 TabContentModel* TabContentModel::GetInstance()
39 {
40     if (!instance_) {
41         std::lock_guard<std::mutex> lock(mutex_);
42         if (!instance_) {
43 #ifdef NG_BUILD
44             instance_.reset(new NG::TabContentModelNG());
45 #else
46             if (Container::IsCurrentUseNewPipeline()) {
47                 instance_.reset(new NG::TabContentModelNG());
48             } else {
49                 instance_.reset(new Framework::TabContentModelImpl());
50             }
51 #endif
52         }
53     }
54     return instance_.get();
55 }
56 
57 } // namespace OHOS::Ace
58 
59 namespace OHOS::Ace::Framework {
60 
Create(const JSCallbackInfo & info)61 void JSTabContent::Create(const JSCallbackInfo& info)
62 {
63     if (Container::IsCurrentUsePartialUpdate()) {
64         CreateForPartialUpdate(info);
65         return;
66     }
67     TabContentModel::GetInstance()->Create();
68 }
69 
CreateForPartialUpdate(const JSCallbackInfo & info)70 void JSTabContent::CreateForPartialUpdate(const JSCallbackInfo& info)
71 {
72     if (info.Length() <= 0 && !info[0]->IsFunction()) {
73         TabContentModel::GetInstance()->Create();
74         return;
75     }
76 
77     JSRef<JSVal> builderFunctionJS = info[0];
78     auto builderFunc = [context = info.GetExecutionContext(), builder = std::move(builderFunctionJS)]() {
79         JAVASCRIPT_EXECUTION_SCOPE(context)
80         JSRef<JSFunc>::Cast(builder)->Call(JSRef<JSObject>());
81     };
82     TabContentModel::GetInstance()->Create(std::move(builderFunc));
83 }
84 
SetTabBar(const JSCallbackInfo & info)85 void JSTabContent::SetTabBar(const JSCallbackInfo& info)
86 {
87     if (info.Length() <= 0) {
88         return;
89     }
90 
91     std::string infoStr;
92     if (ParseJsString(info[0], infoStr)) {
93         TabContentModel::GetInstance()->SetTabBarStyle(TabBarStyle::NOSTYLE);
94         TabContentModel::GetInstance()->SetTabBar(infoStr, std::nullopt, nullptr, true);
95         return;
96     }
97 
98     if (!info[0]->IsObject()) {
99         return;
100     }
101 
102     auto paramObject = JSRef<JSObject>::Cast(info[0]);
103     JSRef<JSVal> builderFuncParam = paramObject->GetProperty("builder");
104     if (builderFuncParam->IsFunction()) {
105         auto tabBarBuilder = AceType::MakeRefPtr<JsFunction>(info.This(), JSRef<JSFunc>::Cast(builderFuncParam));
106         auto tabBarBuilderFunc = [execCtx = info.GetExecutionContext(),
107                                      tabBarBuilderFunc = std::move(tabBarBuilder)]() {
108             if (tabBarBuilderFunc) {
109                 ACE_SCOPED_TRACE("JSTabContent::Execute TabBar builder");
110                 JAVASCRIPT_EXECUTION_SCOPE(execCtx);
111                 tabBarBuilderFunc->ExecuteJS();
112             }
113         };
114         TabContentModel::GetInstance()->SetTabBarStyle(TabBarStyle::NOSTYLE);
115         TabContentModel::GetInstance()->SetTabBar(std::nullopt, std::nullopt, std::move(tabBarBuilderFunc), false);
116         return;
117     }
118     JSRef<JSVal> typeParam = paramObject->GetProperty("type");
119     if (typeParam->IsString()) {
120         auto type = typeParam->ToString();
121         if (type == "SubTabBarStyle") {
122             SetSubTabBarStyle(paramObject);
123             return;
124         }
125         if (type == "BottomTabBarStyle") {
126             SetBottomTabBarStyle(paramObject);
127             return;
128         }
129     }
130 
131     JSRef<JSVal> textParam = paramObject->GetProperty("text");
132     auto isTextEmpty = textParam->IsEmpty() || textParam->IsUndefined() || textParam->IsNull();
133     std::optional<std::string> textOpt = std::nullopt;
134     if (!isTextEmpty) {
135         std::string text;
136         if (ParseJsString(textParam, text)) {
137             textOpt = text;
138         }
139     }
140 
141     JSRef<JSVal> iconParam = paramObject->GetProperty("icon");
142     auto isIconEmpty = iconParam->IsEmpty() || iconParam->IsUndefined() || iconParam->IsNull();
143     std::optional<std::string> iconOpt = std::nullopt;
144     if (!isIconEmpty) {
145         std::string icon;
146         if (ParseJsMedia(iconParam, icon)) {
147             iconOpt = icon;
148         }
149     }
150     TabContentModel::GetInstance()->SetTabBarStyle(TabBarStyle::NOSTYLE);
151     TabContentModel::GetInstance()->SetTabBar(textOpt, iconOpt, nullptr, false);
152 }
153 
Pop()154 void JSTabContent::Pop()
155 {
156     TabContentModel::GetInstance()->Pop();
157 }
158 
SetIndicator(const JSRef<JSVal> & info)159 void JSTabContent::SetIndicator(const JSRef<JSVal>& info)
160 {
161     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info);
162     IndicatorStyle indicator;
163     CalcDimension indicatorHeight;
164     CalcDimension indicatorWidth;
165     CalcDimension indicatorBorderRadius;
166     CalcDimension indicatorMarginTop;
167     if (!info->IsObject() || !ConvertFromJSValue(obj->GetProperty("color"), indicator.color)) {
168         RefPtr<TabTheme> tabTheme = GetTheme<TabTheme>();
169         if (tabTheme) {
170             indicator.color = tabTheme->GetActiveIndicatorColor();
171         }
172     }
173     if (!info->IsObject() || !ParseJsDimensionVp(obj->GetProperty("height"), indicatorHeight) ||
174         indicatorHeight.Value() < 0.0f || indicatorHeight.Unit() == DimensionUnit::PERCENT) {
175         RefPtr<TabTheme> tabTheme = GetTheme<TabTheme>();
176         if (tabTheme) {
177             indicator.height = tabTheme->GetActiveIndicatorWidth();
178         }
179     } else {
180         indicator.height = indicatorHeight;
181     }
182     if (!info->IsObject() || !ParseJsDimensionVp(obj->GetProperty("width"), indicatorWidth) ||
183         indicatorWidth.Value() < 0.0f || indicatorWidth.Unit() == DimensionUnit::PERCENT) {
184         indicator.width = 0.0_vp;
185     } else {
186         indicator.width = indicatorWidth;
187     }
188     if (!info->IsObject() || !ParseJsDimensionVp(obj->GetProperty("borderRadius"), indicatorBorderRadius) ||
189         indicatorBorderRadius.Value() < 0.0f || indicatorBorderRadius.Unit() == DimensionUnit::PERCENT) {
190         indicator.borderRadius = 0.0_vp;
191     } else {
192         indicator.borderRadius = indicatorBorderRadius;
193     }
194     if (!info->IsObject() || !ParseJsDimensionVp(obj->GetProperty("marginTop"), indicatorMarginTop) ||
195         indicatorMarginTop.Value() < 0.0f || indicatorMarginTop.Unit() == DimensionUnit::PERCENT) {
196         RefPtr<TabTheme> tabTheme = GetTheme<TabTheme>();
197         if (tabTheme) {
198             indicator.marginTop = tabTheme->GetSubTabIndicatorGap();
199         }
200     } else {
201         indicator.marginTop = indicatorMarginTop;
202     }
203     TabContentModel::GetInstance()->SetIndicator(indicator);
204 }
205 
SetBoard(const JSRef<JSVal> & info)206 void JSTabContent::SetBoard(const JSRef<JSVal>& info)
207 {
208     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info);
209     BoardStyle board;
210     CalcDimension borderRadius;
211     if (!info->IsObject() || !ParseJsDimensionVp(obj->GetProperty("borderRadius"), borderRadius) ||
212         borderRadius.Value() < 0.0f || borderRadius.Unit() == DimensionUnit::PERCENT) {
213         RefPtr<TabTheme> tabTheme = GetTheme<TabTheme>();
214         if (tabTheme) {
215             board.borderRadius = tabTheme->GetFocusIndicatorRadius();
216         }
217     } else {
218         board.borderRadius = borderRadius;
219     }
220     TabContentModel::GetInstance()->SetBoard(board);
221 }
222 
SetSelectedMode(const JSRef<JSVal> & info)223 void JSTabContent::SetSelectedMode(const JSRef<JSVal>& info)
224 {
225     int32_t selectedMode;
226     if (!ConvertFromJSValue(info, selectedMode)) {
227         TabContentModel::GetInstance()->SetSelectedMode(SelectedMode::INDICATOR);
228     } else {
229         TabContentModel::GetInstance()->SetSelectedMode(static_cast<SelectedMode>(selectedMode));
230     }
231 }
232 
GetFontContent(const JSRef<JSVal> font,LabelStyle & labelStyle)233 void JSTabContent::GetFontContent(const JSRef<JSVal> font, LabelStyle& labelStyle)
234 {
235     JSRef<JSObject> obj = JSRef<JSObject>::Cast(font);
236     JSRef<JSVal> size = obj->GetProperty("size");
237     CalcDimension fontSize;
238     if (ParseJsDimensionFp(size, fontSize) && NonNegative(fontSize.Value()) &&
239         fontSize.Unit() != DimensionUnit::PERCENT) {
240         labelStyle.fontSize = fontSize;
241     }
242 
243     JSRef<JSVal> weight = obj->GetProperty("weight");
244     if (weight->IsString() || weight->IsNumber()) {
245         labelStyle.fontWeight = ConvertStrToFontWeight(weight->ToString());
246     }
247 
248     JSRef<JSVal> family = obj->GetProperty("family");
249     std::vector<std::string> fontFamilies;
250     if (ParseJsFontFamilies(family, fontFamilies)) {
251         labelStyle.fontFamily = fontFamilies;
252     }
253 
254     JSRef<JSVal> style = obj->GetProperty("style");
255     if (style->IsNumber()) {
256         int32_t value = style->ToNumber<int32_t>();
257         if (value >= 0 && value < static_cast<int32_t>(FONT_STYLES.size())) {
258             labelStyle.fontStyle = FONT_STYLES[value];
259         }
260     }
261 }
262 
SetLabelStyle(const JSRef<JSVal> & info,bool isSubTabStyle)263 void JSTabContent::SetLabelStyle(const JSRef<JSVal>& info, bool isSubTabStyle)
264 {
265     LabelStyle labelStyle;
266     if (!info->IsObject()) {
267         LOGW("info not is Object");
268     } else {
269         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info);
270         JSRef<JSVal> overflowValue = obj->GetProperty("overflow");
271         if (!overflowValue->IsNull() && overflowValue->IsNumber()) {
272             auto overflow = overflowValue->ToNumber<int32_t>();
273             if (overflow >= 0 && overflow < static_cast<int32_t>(TEXT_OVERFLOWS.size())) {
274                 labelStyle.textOverflow = TEXT_OVERFLOWS[overflow];
275             }
276         }
277 
278         JSRef<JSVal> maxLines = obj->GetProperty("maxLines");
279         if (!maxLines->IsNull() && maxLines->IsNumber() && maxLines->ToNumber<int32_t>() > 0) {
280             labelStyle.maxLines = maxLines->ToNumber<int32_t>();
281         }
282 
283         JSRef<JSVal> minFontSizeValue = obj->GetProperty("minFontSize");
284         CalcDimension minFontSize;
285         if (ParseJsDimensionFp(minFontSizeValue, minFontSize) && NonNegative(minFontSize.Value()) &&
286             minFontSize.Unit() != DimensionUnit::PERCENT) {
287             labelStyle.minFontSize = minFontSize;
288         }
289 
290         JSRef<JSVal> maxFontSizeValue = obj->GetProperty("maxFontSize");
291         CalcDimension maxFontSize;
292         if (ParseJsDimensionFp(maxFontSizeValue, maxFontSize) && NonNegative(maxFontSize.Value()) &&
293             maxFontSize.Unit() != DimensionUnit::PERCENT) {
294             labelStyle.maxFontSize = maxFontSize;
295         }
296 
297         JSRef<JSVal> heightAdaptivePolicyValue = obj->GetProperty("heightAdaptivePolicy");
298         if (!heightAdaptivePolicyValue->IsNull() && heightAdaptivePolicyValue->IsNumber()) {
299             auto heightAdaptivePolicy = heightAdaptivePolicyValue->ToNumber<int32_t>();
300             if (heightAdaptivePolicy >= 0 &&
301                 heightAdaptivePolicy < static_cast<int32_t>(HEIGHT_ADAPTIVE_POLICIES.size())) {
302                 labelStyle.heightAdaptivePolicy = HEIGHT_ADAPTIVE_POLICIES[heightAdaptivePolicy];
303             }
304         }
305 
306         JSRef<JSVal> font = obj->GetProperty("font");
307         if (!font->IsNull() && font->IsObject()) {
308             GetFontContent(font, labelStyle);
309         }
310     }
311     CompleteParameters(labelStyle, isSubTabStyle);
312     TabContentModel::GetInstance()->SetLabelStyle(labelStyle);
313 }
314 
SetPadding(const JSRef<JSVal> & info,bool isSubTabStyle)315 void JSTabContent::SetPadding(const JSRef<JSVal>& info, bool isSubTabStyle)
316 {
317     CalcDimension length;
318     NG::PaddingProperty padding;
319     if (ParseJsDimensionVp(info, length) && NonNegative(length.Value()) && length.Unit() != DimensionUnit::PERCENT) {
320         padding.left = NG::CalcLength(length);
321         padding.right = NG::CalcLength(length);
322         padding.top = NG::CalcLength(length);
323         padding.bottom = NG::CalcLength(length);
324         TabContentModel::GetInstance()->SetPadding(padding);
325         return;
326     }
327 
328     RefPtr<TabTheme> tabTheme = GetTheme<TabTheme>();
329     if (tabTheme) {
330         if (isSubTabStyle) {
331             padding.top = NG::CalcLength(tabTheme->GetSubTabTopPadding());
332             padding.bottom = NG::CalcLength(tabTheme->GetSubTabBottomPadding());
333             padding.left = NG::CalcLength(tabTheme->GetSubTabHorizontalPadding());
334             padding.right = NG::CalcLength(tabTheme->GetSubTabHorizontalPadding());
335         } else {
336             padding.top = NG::CalcLength(0.0_vp);
337             padding.bottom = NG::CalcLength(0.0_vp);
338             padding.left = NG::CalcLength(tabTheme->GetBottomTabHorizontalPadding());
339             padding.right = NG::CalcLength(tabTheme->GetBottomTabHorizontalPadding());
340         }
341     }
342     if (info->IsObject()) {
343         JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(info);
344         CalcDimension left;
345         if (ParseJsDimensionVp(paddingObj->GetProperty("left"), left) && NonNegative(left.Value()) &&
346             left.Unit() != DimensionUnit::PERCENT) {
347             padding.left = NG::CalcLength(left);
348         }
349         CalcDimension right;
350         if (ParseJsDimensionVp(paddingObj->GetProperty("right"), right) && NonNegative(right.Value()) &&
351             right.Unit() != DimensionUnit::PERCENT) {
352             padding.right = NG::CalcLength(right);
353         }
354         CalcDimension top;
355         if (ParseJsDimensionVp(paddingObj->GetProperty("top"), top) && NonNegative(top.Value()) &&
356             top.Unit() != DimensionUnit::PERCENT) {
357             padding.top = NG::CalcLength(top);
358         }
359         CalcDimension bottom;
360         if (ParseJsDimensionVp(paddingObj->GetProperty("bottom"), bottom) && NonNegative(bottom.Value()) &&
361             bottom.Unit() != DimensionUnit::PERCENT) {
362             padding.bottom = NG::CalcLength(bottom);
363         }
364     }
365     TabContentModel::GetInstance()->SetPadding(padding);
366 }
367 
CompleteParameters(LabelStyle & labelStyle,bool isSubTabStyle)368 void JSTabContent::CompleteParameters(LabelStyle& labelStyle, bool isSubTabStyle)
369 {
370     auto tabTheme = GetTheme<TabTheme>();
371     if (!tabTheme) {
372         return;
373     }
374     if (!labelStyle.maxLines.has_value()) {
375         labelStyle.maxLines = 1;
376     }
377     if (!labelStyle.minFontSize.has_value()) {
378         labelStyle.minFontSize = 0.0_vp;
379     }
380     if (!labelStyle.maxFontSize.has_value()) {
381         labelStyle.maxFontSize = 0.0_vp;
382     }
383     if (!labelStyle.fontSize.has_value()) {
384         if (isSubTabStyle) {
385             labelStyle.fontSize = tabTheme->GetSubTabTextDefaultFontSize();
386         } else {
387             labelStyle.fontSize = tabTheme->GetBottomTabTextSize();
388         }
389     }
390     if (!labelStyle.fontWeight.has_value()) {
391         if (isSubTabStyle) {
392             labelStyle.fontWeight = FontWeight::NORMAL;
393         } else {
394             labelStyle.fontWeight = FontWeight::MEDIUM;
395         }
396     }
397     if (!labelStyle.fontStyle.has_value()) {
398         labelStyle.fontStyle = FontStyle::NORMAL;
399     }
400     if (!labelStyle.fontFamily.has_value()) {
401         labelStyle.fontFamily = { "HarmonyOS Sans" };
402     }
403     if (!labelStyle.heightAdaptivePolicy.has_value()) {
404         labelStyle.heightAdaptivePolicy = TextHeightAdaptivePolicy::MAX_LINES_FIRST;
405     }
406     if (!labelStyle.textOverflow.has_value()) {
407         labelStyle.textOverflow = TextOverflow::ELLIPSIS;
408     }
409 }
410 
SetSubTabBarStyle(const JSRef<JSObject> & paramObject)411 void JSTabContent::SetSubTabBarStyle(const JSRef<JSObject>& paramObject)
412 {
413     JSRef<JSVal> contentParam = paramObject->GetProperty("content");
414     auto isContentEmpty = contentParam->IsEmpty() || contentParam->IsUndefined() || contentParam->IsNull();
415     if (isContentEmpty) {
416         LOGW("The content param is empty");
417     }
418     std::optional<std::string> contentOpt;
419     std::string content;
420     if (ParseJsString(contentParam, content)) {
421         contentOpt = content;
422     }
423 
424     JSRef<JSVal> indicatorParam = paramObject->GetProperty("indicator");
425     SetIndicator(indicatorParam);
426 
427     JSRef<JSVal> selectedModeParam = paramObject->GetProperty("selectedMode");
428     SetSelectedMode(selectedModeParam);
429 
430     JSRef<JSVal> boardParam = paramObject->GetProperty("board");
431     SetBoard(boardParam);
432 
433     JSRef<JSVal> labelStyleParam = paramObject->GetProperty("labelStyle");
434     SetLabelStyle(labelStyleParam, true);
435 
436     JSRef<JSVal> paddingParam = paramObject->GetProperty("padding");
437     SetPadding(paddingParam, true);
438 
439     TabContentModel::GetInstance()->SetTabBarStyle(TabBarStyle::SUBTABBATSTYLE);
440     TabContentModel::GetInstance()->SetTabBar(contentOpt, std::nullopt, nullptr, false);
441 }
442 
SetLayoutMode(const JSRef<JSVal> & info)443 void JSTabContent::SetLayoutMode(const JSRef<JSVal>& info)
444 {
445     int32_t layoutMode;
446     if (!ConvertFromJSValue(info, layoutMode)) {
447         TabContentModel::GetInstance()->SetLayoutMode(LayoutMode::VERTICAL);
448     } else {
449         TabContentModel::GetInstance()->SetLayoutMode(static_cast<LayoutMode>(layoutMode));
450     }
451 }
452 
SetVerticalAlign(const JSRef<JSVal> & info)453 void JSTabContent::SetVerticalAlign(const JSRef<JSVal>& info)
454 {
455     auto align = FlexAlign::CENTER;
456     if (info->IsNumber()) {
457         auto value = info->ToNumber<int32_t>();
458         if (value >= static_cast<int32_t>(FlexAlign::FLEX_START) &&
459             value <= static_cast<int32_t>(FlexAlign::FLEX_END)) {
460             align = static_cast<FlexAlign>(value);
461         }
462     }
463     TabContentModel::GetInstance()->SetVerticalAlign(align);
464 }
465 
SetSymmetricExtensible(const JSRef<JSVal> & info)466 void JSTabContent::SetSymmetricExtensible(const JSRef<JSVal>& info)
467 {
468     bool isExtensible = false;
469     ParseJsBool(info, isExtensible);
470     TabContentModel::GetInstance()->SetSymmetricExtensible(isExtensible);
471 }
472 
SetBottomTabBarStyle(const JSRef<JSObject> & paramObject)473 void JSTabContent::SetBottomTabBarStyle(const JSRef<JSObject>& paramObject)
474 {
475     JSRef<JSVal> textParam = paramObject->GetProperty("text");
476     std::optional<std::string> textOpt = std::nullopt;
477     std::string text;
478     if (ParseJsString(textParam, text)) {
479         textOpt = text;
480     }
481 
482     JSRef<JSVal> iconParam = paramObject->GetProperty("icon");
483     std::optional<std::string> iconOpt = std::nullopt;
484     std::string icon;
485     if (ParseJsMedia(iconParam, icon)) {
486         iconOpt = icon;
487     }
488 
489     JSRef<JSVal> paddingParam = paramObject->GetProperty("padding");
490     SetPadding(paddingParam, false);
491 
492     JSRef<JSVal> layoutParam = paramObject->GetProperty("layoutMode");
493     SetLayoutMode(layoutParam);
494 
495     JSRef<JSVal> verticalAlignParam = paramObject->GetProperty("verticalAlign");
496     SetVerticalAlign(verticalAlignParam);
497 
498     JSRef<JSVal> extensibleParam = paramObject->GetProperty("symmetricExtensible");
499     SetSymmetricExtensible(extensibleParam);
500 
501     JSRef<JSVal> labelStyleParam = paramObject->GetProperty("labelStyle");
502     SetLabelStyle(labelStyleParam, false);
503 
504     TabContentModel::GetInstance()->SetTabBarStyle(TabBarStyle::BOTTOMTABBATSTYLE);
505     TabContentModel::GetInstance()->SetTabBar(textOpt, iconOpt, nullptr, false);
506 }
507 
JSBind(BindingTarget globalObj)508 void JSTabContent::JSBind(BindingTarget globalObj)
509 {
510     JSClass<JSTabContent>::Declare("TabContent");
511     JSClass<JSTabContent>::StaticMethod("create", &JSTabContent::Create);
512     JSClass<JSTabContent>::StaticMethod("pop", &JSTabContent::Pop);
513     JSClass<JSTabContent>::StaticMethod("tabBar", &JSTabContent::SetTabBar);
514     JSClass<JSTabContent>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
515     JSClass<JSTabContent>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
516     JSClass<JSTabContent>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
517     JSClass<JSTabContent>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
518     JSClass<JSTabContent>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
519     JSClass<JSTabContent>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
520     JSClass<JSTabContent>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
521     JSClass<JSTabContent>::StaticMethod("width", &JSTabContent::SetTabContentWidth);
522     JSClass<JSTabContent>::StaticMethod("height", &JSTabContent::SetTabContentHeight);
523     JSClass<JSTabContent>::StaticMethod("size", &JSTabContent::SetTabContentSize);
524     JSClass<JSTabContent>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
525     JSClass<JSTabContent>::InheritAndBind<JSContainerBase>(globalObj);
526 }
527 
528 } // namespace OHOS::Ace::Framework
529