• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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->IsObject()) {
87                 auto radiusObj = JSRef<JSObject>::Cast(radius);
88                 auto resType = radiusObj->GetPropertyValue("type", -1); //-1 means unkown resource type
89                 if (resType == -1) {
90                     SetRadiusWithArrayValue(nullptr, radius);
91                 } else {
92                     SetRadiusWithJsVal(nullptr, radius);
93                 }
94             }
95         }
96         info.SetReturnValue(info.This());
97     }
98 }
99 
JsRadiusWidth(const JSCallbackInfo & info)100 void JSRect::JsRadiusWidth(const JSCallbackInfo& info)
101 {
102     if (info.Length() < 1) {
103         return;
104     }
105     SetRadiusWidth(info[0]);
106 }
107 
JsRadiusHeight(const JSCallbackInfo & info)108 void JSRect::JsRadiusHeight(const JSCallbackInfo& info)
109 {
110     if (info.Length() < 1) {
111         return;
112     }
113     SetRadiusHeight(info[0]);
114 }
115 
SetRadiusWidth(const JSRef<JSVal> & jsVal)116 void JSRect::SetRadiusWidth(const JSRef<JSVal>& jsVal)
117 {
118     CalcDimension value(0.0f);
119     RefPtr<ResourceObject> radiusWidthResObj;
120     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
121         ParseJsDimensionVp(jsVal, value, radiusWidthResObj);
122     } else {
123         if (!ParseJsDimensionVpNG(jsVal, value, radiusWidthResObj)) {
124             value.SetValue(0.0f);
125         }
126     }
127     UnRegisterResource("RectRadiusWidth");
128     if (SystemProperties::ConfigChangePerform() && radiusWidthResObj) {
129         RegisterResource<CalcDimension>("RectRadiusWidth", radiusWidthResObj, value);
130     }
131     RectModel::GetInstance()->SetRadiusWidth(value);
132 }
133 
SetRadiusHeight(const JSRef<JSVal> & jsVal)134 void JSRect::SetRadiusHeight(const JSRef<JSVal>& jsVal)
135 {
136     CalcDimension value(0.0f);
137     RefPtr<ResourceObject> radiusHeightResObj;
138     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
139         ParseJsDimensionVp(jsVal, value, radiusHeightResObj);
140     } else {
141         if (!ParseJsDimensionVpNG(jsVal, value, radiusHeightResObj)) {
142             value.SetValue(0.0f);
143         }
144     }
145     UnRegisterResource("RectRadiusHeight");
146     if (SystemProperties::ConfigChangePerform() && radiusHeightResObj) {
147         RegisterResource<CalcDimension>("RectRadiusHeight", radiusHeightResObj, value);
148     }
149     RectModel::GetInstance()->SetRadiusHeight(value);
150 }
151 
SetRadius(const JSCallbackInfo & info)152 void JSRect::SetRadius(const JSCallbackInfo& info)
153 {
154     if (info.Length() < 1) {
155         return;
156     }
157     CalcDimension value(0.0f);
158     RectModel::GetInstance()->SetRadiusWidth(value);
159     RectModel::GetInstance()->SetRadiusHeight(value);
160     if (info[0]->IsArray()) {
161         SetRadiusWithArrayValue(nullptr, info[0]);
162         info.SetReturnValue(info.This());
163         return;
164     }
165     if (info[0]->IsNumber() || info[0]->IsString() || info[0]->IsObject()) {
166         SetRadiusWithJsVal(nullptr, info[0]);
167         info.SetReturnValue(info.This());
168     }
169 }
170 
SetRadiusWithJsVal(const RefPtr<ShapeRect> & shapeRect,const JSRef<JSVal> & jsVal)171 void JSRect::SetRadiusWithJsVal(const RefPtr<ShapeRect>& shapeRect, const JSRef<JSVal>& jsVal)
172 {
173     CalcDimension value(0.0f);
174     RefPtr<ResourceObject> radiusResObj;
175     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
176         ParseJsDimensionVp(jsVal, value, radiusResObj);
177     } else {
178         if (!ParseJsDimensionVpNG(jsVal, value, radiusResObj)) {
179             value.SetValue(0.0f);
180         }
181     }
182     if (shapeRect) {
183         AnimationOption option = ViewStackModel::GetInstance()->GetImplicitAnimationOption();
184         shapeRect->SetRadiusWidth(value, option);
185         shapeRect->SetRadiusHeight(value, option);
186         return;
187     }
188     UnRegisterResource("RectRadius");
189     if (SystemProperties::ConfigChangePerform() && radiusResObj) {
190         RegisterResource<CalcDimension>("RectRadius", radiusResObj, value);
191     }
192     RectModel::GetInstance()->SetRadiusWidth(value);
193     RectModel::GetInstance()->SetRadiusHeight(value);
194 }
195 
SetRadiusWithArrayValue(const RefPtr<ShapeRect> & shapeRect,const JSRef<JSVal> & jsVal)196 void JSRect::SetRadiusWithArrayValue(const RefPtr<ShapeRect>& shapeRect, const JSRef<JSVal>& jsVal)
197 {
198     static std::vector<std::string> RADIUS_TYPES = { "TopLeft", "TopRight", "BottomRight", "BottomLeft" };
199     if (!jsVal->IsArray()) {
200         return;
201     }
202     JSRef<JSArray> array = JSRef<JSArray>::Cast(jsVal);
203     auto length = static_cast<int32_t>(array->Length());
204     if (length <= 0) {
205         return;
206     }
207     length = std::min(length, 4);
208     for (int32_t i = 0; i < length; i++) {
209         JSRef<JSVal> radiusItem = array->GetValueAt(i);
210         if (!radiusItem->IsArray()) {
211             break;
212         }
213         JSRef<JSArray> radiusArray = JSRef<JSArray>::Cast(radiusItem);
214         if (radiusArray->Length() != 2) {
215             break;
216         }
217         JSRef<JSVal> radiusX = radiusArray->GetValueAt(0);
218         JSRef<JSVal> radiusY = radiusArray->GetValueAt(1);
219         CalcDimension radiusXValue(0.0f);
220         CalcDimension radiusYValue(0.0f);
221         RefPtr<ResourceObject> radiusXResObj;
222         RefPtr<ResourceObject> radiusYResObj;
223         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
224             if (ParseJsDimensionVp(radiusX, radiusXValue)) {
225                 ParseJsDimensionVp(radiusY, radiusYValue);
226             }
227         } else {
228             if (!ParseJsDimensionVpNG(radiusX, radiusXValue, radiusXResObj)) {
229                 radiusXValue.SetValue(0.0f);
230             }
231             if (!ParseJsDimensionVpNG(radiusY, radiusYValue, radiusYResObj)) {
232                 radiusYValue.SetValue(0.0f);
233             }
234         }
235         std::string key = std::string("RectRadius") + RADIUS_TYPES[i];
236         UnRegisterResource(key);
237         if (SystemProperties::ConfigChangePerform() && (radiusXResObj || radiusYResObj)) {
238             RectModel::GetInstance()->SetRadiusValue(radiusXValue, radiusYValue, radiusXResObj, radiusYResObj, i);
239         }
240         SetRadiusValue(shapeRect, radiusXValue, radiusYValue, i);
241     }
242 }
243 
SetRadiusValue(const RefPtr<ShapeRect> & shapeRect,const CalcDimension & radiusX,const CalcDimension & radiusY,int32_t index)244 void JSRect::SetRadiusValue(
245     const RefPtr<ShapeRect>& shapeRect, const CalcDimension& radiusX, const CalcDimension& radiusY, int32_t index)
246 {
247     if (shapeRect) {
248         RectModel::GetInstance()->SetShapeRectRadius(shapeRect, radiusX, radiusY, index);
249     } else {
250         RectModel::GetInstance()->SetRadiusValue(radiusX, radiusY, index);
251     }
252 }
253 
ObjectRadiusWidth(const JSCallbackInfo & info)254 void JSRect::ObjectRadiusWidth(const JSCallbackInfo& info)
255 {
256     info.ReturnSelf();
257     if (info.Length() < 1) {
258         return;
259     }
260     CalcDimension value;
261     if (!ParseJsDimensionVp(info[0], value)) {
262         return;
263     }
264     if (LessNotEqual(value.Value(), 0.0)) {
265         return;
266     }
267     auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
268     if (rect) {
269         rect->SetRadiusWidth(value);
270     }
271 }
272 
ObjectRadiusHeight(const JSCallbackInfo & info)273 void JSRect::ObjectRadiusHeight(const JSCallbackInfo& info)
274 {
275     info.ReturnSelf();
276     if (info.Length() < 1) {
277         return;
278     }
279     CalcDimension value;
280     if (!ParseJsDimensionVp(info[0], value)) {
281         return;
282     }
283     if (LessNotEqual(value.Value(), 0.0)) {
284         return;
285     }
286     auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
287     if (rect) {
288         rect->SetRadiusHeight(value);
289     }
290 }
291 
ObjectRadius(const JSCallbackInfo & info)292 void JSRect::ObjectRadius(const JSCallbackInfo& info)
293 {
294     info.ReturnSelf();
295     if (info.Length() < 1) {
296         return;
297     }
298     auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
299     if (!rect) {
300         return;
301     }
302     if (info[0]->IsNumber() || info[0]->IsString()) {
303         SetRadiusWithJsVal(rect, info[0]);
304     }
305     if (info[0]->IsArray()) {
306         SetRadiusWithArrayValue(rect, info[0]);
307     }
308 }
309 
ParseRectObjBelowApi12(const RefPtr<ShapeRect> & rect,const JSRef<JSObject> & obj)310 void JSRect::ParseRectObjBelowApi12(const RefPtr<ShapeRect>& rect, const JSRef<JSObject>& obj)
311 {
312     CalcDimension width;
313     CalcDimension height;
314     CalcDimension radiusWidth;
315     CalcDimension radiusHeight;
316     if (ParseJsDimensionVp(obj->GetProperty("width"), width) && width.IsValid()) {
317         rect->SetWidth(width);
318     }
319     if (ParseJsDimensionVp(obj->GetProperty("height"), height) && height.IsValid()) {
320         rect->SetHeight(height);
321     }
322     if (ParseJsDimensionVp(obj->GetProperty("radiusWidth"), radiusWidth) && radiusWidth.IsValid()) {
323         rect->SetRadiusWidth(radiusWidth);
324     }
325     if (ParseJsDimensionVp(obj->GetProperty("radiusHeight"), radiusHeight) && radiusHeight.IsValid()) {
326         rect->SetRadiusHeight(radiusHeight);
327     }
328 }
329 
ParseRectObjAboveApi12(const RefPtr<ShapeRect> & rect,const JSRef<JSObject> & obj)330 void JSRect::ParseRectObjAboveApi12(const RefPtr<ShapeRect>& rect, const JSRef<JSObject>& obj)
331 {
332     CalcDimension width;
333     CalcDimension height;
334     CalcDimension radiusWidth;
335     CalcDimension radiusHeight;
336     if (ParseJsDimensionVpNG(obj->GetProperty("width"), width) && width.IsValid()) {
337         rect->SetWidth(width);
338     }
339     if (ParseJsDimensionVpNG(obj->GetProperty("height"), height) && height.IsValid()) {
340         rect->SetHeight(height);
341     }
342     if (ParseJsDimensionVpNG(obj->GetProperty("radiusWidth"), radiusWidth) && radiusWidth.IsValid()) {
343         rect->SetRadiusWidth(radiusWidth);
344     }
345     if (ParseJsDimensionVpNG(obj->GetProperty("radiusHeight"), radiusHeight) && radiusHeight.IsValid()) {
346         rect->SetRadiusHeight(radiusHeight);
347     }
348 }
349 
ConstructorCallback(const JSCallbackInfo & info)350 void JSRect::ConstructorCallback(const JSCallbackInfo& info)
351 {
352     auto jsRect = AceType::MakeRefPtr<JSRect>();
353     auto rect = AceType::MakeRefPtr<ShapeRect>();
354     if (info.Length() > 0 && info[0]->IsObject()) {
355         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
356         if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
357             ParseRectObjBelowApi12(rect, obj);
358         } else {
359             ParseRectObjAboveApi12(rect, obj);
360         }
361         JSRef<JSVal> radius = obj->GetProperty("radius");
362         if (radius->IsNumber() || radius->IsString()) {
363             SetRadiusWithJsVal(rect, radius);
364         } else if (radius->IsArray()) {
365             SetRadiusWithArrayValue(rect, radius);
366         }
367         info.SetReturnValue(info.This());
368     }
369     jsRect->SetBasicShape(rect);
370     jsRect->IncRefCount();
371     info.SetReturnValue(AceType::RawPtr(jsRect));
372 }
373 
DestructorCallback(JSRect * jsRect)374 void JSRect::DestructorCallback(JSRect* jsRect)
375 {
376     if (jsRect != nullptr) {
377         jsRect->DecRefCount();
378     }
379 }
380 
JSBind(BindingTarget globalObj)381 void JSRect::JSBind(BindingTarget globalObj)
382 {
383     JSClass<JSRect>::Declare("Rect");
384     JSClass<JSRect>::StaticMethod("create", &JSRect::Create);
385     JSClass<JSRect>::StaticMethod("radiusWidth", &JSRect::JsRadiusWidth);
386     JSClass<JSRect>::StaticMethod("radiusHeight", &JSRect::JsRadiusHeight);
387     JSClass<JSRect>::StaticMethod("radius", &JSRect::SetRadius);
388 
389     JSClass<JSRect>::CustomMethod("width", &JSShapeAbstract::ObjectWidth);
390     JSClass<JSRect>::CustomMethod("height", &JSShapeAbstract::ObjectHeight);
391     JSClass<JSRect>::CustomMethod("size", &JSShapeAbstract::ObjectSize);
392     JSClass<JSRect>::CustomMethod("offset", &JSShapeAbstract::ObjectOffset);
393     JSClass<JSRect>::CustomMethod("radiusWidth", &JSRect::ObjectRadiusWidth);
394     JSClass<JSRect>::CustomMethod("radiusHeight", &JSRect::ObjectRadiusHeight);
395     JSClass<JSRect>::CustomMethod("radius", &JSRect::ObjectRadius);
396     JSClass<JSRect>::CustomMethod("fill", &JSShapeAbstract::ObjectFill);
397     JSClass<JSRect>::CustomMethod("position", &JSShapeAbstract::ObjectPosition);
398 
399     JSClass<JSRect>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
400     JSClass<JSRect>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
401     JSClass<JSRect>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
402     JSClass<JSRect>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
403     JSClass<JSRect>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
404 
405     JSClass<JSRect>::InheritAndBind<JSShapeAbstract>(
406         globalObj, JSRect::ConstructorCallback, JSRect::DestructorCallback);
407 }
408 
409 } // namespace OHOS::Ace::Framework
410