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