1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "frameworks/bridge/declarative_frontend/jsview/js_tabs.h"
17
18 #include "base/log/ace_scoring_log.h"
19 #include "bridge/declarative_frontend/jsview/js_tabs_controller.h"
20 #include "bridge/declarative_frontend/jsview/models/tabs_model_impl.h"
21 #include "core/components_ng/pattern/tabs/tabs_model_ng.h"
22
23 namespace OHOS::Ace {
24
25 std::unique_ptr<TabsModel> TabsModel::instance_ = nullptr;
26
GetInstance()27 TabsModel* TabsModel::GetInstance()
28 {
29 if (!instance_) {
30 #ifdef NG_BUILD
31 instance_.reset(new NG::TabsModelNG());
32 #else
33 if (Container::IsCurrentUseNewPipeline()) {
34 instance_.reset(new NG::TabsModelNG());
35 } else {
36 instance_.reset(new Framework::TabsModelImpl());
37 }
38 #endif
39 }
40 return instance_.get();
41 }
42
43 } // namespace OHOS::Ace
44
45 namespace OHOS::Ace::Framework {
46 namespace {
47
48 const std::vector<BarPosition> BAR_POSITIONS = { BarPosition::START, BarPosition::END };
49
TabContentChangeEventToJSValue(const TabContentChangeEvent & eventInfo)50 JSRef<JSVal> TabContentChangeEventToJSValue(const TabContentChangeEvent& eventInfo)
51 {
52 return JSRef<JSVal>::Make(ToJSValue(eventInfo.GetIndex()));
53 }
54
55 } // namespace
56
SetOnChange(const JSCallbackInfo & info)57 void JSTabs::SetOnChange(const JSCallbackInfo& info)
58 {
59 if (!info[0]->IsFunction()) {
60 return;
61 }
62
63 auto changeHandler = AceType::MakeRefPtr<JsEventFunction<TabContentChangeEvent, 1>>(
64 JSRef<JSFunc>::Cast(info[0]), TabContentChangeEventToJSValue);
65 auto onChange = [executionContext = info.GetExecutionContext(), func = std::move(changeHandler)](
66 const BaseEventInfo* info) {
67 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
68 const auto* tabsInfo = TypeInfoHelper::DynamicCast<TabContentChangeEvent>(info);
69 if (!tabsInfo) {
70 LOGE("HandleChangeEvent tabsInfo == nullptr");
71 return;
72 }
73 ACE_SCORING_EVENT("Tabs.onChange");
74 func->Execute(*tabsInfo);
75 };
76 TabsModel::GetInstance()->SetOnChange(std::move(onChange));
77 }
78
Create(const JSCallbackInfo & info)79 void JSTabs::Create(const JSCallbackInfo& info)
80 {
81 BarPosition barPosition = BarPosition::START;
82 RefPtr<TabController> tabController;
83 RefPtr<SwiperController> swiperController;
84 int32_t index = 0;
85 if (info[0]->IsObject()) {
86 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
87 JSRef<JSVal> val = obj->GetProperty("barPosition");
88 if (val->IsNumber()) {
89 auto barPositionVal = val->ToNumber<int32_t>();
90 if (barPositionVal >= 0 && barPositionVal < static_cast<int32_t>(BAR_POSITIONS.size())) {
91 barPosition = BAR_POSITIONS[barPositionVal];
92 }
93 }
94 JSRef<JSVal> controller = obj->GetProperty("controller");
95 if (controller->IsObject()) {
96 auto* jsTabsController = JSRef<JSObject>::Cast(controller)->Unwrap<JSTabsController>();
97 if (jsTabsController) {
98 tabController = jsTabsController->GetController();
99 swiperController = jsTabsController->GetSwiperController();
100 }
101 }
102 JSRef<JSVal> indexVal = obj->GetProperty("index");
103 if (indexVal->IsNumber()) {
104 index = indexVal->ToNumber<int32_t>();
105 if (!tabController) {
106 tabController = JSTabsController::CreateController();
107 }
108 tabController->SetInitialIndex(index);
109 }
110 }
111
112 TabsModel::GetInstance()->Create(barPosition, index, tabController, swiperController);
113 }
114
Pop()115 void JSTabs::Pop()
116 {
117 TabsModel::GetInstance()->Pop();
118 }
119
SetBarPosition(const JSCallbackInfo & info)120 void JSTabs::SetBarPosition(const JSCallbackInfo& info)
121 {
122 BarPosition barVal = BarPosition::START;
123 if (info.Length() > 0 && info[0]->IsNumber()) {
124 auto barPositionVal = info[0]->ToNumber<int32_t>();
125 if (barPositionVal >= 0 && barPositionVal < static_cast<int32_t>(BAR_POSITIONS.size())) {
126 barVal = BAR_POSITIONS[barPositionVal];
127 }
128 }
129
130 TabsModel::GetInstance()->SetTabBarPosition(barVal);
131 }
132
SetVertical(const std::string & value)133 void JSTabs::SetVertical(const std::string& value)
134 {
135 TabsModel::GetInstance()->SetIsVertical(StringToBool(value));
136 }
137
SetScrollable(const std::string & value)138 void JSTabs::SetScrollable(const std::string& value)
139 {
140 if (value == "undefined") {
141 TabsModel::GetInstance()->SetScrollable(true);
142 return;
143 }
144 TabsModel::GetInstance()->SetScrollable(StringToBool(value));
145 }
146
SetBarMode(const std::string & value)147 void JSTabs::SetBarMode(const std::string& value)
148 {
149 if (value == "undefined") {
150 TabsModel::GetInstance()->SetTabBarMode(TabBarMode::FIXED);
151 return;
152 }
153 TabsModel::GetInstance()->SetTabBarMode(ConvertStrToTabBarMode(value));
154 }
155
SetBarWidth(const JSCallbackInfo & info)156 void JSTabs::SetBarWidth(const JSCallbackInfo& info)
157 {
158 if (info.Length() < 1) {
159 LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
160 return;
161 }
162
163 Dimension width = Dimension(-1.0, DimensionUnit::VP);
164 if (!ParseJsDimensionVp(info[0], width)) {
165 LOGE("The arg is wrong, fail to parse dimension");
166 }
167
168 TabsModel::GetInstance()->SetTabBarWidth(width);
169 }
170
SetBarHeight(const JSCallbackInfo & info)171 void JSTabs::SetBarHeight(const JSCallbackInfo& info)
172 {
173 if (info.Length() < 1) {
174 LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
175 return;
176 }
177 Dimension height = Dimension(-1.0, DimensionUnit::VP);
178 if (!ParseJsDimensionVp(info[0], height)) {
179 LOGE("The arg is wrong, fail to parse dimension");
180 }
181
182 TabsModel::GetInstance()->SetTabBarHeight(height);
183 }
184
SetIndex(int32_t index)185 void JSTabs::SetIndex(int32_t index)
186 {
187 TabsModel::GetInstance()->SetIndex(index);
188 }
189
SetAnimationDuration(float value)190 void JSTabs::SetAnimationDuration(float value)
191 {
192 if (std::isnan(value)) {
193 LOGI("The arg is nan, use default value");
194 auto pipelineContext = PipelineContext::GetCurrentContext();
195 CHECK_NULL_VOID(pipelineContext);
196 auto tabTheme = pipelineContext->GetTheme<TabTheme>();
197 CHECK_NULL_VOID(tabTheme);
198 TabsModel::GetInstance()->SetAnimationDuration(static_cast<float>(tabTheme->GetTabContentAnimationDuration()));
199 return;
200 }
201 TabsModel::GetInstance()->SetAnimationDuration(value);
202 }
203
JSBind(BindingTarget globalObj)204 void JSTabs::JSBind(BindingTarget globalObj)
205 {
206 JSClass<JSTabs>::Declare("Tabs");
207 JSClass<JSTabs>::StaticMethod("create", &JSTabs::Create);
208 JSClass<JSTabs>::StaticMethod("pop", &JSTabs::Pop);
209 JSClass<JSTabs>::StaticMethod("vertical", &JSTabs::SetVertical);
210 JSClass<JSTabs>::StaticMethod("barPosition", &JSTabs::SetBarPosition);
211 JSClass<JSTabs>::StaticMethod("scrollable", &JSTabs::SetScrollable);
212 JSClass<JSTabs>::StaticMethod("barMode", &JSTabs::SetBarMode);
213 JSClass<JSTabs>::StaticMethod("barWidth", &JSTabs::SetBarWidth);
214 JSClass<JSTabs>::StaticMethod("barHeight", &JSTabs::SetBarHeight);
215 JSClass<JSTabs>::StaticMethod("index", &JSTabs::SetIndex);
216 JSClass<JSTabs>::StaticMethod("animationDuration", &JSTabs::SetAnimationDuration);
217 JSClass<JSTabs>::StaticMethod("onChange", &JSTabs::SetOnChange);
218 JSClass<JSTabs>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
219 JSClass<JSTabs>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
220 JSClass<JSTabs>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
221 JSClass<JSTabs>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
222 JSClass<JSTabs>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
223 JSClass<JSTabs>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
224 JSClass<JSTabs>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
225 JSClass<JSTabs>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
226 JSClass<JSTabs>::Inherit<JSContainerBase>();
227 JSClass<JSTabs>::Bind<>(globalObj);
228 }
229
230 } // namespace OHOS::Ace::Framework
231