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 "core/components_ng/base/view_stack_model.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 {
GetInstance()25 RectModel* RectModel::GetInstance()
26 {
27 #ifdef NG_BUILD
28 static NG::RectModelNG instance;
29 return &instance;
30 #else
31 if (Container::IsCurrentUseNewPipeline()) {
32 static NG::RectModelNG instance;
33 return &instance;
34 } else {
35 static Framework::RectModelImpl instance;
36 return &instance;
37 }
38 #endif
39 }
40 } // namespace OHOS::Ace
41
42 namespace OHOS::Ace::Framework {
43 namespace {
44 constexpr uint32_t HAS_RADIUS_WIDTH = 1;
45 constexpr uint32_t HAS_RADIUS_HEIGHT = 1 << 1;
46 constexpr uint32_t HAS_RADIUS = 1 << 2;
47 } // namespace
48
Create(const JSCallbackInfo& info)49 void JSRect::Create(const JSCallbackInfo& info)
50 {
51 RectModel::GetInstance()->Create();
52 JSShapeAbstract::SetSize(info);
53 if (info.Length() > 0 && info[0]->IsObject()) {
54 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
55 auto propertyNames = obj->GetPropertyNames();
56 if (!propertyNames->IsArray()) {
57 return;
58 }
59 auto propertyFlag = 0U;
60 for (size_t i = 0; i < propertyNames->Length(); i++) {
61 JSRef<JSVal> value = propertyNames->GetValueAt(i);
62 if (!value->IsString()) {
63 continue;
64 }
65 auto propertyName = value->ToString();
66 if (propertyName == "radiusWidth") {
67 propertyFlag = propertyFlag | HAS_RADIUS_WIDTH;
68 } else if (propertyName == "radiusHeight") {
69 propertyFlag = propertyFlag | HAS_RADIUS_HEIGHT;
70 } else if (propertyName == "radius") {
71 propertyFlag = propertyFlag | HAS_RADIUS;
72 }
73 }
74 if ((propertyFlag & HAS_RADIUS_WIDTH) == HAS_RADIUS_WIDTH) {
75 JSRef<JSVal> radiusWidth = obj->GetProperty("radiusWidth");
76 SetRadiusWidth(radiusWidth);
77 }
78 if ((propertyFlag & HAS_RADIUS_HEIGHT) == HAS_RADIUS_HEIGHT) {
79 JSRef<JSVal> radiusHeight = obj->GetProperty("radiusHeight");
80 SetRadiusHeight(radiusHeight);
81 }
82 if ((propertyFlag & HAS_RADIUS) == HAS_RADIUS) {
83 JSRef<JSVal> radius = obj->GetProperty("radius");
84 if (radius->IsNumber() || radius->IsString()) {
85 SetRadiusWithJsVal(nullptr, radius);
86 } else if (radius->IsArray()) {
87 SetRadiusWithArrayValue(nullptr, radius);
88 }
89 }
90 info.SetReturnValue(info.This());
91 }
92 }
93
JsRadiusWidth(const JSCallbackInfo& info)94 void JSRect::JsRadiusWidth(const JSCallbackInfo& info)
95 {
96 if (info.Length() < 1) {
97 return;
98 }
99 SetRadiusWidth(info[0]);
100 }
101
JsRadiusHeight(const JSCallbackInfo& info)102 void JSRect::JsRadiusHeight(const JSCallbackInfo& info)
103 {
104 if (info.Length() < 1) {
105 return;
106 }
107 SetRadiusHeight(info[0]);
108 }
109
SetRadiusWidth(const JSRef<JSVal>& jsVal)110 void JSRect::SetRadiusWidth(const JSRef<JSVal>& jsVal)
111 {
112 CalcDimension value(0.0f);
113 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
114 ParseJsDimensionVp(jsVal, value);
115 } else {
116 if (!ParseJsDimensionVpNG(jsVal, value)) {
117 value.SetValue(0.0f);
118 }
119 }
120 RectModel::GetInstance()->SetRadiusWidth(value);
121 }
122
SetRadiusHeight(const JSRef<JSVal>& jsVal)123 void JSRect::SetRadiusHeight(const JSRef<JSVal>& jsVal)
124 {
125 CalcDimension value(0.0f);
126 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
127 ParseJsDimensionVp(jsVal, value);
128 } else {
129 if (!ParseJsDimensionVpNG(jsVal, value)) {
130 value.SetValue(0.0f);
131 }
132 }
133 RectModel::GetInstance()->SetRadiusHeight(value);
134 }
135
SetRadius(const JSCallbackInfo& info)136 void JSRect::SetRadius(const JSCallbackInfo& info)
137 {
138 if (info.Length() < 1) {
139 return;
140 }
141 CalcDimension value(0.0f);
142 RectModel::GetInstance()->SetRadiusWidth(value);
143 RectModel::GetInstance()->SetRadiusHeight(value);
144 if (info[0]->IsArray()) {
145 SetRadiusWithArrayValue(nullptr, info[0]);
146 info.SetReturnValue(info.This());
147 return;
148 }
149 if (info[0]->IsNumber() || info[0]->IsString() || info[0]->IsObject()) {
150 SetRadiusWithJsVal(nullptr, info[0]);
151 info.SetReturnValue(info.This());
152 }
153 }
154
SetRadiusWithJsVal(const RefPtr<ShapeRect>& shapeRect, const JSRef<JSVal>& jsVal)155 void JSRect::SetRadiusWithJsVal(const RefPtr<ShapeRect>& shapeRect, const JSRef<JSVal>& jsVal)
156 {
157 CalcDimension value(0.0f);
158 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
159 ParseJsDimensionVp(jsVal, value);
160 } else {
161 if (!ParseJsDimensionVpNG(jsVal, value)) {
162 value.SetValue(0.0f);
163 }
164 }
165 if (shapeRect) {
166 AnimationOption option = ViewStackModel::GetInstance()->GetImplicitAnimationOption();
167 shapeRect->SetRadiusWidth(value, option);
168 shapeRect->SetRadiusHeight(value, option);
169 return;
170 }
171 RectModel::GetInstance()->SetRadiusWidth(value);
172 RectModel::GetInstance()->SetRadiusHeight(value);
173 }
174
SetRadiusWithArrayValue(const RefPtr<ShapeRect>& shapeRect, const JSRef<JSVal>& jsVal)175 void JSRect::SetRadiusWithArrayValue(const RefPtr<ShapeRect>& shapeRect, const JSRef<JSVal>& jsVal)
176 {
177 if (!jsVal->IsArray()) {
178 return;
179 }
180 JSRef<JSArray> array = JSRef<JSArray>::Cast(jsVal);
181 auto length = static_cast<int32_t>(array->Length());
182 if (length <= 0) {
183 return;
184 }
185 length = std::min(length, 4);
186 for (int32_t i = 0; i < length; i++) {
187 JSRef<JSVal> radiusItem = array->GetValueAt(i);
188 if (!radiusItem->IsArray()) {
189 break;
190 }
191 JSRef<JSArray> radiusArray = JSRef<JSArray>::Cast(radiusItem);
192 if (radiusArray->Length() != 2) {
193 break;
194 }
195 JSRef<JSVal> radiusX = radiusArray->GetValueAt(0);
196 JSRef<JSVal> radiusY = radiusArray->GetValueAt(1);
197 CalcDimension radiusXValue(0.0f);
198 CalcDimension radiusYValue(0.0f);
199 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
200 if (ParseJsDimensionVp(radiusX, radiusXValue)) {
201 ParseJsDimensionVp(radiusY, radiusYValue);
202 }
203 } else {
204 if (!ParseJsDimensionVpNG(radiusX, radiusXValue)) {
205 radiusXValue.SetValue(0.0f);
206 }
207 if (!ParseJsDimensionVpNG(radiusY, radiusYValue)) {
208 radiusYValue.SetValue(0.0f);
209 }
210 }
211 SetRadiusValue(shapeRect, radiusXValue, radiusYValue, i);
212 }
213 }
214
SetRadiusValue( const RefPtr<ShapeRect>& shapeRect, const CalcDimension& radiusX, const CalcDimension& radiusY, int32_t index)215 void JSRect::SetRadiusValue(
216 const RefPtr<ShapeRect>& shapeRect, const CalcDimension& radiusX, const CalcDimension& radiusY, int32_t index)
217 {
218 if (shapeRect) {
219 RectModel::GetInstance()->SetShapeRectRadius(shapeRect, radiusX, radiusY, index);
220 } else {
221 RectModel::GetInstance()->SetRadiusValue(radiusX, radiusY, index);
222 }
223 }
224
ObjectRadiusWidth(const JSCallbackInfo& info)225 void JSRect::ObjectRadiusWidth(const JSCallbackInfo& info)
226 {
227 info.ReturnSelf();
228 if (info.Length() < 1) {
229 return;
230 }
231 CalcDimension value;
232 if (!ParseJsDimensionVp(info[0], value)) {
233 return;
234 }
235 if (LessNotEqual(value.Value(), 0.0)) {
236 return;
237 }
238 auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
239 if (rect) {
240 rect->SetRadiusWidth(value);
241 }
242 }
243
ObjectRadiusHeight(const JSCallbackInfo& info)244 void JSRect::ObjectRadiusHeight(const JSCallbackInfo& info)
245 {
246 info.ReturnSelf();
247 if (info.Length() < 1) {
248 return;
249 }
250 CalcDimension value;
251 if (!ParseJsDimensionVp(info[0], value)) {
252 return;
253 }
254 if (LessNotEqual(value.Value(), 0.0)) {
255 return;
256 }
257 auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
258 if (rect) {
259 rect->SetRadiusHeight(value);
260 }
261 }
262
ObjectRadius(const JSCallbackInfo& info)263 void JSRect::ObjectRadius(const JSCallbackInfo& info)
264 {
265 info.ReturnSelf();
266 if (info.Length() < 1) {
267 return;
268 }
269 auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
270 if (!rect) {
271 return;
272 }
273 if (info[0]->IsNumber() || info[0]->IsString()) {
274 SetRadiusWithJsVal(rect, info[0]);
275 }
276 if (info[0]->IsArray()) {
277 SetRadiusWithArrayValue(rect, info[0]);
278 }
279 }
280
ParseRectObjBelowApi12(const RefPtr<ShapeRect>& rect, const JSRef<JSObject>& obj)281 void JSRect::ParseRectObjBelowApi12(const RefPtr<ShapeRect>& rect, const JSRef<JSObject>& obj)
282 {
283 CalcDimension width;
284 CalcDimension height;
285 CalcDimension radiusWidth;
286 CalcDimension radiusHeight;
287 if (ParseJsDimensionVp(obj->GetProperty("width"), width) && width.IsValid()) {
288 rect->SetWidth(width);
289 }
290 if (ParseJsDimensionVp(obj->GetProperty("height"), height) && height.IsValid()) {
291 rect->SetHeight(height);
292 }
293 if (ParseJsDimensionVp(obj->GetProperty("radiusWidth"), radiusWidth) && radiusWidth.IsValid()) {
294 rect->SetRadiusWidth(radiusWidth);
295 }
296 if (ParseJsDimensionVp(obj->GetProperty("radiusHeight"), radiusHeight) && radiusHeight.IsValid()) {
297 rect->SetRadiusHeight(radiusHeight);
298 }
299 }
300
ParseRectObjAboveApi12(const RefPtr<ShapeRect>& rect, const JSRef<JSObject>& obj)301 void JSRect::ParseRectObjAboveApi12(const RefPtr<ShapeRect>& rect, const JSRef<JSObject>& obj)
302 {
303 CalcDimension width;
304 CalcDimension height;
305 CalcDimension radiusWidth;
306 CalcDimension radiusHeight;
307 if (ParseJsDimensionVpNG(obj->GetProperty("width"), width) && width.IsValid()) {
308 rect->SetWidth(width);
309 }
310 if (ParseJsDimensionVpNG(obj->GetProperty("height"), height) && height.IsValid()) {
311 rect->SetHeight(height);
312 }
313 if (ParseJsDimensionVpNG(obj->GetProperty("radiusWidth"), radiusWidth) && radiusWidth.IsValid()) {
314 rect->SetRadiusWidth(radiusWidth);
315 }
316 if (ParseJsDimensionVpNG(obj->GetProperty("radiusHeight"), radiusHeight) && radiusHeight.IsValid()) {
317 rect->SetRadiusHeight(radiusHeight);
318 }
319 }
320
ConstructorCallback(const JSCallbackInfo& info)321 void JSRect::ConstructorCallback(const JSCallbackInfo& info)
322 {
323 auto jsRect = AceType::MakeRefPtr<JSRect>();
324 auto rect = AceType::MakeRefPtr<ShapeRect>();
325 if (info.Length() > 0 && info[0]->IsObject()) {
326 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
327 if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
328 ParseRectObjBelowApi12(rect, obj);
329 } else {
330 ParseRectObjAboveApi12(rect, obj);
331 }
332 JSRef<JSVal> radius = obj->GetProperty("radius");
333 if (radius->IsNumber() || radius->IsString()) {
334 SetRadiusWithJsVal(rect, radius);
335 } else if (radius->IsArray()) {
336 SetRadiusWithArrayValue(rect, radius);
337 }
338 info.SetReturnValue(info.This());
339 }
340 jsRect->SetBasicShape(rect);
341 jsRect->IncRefCount();
342 info.SetReturnValue(AceType::RawPtr(jsRect));
343 }
344
DestructorCallback(JSRect* jsRect)345 void JSRect::DestructorCallback(JSRect* jsRect)
346 {
347 if (jsRect != nullptr) {
348 jsRect->DecRefCount();
349 }
350 }
351
JSBind(BindingTarget globalObj)352 void JSRect::JSBind(BindingTarget globalObj)
353 {
354 JSClass<JSRect>::Declare("Rect");
355 JSClass<JSRect>::StaticMethod("create", &JSRect::Create);
356 JSClass<JSRect>::StaticMethod("radiusWidth", &JSRect::JsRadiusWidth);
357 JSClass<JSRect>::StaticMethod("radiusHeight", &JSRect::JsRadiusHeight);
358 JSClass<JSRect>::StaticMethod("radius", &JSRect::SetRadius);
359
360 JSClass<JSRect>::CustomMethod("width", &JSShapeAbstract::ObjectWidth);
361 JSClass<JSRect>::CustomMethod("height", &JSShapeAbstract::ObjectHeight);
362 JSClass<JSRect>::CustomMethod("size", &JSShapeAbstract::ObjectSize);
363 JSClass<JSRect>::CustomMethod("offset", &JSShapeAbstract::ObjectOffset);
364 JSClass<JSRect>::CustomMethod("radiusWidth", &JSRect::ObjectRadiusWidth);
365 JSClass<JSRect>::CustomMethod("radiusHeight", &JSRect::ObjectRadiusHeight);
366 JSClass<JSRect>::CustomMethod("radius", &JSRect::ObjectRadius);
367 JSClass<JSRect>::CustomMethod("fill", &JSShapeAbstract::ObjectFill);
368 JSClass<JSRect>::CustomMethod("position", &JSShapeAbstract::ObjectPosition);
369
370 JSClass<JSRect>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
371 JSClass<JSRect>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
372 JSClass<JSRect>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
373 JSClass<JSRect>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
374 JSClass<JSRect>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
375
376 JSClass<JSRect>::InheritAndBind<JSShapeAbstract>(
377 globalObj, JSRect::ConstructorCallback, JSRect::DestructorCallback);
378 }
379
380 } // namespace OHOS::Ace::Framework
381