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