1 /*
2 * Copyright (c) 2021 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_toggle.h"
17
18 #include <cstddef>
19 #include <string>
20
21 #include "base/log/ace_scoring_log.h"
22 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
23 #include "bridge/declarative_frontend/jsview/models/toggle_model_impl.h"
24 #include "core/common/container.h"
25 #include "core/components/common/properties/color.h"
26 #include "core/components_ng/pattern/button/toggle_button_model_ng.h"
27 #include "core/components_ng/pattern/toggle/toggle_model_ng.h"
28
29 namespace OHOS::Ace {
30
31 std::unique_ptr<ToggleModel> ToggleModel::instance_ = nullptr;
32
GetInstance()33 ToggleModel* ToggleModel::GetInstance()
34 {
35 if (!instance_) {
36 #ifdef NG_BUILD
37 instance_.reset(new NG::ToggleModelNG());
38 #else
39 if (Container::IsCurrentUseNewPipeline()) {
40 instance_.reset(new NG::ToggleModelNG());
41 } else {
42 instance_.reset(new Framework::ToggleModelImpl());
43 }
44 #endif
45 }
46 return instance_.get();
47 }
48
49 } // namespace OHOS::Ace
50
51 namespace OHOS::Ace::Framework {
52
JSBind(BindingTarget globalObj)53 void JSToggle::JSBind(BindingTarget globalObj)
54 {
55 JSClass<JSToggle>::Declare("Toggle");
56 JSClass<JSToggle>::StaticMethod("create", &JSToggle::Create);
57 JSClass<JSToggle>::StaticMethod("onChange", &JSToggle::OnChange);
58 JSClass<JSToggle>::StaticMethod("selectedColor", &JSToggle::SelectedColor);
59 JSClass<JSToggle>::StaticMethod("width", &JSToggle::JsWidth);
60 JSClass<JSToggle>::StaticMethod("height", &JSToggle::JsHeight);
61 JSClass<JSToggle>::StaticMethod("size", &JSToggle::JsSize);
62 JSClass<JSToggle>::StaticMethod("padding", &JSToggle::JsPadding);
63 JSClass<JSToggle>::StaticMethod("switchPointColor", &JSToggle::SwitchPointColor);
64 JSClass<JSToggle>::StaticMethod("backgroundColor", &JSToggle::SetBackgroundColor);
65
66 JSClass<JSToggle>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
67 JSClass<JSToggle>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
68 JSClass<JSToggle>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
69 JSClass<JSToggle>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
70 JSClass<JSToggle>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
71 JSClass<JSToggle>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
72 JSClass<JSToggle>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
73 JSClass<JSToggle>::Inherit<JSViewAbstract>();
74 JSClass<JSToggle>::Bind(globalObj);
75 }
76
Create(const JSCallbackInfo & info)77 void JSToggle::Create(const JSCallbackInfo& info)
78 {
79 if (info.Length() < 1 || !info[0]->IsObject()) {
80 LOGE("toggle create error, info is non-valid");
81 return;
82 }
83
84 auto paramObject = JSRef<JSObject>::Cast(info[0]);
85 auto type = paramObject->GetProperty("type");
86 if (!type->IsNumber()) {
87 LOGE("toggle create error, type is non-valid");
88 return;
89 }
90
91 auto tempIsOn = paramObject->GetProperty("isOn");
92 bool isOn = tempIsOn->IsBoolean() ? tempIsOn->ToBoolean() : false;
93 auto toggleType = static_cast<ToggleType>(type->ToNumber<int32_t>());
94
95 auto toggleTypeInt = static_cast<int32_t>(toggleType);
96
97 ToggleModel::GetInstance()->Create(NG::ToggleType(toggleTypeInt), isOn);
98 }
99
JsWidth(const JSCallbackInfo & info)100 void JSToggle::JsWidth(const JSCallbackInfo& info)
101 {
102 if (info.Length() < 1) {
103 LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
104 return;
105 }
106
107 JsWidth(info[0]);
108 }
109
JsWidth(const JSRef<JSVal> & jsValue)110 void JSToggle::JsWidth(const JSRef<JSVal>& jsValue)
111 {
112 Dimension value;
113 if (!ParseJsDimensionVp(jsValue, value)) {
114 return;
115 }
116
117 if (Container::IsCurrentUseNewPipeline()) {
118 JSViewAbstract::JsWidth(jsValue);
119 return;
120 }
121
122 ToggleModel::GetInstance()->SetWidth(value);
123 }
124
JsHeight(const JSCallbackInfo & info)125 void JSToggle::JsHeight(const JSCallbackInfo& info)
126 {
127 if (info.Length() < 1) {
128 LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
129 return;
130 }
131
132 JsHeight(info[0]);
133 }
134
JsHeight(const JSRef<JSVal> & jsValue)135 void JSToggle::JsHeight(const JSRef<JSVal>& jsValue)
136 {
137 Dimension value;
138 if (!ParseJsDimensionVp(jsValue, value)) {
139 return;
140 }
141
142 if (Container::IsCurrentUseNewPipeline()) {
143 JSViewAbstract::JsHeight(jsValue);
144 return;
145 }
146 ToggleModel::GetInstance()->SetHeight(value);
147 }
148
JsSize(const JSCallbackInfo & info)149 void JSToggle::JsSize(const JSCallbackInfo& info)
150 {
151 if (info.Length() < 1) {
152 LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
153 return;
154 }
155
156 if (!info[0]->IsObject()) {
157 LOGE("arg is not Object or String.");
158 return;
159 }
160
161 JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
162 JsWidth(sizeObj->GetProperty("width"));
163 JsHeight(sizeObj->GetProperty("height"));
164 }
165
OnChange(const JSCallbackInfo & args)166 void JSToggle::OnChange(const JSCallbackInfo& args)
167 {
168 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
169 auto onChange = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](bool isOn) {
170 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
171 ACE_SCORING_EVENT("Toggle.onChange");
172 auto newJSVal = JSRef<JSVal>::Make(ToJSValue(isOn));
173 func->ExecuteJS(1, &newJSVal);
174 };
175 ToggleModel::GetInstance()->OnChange(std::move(onChange));
176 args.ReturnSelf();
177 }
178
SelectedColor(const JSCallbackInfo & info)179 void JSToggle::SelectedColor(const JSCallbackInfo& info)
180 {
181 if (info.Length() < 1) {
182 LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
183 return;
184 }
185 Color selectedColor;
186 if (!ParseJsColor(info[0], selectedColor)) {
187 return;
188 }
189
190 ToggleModel::GetInstance()->SetSelectedColor(selectedColor);
191 }
192
SwitchPointColor(const JSCallbackInfo & info)193 void JSToggle::SwitchPointColor(const JSCallbackInfo& info)
194 {
195 if (info.Length() < 1) {
196 LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
197 return;
198 }
199 Color color;
200 if (!ParseJsColor(info[0], color)) {
201 return;
202 }
203
204 ToggleModel::GetInstance()->SetSwitchPointColor(color);
205 }
206
JsPadding(const JSCallbackInfo & info)207 void JSToggle::JsPadding(const JSCallbackInfo& info)
208 {
209 if (info.Length() < 1) {
210 LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
211 return;
212 }
213 if (!info[0]->IsString() && !info[0]->IsNumber() && !info[0]->IsObject()) {
214 LOGE("arg is not a string, number or object.");
215 return;
216 }
217 if (Container::IsCurrentUseNewPipeline() || ToggleModel::GetInstance()->IsToggle()) {
218 JSViewAbstract::JsPadding(info);
219 return;
220 }
221
222 if (info[0]->IsObject()) {
223 auto argsPtrItem = JsonUtil::ParseJsonString(info[0]->ToString());
224 if (!argsPtrItem || argsPtrItem->IsNull()) {
225 LOGE("Js Parse object failed. argsPtr is null. %s", info[0]->ToString().c_str());
226 return;
227 }
228 if (argsPtrItem->Contains("top") || argsPtrItem->Contains("bottom") || argsPtrItem->Contains("left") ||
229 argsPtrItem->Contains("right")) {
230 Dimension topDimen = Dimension(0.0, DimensionUnit::VP);
231 Dimension leftDimen = Dimension(0.0, DimensionUnit::VP);
232 Dimension rightDimen = Dimension(0.0, DimensionUnit::VP);
233 Dimension bottomDimen = Dimension(0.0, DimensionUnit::VP);
234 ParseJsonDimensionVp(argsPtrItem->GetValue("top"), topDimen);
235 ParseJsonDimensionVp(argsPtrItem->GetValue("left"), leftDimen);
236 ParseJsonDimensionVp(argsPtrItem->GetValue("right"), rightDimen);
237 ParseJsonDimensionVp(argsPtrItem->GetValue("bottom"), bottomDimen);
238 if (leftDimen == 0.0_vp) {
239 leftDimen = rightDimen;
240 }
241 if (topDimen == 0.0_vp) {
242 topDimen = bottomDimen;
243 }
244 if (leftDimen == 0.0_vp) {
245 leftDimen = topDimen;
246 }
247 NG::PaddingPropertyF padding;
248 padding.left = leftDimen.ConvertToPx();
249 padding.right = rightDimen.ConvertToPx();
250 padding.top = topDimen.ConvertToPx();
251 padding.bottom = bottomDimen.ConvertToPx();
252 ToggleModel::GetInstance()->SetPadding(padding);
253 return;
254 }
255 }
256 Dimension length;
257 if (!JSViewAbstract::ParseJsDimensionVp(info[0], length)) {
258 return;
259 }
260 NG::PaddingPropertyF padding;
261 padding.left = length.ConvertToPx();
262 padding.right = length.ConvertToPx();
263 padding.top = length.ConvertToPx();
264 padding.bottom = length.ConvertToPx();
265 ToggleModel::GetInstance()->SetPadding(padding);
266 }
267
SetBackgroundColor(const JSCallbackInfo & info)268 void JSToggle::SetBackgroundColor(const JSCallbackInfo& info)
269 {
270 if (info.Length() < 1) {
271 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
272 return;
273 }
274 Color backgroundColor;
275 if (!ParseJsColor(info[0], backgroundColor)) {
276 return;
277 }
278
279 if (!Container::IsCurrentUseNewPipeline()) {
280 JSViewAbstract::JsBackgroundColor(info);
281 return;
282 }
283 ToggleModel::GetInstance()->SetBackgroundColor(backgroundColor);
284 }
285
286 } // namespace OHOS::Ace::Framework
287