• 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 {
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         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
106         return;
107     }
108     SetRadiusWidth(info[0]);
109 }
110 
JsRadiusHeight(const JSCallbackInfo & info)111 void JSRect::JsRadiusHeight(const JSCallbackInfo& info)
112 {
113     if (info.Length() < 1) {
114         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
115         return;
116     }
117     SetRadiusHeight(info[0]);
118 }
119 
SetRadiusWidth(const JSRef<JSVal> & jsVal)120 void JSRect::SetRadiusWidth(const JSRef<JSVal>& jsVal)
121 {
122     CalcDimension value(0.0f);
123     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
124         if (!ParseJsDimensionVp(jsVal, value)) {
125             LOGW("value is invalid, use default value(0.0) instead.");
126         }
127     } else {
128         if (!ParseJsDimensionVpNG(jsVal, value)) {
129             LOGW("value is invalid, use default value(0.0) instead.");
130             value.SetValue(0.0f);
131         }
132     }
133     RectModel::GetInstance()->SetRadiusWidth(value);
134 }
135 
SetRadiusHeight(const JSRef<JSVal> & jsVal)136 void JSRect::SetRadiusHeight(const JSRef<JSVal>& jsVal)
137 {
138     CalcDimension value(0.0f);
139     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
140         if (!ParseJsDimensionVp(jsVal, value)) {
141             LOGW("value is invalid, use default value(0.0) instead.");
142         }
143     } else {
144         if (!ParseJsDimensionVpNG(jsVal, value)) {
145             LOGW("value is invalid, use default value(0.0) instead.");
146             value.SetValue(0.0f);
147         }
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         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
156         return;
157     }
158     if (info[0]->IsArray()) {
159         SetRadiusWithArrayValue(nullptr, info[0]);
160         info.SetReturnValue(info.This());
161         return;
162     }
163     if (info[0]->IsNumber() || info[0]->IsString() || info[0]->IsObject()) {
164         SetRadiusWithJsVal(nullptr, info[0]);
165         info.SetReturnValue(info.This());
166     }
167 }
168 
SetRadiusWithJsVal(const RefPtr<ShapeRect> & shapeRect,const JSRef<JSVal> & jsVal)169 void JSRect::SetRadiusWithJsVal(const RefPtr<ShapeRect>& shapeRect, const JSRef<JSVal>& jsVal)
170 {
171     CalcDimension value(0.0f);
172     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
173         if (!ParseJsDimensionVp(jsVal, value)) {
174             LOGW("value is invalid, use default value(0.0) instead.");
175         }
176     } else {
177         if (!ParseJsDimensionVpNG(jsVal, value)) {
178             LOGW("value is invalid, use default value(0.0) instead.");
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     RectModel::GetInstance()->SetRadiusWidth(value);
189     RectModel::GetInstance()->SetRadiusHeight(value);
190 }
191 
SetRadiusWithArrayValue(const RefPtr<ShapeRect> & shapeRect,const JSRef<JSVal> & jsVal)192 void JSRect::SetRadiusWithArrayValue(const RefPtr<ShapeRect>& shapeRect, const JSRef<JSVal>& jsVal)
193 {
194     if (!jsVal->IsArray()) {
195         LOGE("The arg is not array.");
196         return;
197     }
198     JSRef<JSArray> array = JSRef<JSArray>::Cast(jsVal);
199     auto length = static_cast<int32_t>(array->Length());
200     if (length <= 0) {
201         LOGE("info is invalid");
202         return;
203     }
204     length = std::min(length, 4);
205     for (int32_t i = 0; i < length; i++) {
206         JSRef<JSVal> radiusItem = array->GetValueAt(i);
207         if (!radiusItem->IsArray()) {
208             break;
209         }
210         JSRef<JSArray> radiusArray = JSRef<JSArray>::Cast(radiusItem);
211         if (radiusArray->Length() != 2) {
212             break;
213         }
214         JSRef<JSVal> radiusX = radiusArray->GetValueAt(0);
215         JSRef<JSVal> radiusY = radiusArray->GetValueAt(1);
216         CalcDimension radiusXValue(0.0f);
217         CalcDimension radiusYValue(0.0f);
218         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
219             if (!ParseJsDimensionVp(radiusX, radiusXValue) || !ParseJsDimensionVp(radiusY, radiusYValue)) {
220                 LOGW("value is invalid, use default value(0.0) instead.");
221             }
222         } else {
223             if (!ParseJsDimensionVpNG(radiusX, radiusXValue)) {
224                 LOGW("radiusX is invalid, use default value(0.0) instead.");
225                 radiusXValue.SetValue(0.0f);
226             }
227             if (!ParseJsDimensionVpNG(radiusY, radiusYValue)) {
228                 LOGW("radiusY is invalid, use default value(0.0) instead.");
229                 radiusYValue.SetValue(0.0f);
230             }
231         }
232         SetRadiusValue(shapeRect, radiusXValue, radiusYValue, i);
233     }
234 }
235 
SetRadiusValue(const RefPtr<ShapeRect> & shapeRect,const CalcDimension & radiusX,const CalcDimension & radiusY,int32_t index)236 void JSRect::SetRadiusValue(
237     const RefPtr<ShapeRect>& shapeRect, const CalcDimension& radiusX, const CalcDimension& radiusY, int32_t index)
238 {
239     if (shapeRect) {
240         RectModel::GetInstance()->SetShapeRectRadius(shapeRect, radiusX, radiusY, index);
241     } else {
242         RectModel::GetInstance()->SetRadiusValue(radiusX, radiusY, index);
243     }
244 }
245 
ObjectRadiusWidth(const JSCallbackInfo & info)246 void JSRect::ObjectRadiusWidth(const JSCallbackInfo& info)
247 {
248     info.ReturnSelf();
249     if (info.Length() < 1) {
250         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
251         return;
252     }
253     CalcDimension value;
254     if (!ParseJsDimensionVp(info[0], value)) {
255         return;
256     }
257     if (LessNotEqual(value.Value(), 0.0)) {
258         LOGE("Value is less than zero");
259         return;
260     }
261     auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
262     if (rect) {
263         rect->SetRadiusWidth(value);
264     }
265 }
266 
ObjectRadiusHeight(const JSCallbackInfo & info)267 void JSRect::ObjectRadiusHeight(const JSCallbackInfo& info)
268 {
269     info.ReturnSelf();
270     if (info.Length() < 1) {
271         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
272         return;
273     }
274     CalcDimension value;
275     if (!ParseJsDimensionVp(info[0], value)) {
276         return;
277     }
278     if (LessNotEqual(value.Value(), 0.0)) {
279         LOGE("Value is less than zero");
280         return;
281     }
282     auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
283     if (rect) {
284         rect->SetRadiusHeight(value);
285     }
286 }
287 
ObjectRadius(const JSCallbackInfo & info)288 void JSRect::ObjectRadius(const JSCallbackInfo& info)
289 {
290     info.ReturnSelf();
291     if (info.Length() < 1) {
292         LOGE("arg is invalid");
293         return;
294     }
295     auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
296     if (!rect) {
297         LOGE("rect is null");
298         return;
299     }
300     if (info[0]->IsNumber() || info[0]->IsString()) {
301         SetRadiusWithJsVal(rect, info[0]);
302     }
303     if (info[0]->IsArray()) {
304         SetRadiusWithArrayValue(rect, info[0]);
305     }
306 }
307 
ConstructorCallback(const JSCallbackInfo & info)308 void JSRect::ConstructorCallback(const JSCallbackInfo& info)
309 {
310     auto jsRect = AceType::MakeRefPtr<JSRect>();
311     auto rect = AceType::MakeRefPtr<ShapeRect>();
312     if (info.Length() > 0 && info[0]->IsObject()) {
313         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
314         CalcDimension width;
315         if (ParseJsDimensionVp(obj->GetProperty("width"), width) && width.IsValid()) {
316             rect->SetWidth(width);
317         }
318         CalcDimension height;
319         if (ParseJsDimensionVp(obj->GetProperty("height"), height) && height.IsValid()) {
320             rect->SetHeight(height);
321         }
322         CalcDimension radiusWidth;
323         if (ParseJsDimensionVp(obj->GetProperty("radiusWidth"), radiusWidth) && radiusWidth.IsValid()) {
324             rect->SetRadiusWidth(radiusWidth);
325         }
326         CalcDimension radiusHeight;
327         if (ParseJsDimensionVp(obj->GetProperty("radiusHeight"), radiusHeight) && radiusHeight.IsValid()) {
328             rect->SetRadiusHeight(radiusHeight);
329         }
330         JSRef<JSVal> radius = obj->GetProperty("radius");
331         if (radius->IsNumber() || radius->IsString()) {
332             SetRadiusWithJsVal(rect, radius);
333         }
334         if (radius->IsArray()) {
335             SetRadiusWithArrayValue(rect, radius);
336         }
337         info.SetReturnValue(info.This());
338     }
339     jsRect->SetBasicShape(rect);
340     jsRect->IncRefCount();
341     info.SetReturnValue(AceType::RawPtr(jsRect));
342 }
343 
DestructorCallback(JSRect * jsRect)344 void JSRect::DestructorCallback(JSRect* jsRect)
345 {
346     if (jsRect != nullptr) {
347         jsRect->DecRefCount();
348     }
349 }
350 
JSBind(BindingTarget globalObj)351 void JSRect::JSBind(BindingTarget globalObj)
352 {
353     JSClass<JSRect>::Declare("Rect");
354     JSClass<JSRect>::StaticMethod("create", &JSRect::Create);
355     JSClass<JSRect>::StaticMethod("radiusWidth", &JSRect::JsRadiusWidth);
356     JSClass<JSRect>::StaticMethod("radiusHeight", &JSRect::JsRadiusHeight);
357     JSClass<JSRect>::StaticMethod("radius", &JSRect::SetRadius);
358 
359     JSClass<JSRect>::CustomMethod("width", &JSShapeAbstract::ObjectWidth);
360     JSClass<JSRect>::CustomMethod("height", &JSShapeAbstract::ObjectHeight);
361     JSClass<JSRect>::CustomMethod("size", &JSShapeAbstract::ObjectSize);
362     JSClass<JSRect>::CustomMethod("offset", &JSShapeAbstract::ObjectOffset);
363     JSClass<JSRect>::CustomMethod("radiusWidth", &JSRect::ObjectRadiusWidth);
364     JSClass<JSRect>::CustomMethod("radiusHeight", &JSRect::ObjectRadiusHeight);
365     JSClass<JSRect>::CustomMethod("radius", &JSRect::ObjectRadius);
366     JSClass<JSRect>::CustomMethod("fill", &JSShapeAbstract::ObjectFill);
367     JSClass<JSRect>::CustomMethod("position", &JSShapeAbstract::ObjectPosition);
368 
369     JSClass<JSRect>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
370     JSClass<JSRect>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
371     JSClass<JSRect>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
372     JSClass<JSRect>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
373     JSClass<JSRect>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
374 
375     JSClass<JSRect>::InheritAndBind<JSShapeAbstract>(
376         globalObj, JSRect::ConstructorCallback, JSRect::DestructorCallback);
377 }
378 
379 } // namespace OHOS::Ace::Framework
380