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