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_rect.h"
17
18 #include "base/log/ace_trace.h"
19 #include "bridge/declarative_frontend/jsview/models/rect_model_impl.h"
20 #include "bridge/declarative_frontend/view_stack_processor.h"
21 #include "core/components_ng/pattern/shape/rect_model.h"
22 #include "core/components_ng/pattern/shape/rect_model_ng.h"
23
24 namespace OHOS::Ace {
25
26 std::unique_ptr<RectModel> RectModel::instance_ = nullptr;
27
GetInstance()28 RectModel* RectModel::GetInstance()
29 {
30 if (!instance_) {
31 #ifdef NG_BUILD
32 instance_.reset(new NG::RectModelNG());
33 #else
34 if (Container::IsCurrentUseNewPipeline()) {
35 instance_.reset(new NG::RectModelNG());
36 } else {
37 instance_.reset(new Framework::RectModelImpl());
38 }
39 #endif
40 }
41 return instance_.get();
42 }
43
44 } // namespace OHOS::Ace
45
46 namespace OHOS::Ace::Framework {
47
Create(const JSCallbackInfo & info)48 void JSRect::Create(const JSCallbackInfo& info)
49 {
50 RectModel::GetInstance()->Create();
51 JSShapeAbstract::SetSize(info);
52 if (info.Length() > 0 && info[0]->IsObject()) {
53 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
54 JSRef<JSVal> radiusWidth = obj->GetProperty("radiusWidth");
55 Dimension widthValue;
56 if (ParseJsDimensionVp(radiusWidth, widthValue)) {
57 RectModel::GetInstance()->SetRadiusWidth(widthValue);
58 }
59
60 JSRef<JSVal> radiusHeight = obj->GetProperty("radiusHeight");
61 Dimension heightValue;
62 if (ParseJsDimensionVp(radiusHeight, heightValue)) {
63 RectModel::GetInstance()->SetRadiusHeight(heightValue);
64 }
65
66 JSRef<JSVal> radius = obj->GetProperty("radius");
67 if (radius->IsNumber() || radius->IsString()) {
68 SetRadiusWithJsVal<ShapeComponent>(nullptr, radius);
69 }
70 if (radius->IsArray()) {
71 SetRadiusWithArrayValue<ShapeComponent>(nullptr, radius);
72 }
73 info.SetReturnValue(info.This());
74 }
75 }
76
SetRadiusWidth(const JSCallbackInfo & info)77 void JSRect::SetRadiusWidth(const JSCallbackInfo& info)
78 {
79 if (info.Length() < 1) {
80 LOGE("The arg is wrong, it is supposed to have at least 1 argument");
81 return;
82 }
83
84 if (!info[0]->IsNumber() && !info[0]->IsString()) {
85 LOGE("arg is not Number or String.");
86 return;
87 }
88 Dimension value;
89 if (!ParseJsDimensionVp(info[0], value)) {
90 return;
91 }
92 RectModel::GetInstance()->SetRadiusWidth(value);
93 }
94
SetRadiusHeight(const JSCallbackInfo & info)95 void JSRect::SetRadiusHeight(const JSCallbackInfo& info)
96 {
97 if (info.Length() < 1) {
98 LOGE("The arg is wrong, it is supposed to have at least 1 argument");
99 return;
100 }
101 Dimension value;
102 if (!ParseJsDimensionVp(info[0], value)) {
103 return;
104 }
105 RectModel::GetInstance()->SetRadiusHeight(value);
106 }
107
SetRadius(const JSCallbackInfo & info)108 void JSRect::SetRadius(const JSCallbackInfo& info)
109 {
110 if (info.Length() < 1) {
111 LOGE("The arg is wrong, it is supposed to have at least 1 argument");
112 return;
113 }
114 if (info[0]->IsArray()) {
115 SetRadiusWithArrayValue<ShapeComponent>(nullptr, info[0]);
116 info.SetReturnValue(info.This());
117 return;
118 }
119 if (info[0]->IsNumber() || info[0]->IsString() || info[0]->IsObject()) {
120 SetRadiusWithJsVal<ShapeComponent>(nullptr, info[0]);
121 info.SetReturnValue(info.This());
122 }
123 }
124
125 template<class T>
SetRadiusWithJsVal(const RefPtr<T> & component,const JSRef<JSVal> & jsVal)126 void JSRect::SetRadiusWithJsVal(const RefPtr<T>& component, const JSRef<JSVal>& jsVal)
127 {
128 Dimension value;
129 if (!ParseJsDimensionVp(jsVal, value)) {
130 return;
131 }
132 if (component) {
133 AnimationOption option = ViewStackProcessor::GetInstance()->GetImplicitAnimationOption();
134 component->SetRadiusWidth(value, option);
135 component->SetRadiusHeight(value, option);
136 return;
137 }
138 RectModel::GetInstance()->SetRadiusWidth(value);
139 RectModel::GetInstance()->SetRadiusHeight(value);
140 }
141
142 template<class T>
SetRadiusWithArrayValue(const RefPtr<T> & component,const JSRef<JSVal> & jsVal)143 void JSRect::SetRadiusWithArrayValue(const RefPtr<T>& component, const JSRef<JSVal>& jsVal)
144 {
145 JSRef<JSArray> array = JSRef<JSArray>::Cast(jsVal);
146 int32_t length = static_cast<int32_t>(array->Length());
147 if (length <= 0) {
148 LOGE("info is invalid");
149 return;
150 }
151 length = std::min(length, 4);
152 for (int32_t i = 0; i < length; i++) {
153 JSRef<JSVal> radiusItem = array->GetValueAt(i);
154 if (!radiusItem->IsArray()) {
155 break;
156 }
157 JSRef<JSArray> radiusArray = JSRef<JSArray>::Cast(radiusItem);
158 if (radiusArray->Length() != 2) {
159 break;
160 }
161 JSRef<JSVal> radiusX = radiusArray->GetValueAt(0);
162 JSRef<JSVal> radiusY = radiusArray->GetValueAt(1);
163 Dimension radiusXValue;
164 Dimension radiusYValue;
165 if (ParseJsDimensionVp(radiusX, radiusXValue) && ParseJsDimensionVp(radiusY, radiusYValue)) {
166 SetRadiusValue<T>(component, radiusXValue, radiusYValue, i);
167 }
168 }
169 }
170
171 template<class T>
SetRadiusValue(const RefPtr<T> & component,const Dimension & radiusX,const Dimension & radiusY,int32_t index)172 void JSRect::SetRadiusValue(
173 const RefPtr<T>& component, const Dimension& radiusX, const Dimension& radiusY, int32_t index)
174 {
175 if (component) {
176 RectModel::GetInstance()->SetCallbackRadius(component, radiusX, radiusY, index);
177 } else {
178 RectModel::GetInstance()->SetRadiusValue(radiusX, radiusY, index);
179 }
180 }
181
ObjectRadiusWidth(const JSCallbackInfo & info)182 void JSRect::ObjectRadiusWidth(const JSCallbackInfo& info)
183 {
184 info.ReturnSelf();
185 if (info.Length() < 1) {
186 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
187 return;
188 }
189 Dimension value;
190 if (!ParseJsDimensionVp(info[0], value)) {
191 return;
192 }
193 if (LessNotEqual(value.Value(), 0.0)) {
194 LOGE("Value is less than zero");
195 return;
196 }
197 auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
198 if (rect) {
199 rect->SetRadiusWidth(value);
200 }
201 }
202
ObjectRadiusHeight(const JSCallbackInfo & info)203 void JSRect::ObjectRadiusHeight(const JSCallbackInfo& info)
204 {
205 info.ReturnSelf();
206 if (info.Length() < 1) {
207 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
208 return;
209 }
210 Dimension value;
211 if (!ParseJsDimensionVp(info[0], value)) {
212 return;
213 }
214 if (LessNotEqual(value.Value(), 0.0)) {
215 LOGE("Value is less than zero");
216 return;
217 }
218 auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
219 if (rect) {
220 rect->SetRadiusHeight(value);
221 }
222 }
223
ObjectRadius(const JSCallbackInfo & info)224 void JSRect::ObjectRadius(const JSCallbackInfo& info)
225 {
226 info.ReturnSelf();
227 if (info.Length() < 1) {
228 LOGE("arg is invalid");
229 return;
230 }
231 auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
232 if (!rect) {
233 LOGE("rect is null");
234 return;
235 }
236 if (info[0]->IsNumber() || info[0]->IsString()) {
237 SetRadiusWithJsVal<ShapeRect>(rect, info[0]);
238 }
239 if (info[0]->IsArray()) {
240 SetRadiusWithArrayValue<ShapeRect>(rect, info[0]);
241 }
242 }
243
ConstructorCallback(const JSCallbackInfo & info)244 void JSRect::ConstructorCallback(const JSCallbackInfo& info)
245 {
246 auto jsRect = AceType::MakeRefPtr<JSRect>();
247 auto rect = AceType::MakeRefPtr<ShapeRect>();
248 if (info.Length() > 0 && info[0]->IsObject()) {
249 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
250 Dimension width;
251 if (ParseJsDimensionVp(obj->GetProperty("width"), width) && width.IsValid()) {
252 rect->SetWidth(width);
253 }
254 Dimension height;
255 if (ParseJsDimensionVp(obj->GetProperty("height"), height) && height.IsValid()) {
256 rect->SetHeight(height);
257 }
258 Dimension radiusWidth;
259 if (ParseJsDimensionVp(obj->GetProperty("radiusWidth"), radiusWidth) && radiusWidth.IsValid()) {
260 rect->SetRadiusWidth(radiusWidth);
261 }
262 Dimension radiusHeight;
263 if (ParseJsDimensionVp(obj->GetProperty("radiusHeight"), radiusHeight) && radiusHeight.IsValid()) {
264 rect->SetRadiusHeight(radiusHeight);
265 }
266 JSRef<JSVal> radius = obj->GetProperty("radius");
267 if (radius->IsNumber() || radius->IsString()) {
268 SetRadiusWithJsVal<ShapeRect>(rect, radius);
269 }
270 if (radius->IsArray()) {
271 SetRadiusWithArrayValue<ShapeRect>(rect, radius);
272 }
273 info.SetReturnValue(info.This());
274 }
275 jsRect->SetBasicShape(rect);
276 jsRect->IncRefCount();
277 info.SetReturnValue(AceType::RawPtr(jsRect));
278 }
279
DestructorCallback(JSRect * jsRect)280 void JSRect::DestructorCallback(JSRect* jsRect)
281 {
282 if (jsRect != nullptr) {
283 jsRect->DecRefCount();
284 }
285 }
286
JSBind(BindingTarget globalObj)287 void JSRect::JSBind(BindingTarget globalObj)
288 {
289 JSClass<JSRect>::Declare("Rect");
290 JSClass<JSRect>::StaticMethod("create", &JSRect::Create);
291 JSClass<JSRect>::StaticMethod("radiusWidth", &JSRect::SetRadiusWidth);
292 JSClass<JSRect>::StaticMethod("radiusHeight", &JSRect::SetRadiusHeight);
293 JSClass<JSRect>::StaticMethod("radius", &JSRect::SetRadius);
294
295 JSClass<JSRect>::CustomMethod("width", &JSShapeAbstract::ObjectWidth);
296 JSClass<JSRect>::CustomMethod("height", &JSShapeAbstract::ObjectHeight);
297 JSClass<JSRect>::CustomMethod("size", &JSShapeAbstract::ObjectSize);
298 JSClass<JSRect>::CustomMethod("offset", &JSShapeAbstract::ObjectOffset);
299 JSClass<JSRect>::CustomMethod("radiusWidth", &JSRect::ObjectRadiusWidth);
300 JSClass<JSRect>::CustomMethod("radiusHeight", &JSRect::ObjectRadiusHeight);
301 JSClass<JSRect>::CustomMethod("radius", &JSRect::ObjectRadius);
302 JSClass<JSRect>::CustomMethod("fill", &JSShapeAbstract::ObjectFill);
303
304 JSClass<JSRect>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
305 JSClass<JSRect>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
306 JSClass<JSRect>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
307 JSClass<JSRect>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
308 JSClass<JSRect>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
309
310 JSClass<JSRect>::Inherit<JSShapeAbstract>();
311 JSClass<JSRect>::Bind(globalObj, JSRect::ConstructorCallback, JSRect::DestructorCallback);
312 }
313
314 } // namespace OHOS::Ace::Framework
315