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