1 /*
2 * Copyright (c) 2023 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 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_data_panel_bridge.h"
16
17 #include "base/geometry/dimension.h"
18 #include "bridge/declarative_frontend/jsview/js_linear_gradient.h"
19 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
20 #include "core/components/common/properties/color.h"
21 #include "core/components/data_panel/data_panel_theme.h"
22 #include "core/components/divider/divider_theme.h"
23 #include "core/components_ng/pattern/gauge/gauge_paint_property.h"
24 #include "frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_utils.h"
25
26 #include "core/components_ng/base/frame_node.h"
27 #include "core/components_ng/pattern/data_panel/data_panel_model_ng.h"
28
29 namespace {
30 const char* DATA_PANEL_NODEPTR_OF_UINODE = "nodePtr_";
31 } // namespace
32 namespace OHOS::Ace::NG {
33 namespace {
34 constexpr int32_t NUM_0 = 0;
35 constexpr int32_t NUM_1 = 1;
36 constexpr int32_t NUM_2 = 2;
37
ConvertThemeColor(std::vector<OHOS::Ace::NG::Gradient> & colors)38 void ConvertThemeColor(std::vector<OHOS::Ace::NG::Gradient>& colors)
39 {
40 RefPtr<DataPanelTheme> theme = ArkTSUtils::GetTheme<DataPanelTheme>();
41 auto themeColors = theme->GetColorsArray();
42 for (const auto& item : themeColors) {
43 OHOS::Ace::NG::Gradient gradient;
44 OHOS::Ace::NG::GradientColor gradientColorStart;
45 gradientColorStart.SetLinearColor(LinearColor(item.first));
46 gradientColorStart.SetDimension(Dimension(0.0));
47 gradient.AddColor(gradientColorStart);
48 OHOS::Ace::NG::GradientColor gradientColorEnd;
49 gradientColorEnd.SetLinearColor(LinearColor(item.second));
50 gradientColorEnd.SetDimension(Dimension(1.0));
51 gradient.AddColor(gradientColorEnd);
52 colors.emplace_back(gradient);
53 }
54 }
55
ConvertResourceColor(const EcmaVM * vm,const Local<JSValueRef> & item,OHOS::Ace::NG::Gradient & gradient)56 bool ConvertResourceColor(const EcmaVM* vm, const Local<JSValueRef>& item, OHOS::Ace::NG::Gradient& gradient)
57 {
58 Color color;
59 if (!ArkTSUtils::ParseJsColorAlpha(vm, item, color)) {
60 return false;
61 }
62 OHOS::Ace::NG::GradientColor gradientColorStart;
63 gradientColorStart.SetLinearColor(LinearColor(color));
64 gradientColorStart.SetDimension(Dimension(0.0));
65 gradient.AddColor(gradientColorStart);
66 OHOS::Ace::NG::GradientColor gradientColorEnd;
67 gradientColorEnd.SetLinearColor(LinearColor(color));
68 gradientColorEnd.SetDimension(Dimension(1.0));
69 gradient.AddColor(gradientColorEnd);
70 return true;
71 }
72
ConvertGradientColor(const EcmaVM * vm,const Local<JSValueRef> & itemParam,OHOS::Ace::NG::Gradient & gradient)73 bool ConvertGradientColor(const EcmaVM* vm, const Local<JSValueRef>& itemParam, OHOS::Ace::NG::Gradient& gradient)
74 {
75 if (!itemParam->IsObject(vm)) {
76 return ConvertResourceColor(vm, itemParam, gradient);
77 }
78 Framework::JSLinearGradient* jsLinearGradient =
79 static_cast<Framework::JSLinearGradient*>(itemParam->ToObject(vm)->GetNativePointerField(vm, 0));
80 if (!jsLinearGradient) {
81 return ConvertResourceColor(vm, itemParam, gradient);
82 }
83
84 size_t colorLength = jsLinearGradient->GetGradient().size();
85 if (colorLength == 0) {
86 return false;
87 }
88 for (size_t colorIndex = 0; colorIndex < colorLength; ++colorIndex) {
89 OHOS::Ace::NG::GradientColor gradientColor;
90 gradientColor.SetLinearColor(LinearColor(jsLinearGradient->GetGradient().at(colorIndex).first));
91 gradientColor.SetDimension(jsLinearGradient->GetGradient().at(colorIndex).second);
92 gradient.AddColor(gradientColor);
93 }
94 return true;
95 }
96
SetTrackShadowObject(ArkUINodeHandle nativeNode,std::vector<OHOS::Ace::NG::Gradient> & shadowColors,double radius,double offsetX,double offsetY)97 void SetTrackShadowObject(ArkUINodeHandle nativeNode, std::vector<OHOS::Ace::NG::Gradient>& shadowColors,
98 double radius, double offsetX, double offsetY)
99 {
100 ArkUIGradientType gradient;
101 gradient.length = shadowColors.size();
102 auto linearLength = std::make_unique<uint32_t[]>(shadowColors.size());
103 std::vector<uint32_t> allColor;
104 std::vector<ArkUILengthType> allOffset;
105 for (uint32_t i = 0; i < shadowColors.size(); i++) {
106 linearLength[i] = shadowColors[i].GetColors().size();
107 for (uint32_t j = 0; j < linearLength[i]; j++) {
108 allColor.emplace_back(shadowColors[i].GetColors()[j].GetLinearColor().GetValue());
109 allOffset.emplace_back(ArkUILengthType { .number = shadowColors[i].GetColors()[j].GetDimension().Value(),
110 .unit = static_cast<int8_t>(shadowColors[i].GetColors()[j].GetDimension().Unit()) });
111 }
112 }
113 gradient.color = &(*allColor.begin());
114 gradient.offset = &(*allOffset.begin());
115 gradient.gradientLength = linearLength.get();
116 GetArkUINodeModifiers()->getDataPanelModifier()->setTrackShadow(nativeNode, &gradient, radius, offsetX, offsetY);
117 }
118 } // namespace
119
SetValueColors(ArkUIRuntimeCallInfo * runtimeCallInfo)120 ArkUINativeModuleValue DataPanelBridge::SetValueColors(ArkUIRuntimeCallInfo* runtimeCallInfo)
121 {
122 EcmaVM* vm = runtimeCallInfo->GetVM();
123 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
124 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
125 Local<JSValueRef> colors = runtimeCallInfo->GetCallArgRef(NUM_1);
126 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
127
128 std::vector<OHOS::Ace::NG::Gradient> shadowColors;
129 if (!colors.IsEmpty() && colors->IsArray(vm)) {
130 auto colorsArray = panda::CopyableGlobal<panda::ArrayRef>(vm, colors);
131 for (size_t i = 0; i < colorsArray->Length(vm); ++i) {
132 auto item = colorsArray->GetValueAt(vm, colors, i);
133 OHOS::Ace::NG::Gradient gradient;
134 if (!ConvertGradientColor(vm, item, gradient)) {
135 shadowColors.clear();
136 ConvertThemeColor(shadowColors);
137 break;
138 }
139 shadowColors.emplace_back(gradient);
140 }
141 }
142 ArkUIGradientType gradient;
143 gradient.length = shadowColors.size();
144 auto linearLength = std::make_unique<uint32_t[]>(shadowColors.size());
145 std::vector<uint32_t> allColor;
146 std::vector<ArkUILengthType> allOffset;
147 for (uint32_t i = 0; i < shadowColors.size(); i++) {
148 linearLength[i] = shadowColors[i].GetColors().size();
149 for (uint32_t j = 0; j < linearLength[i]; j++) {
150 allColor.emplace_back(shadowColors[i].GetColors()[j].GetLinearColor().GetValue());
151 allOffset.emplace_back(ArkUILengthType { .number = shadowColors[i].GetColors()[j].GetDimension().Value(),
152 .unit = static_cast<int8_t>(shadowColors[i].GetColors()[j].GetDimension().Unit()) });
153 }
154 }
155 gradient.color = &(*allColor.begin());
156 gradient.offset = &(*allOffset.begin());
157 gradient.gradientLength = linearLength.get();
158 GetArkUINodeModifiers()->getDataPanelModifier()->setValueColors(nativeNode, &gradient);
159 return panda::JSValueRef::Undefined(vm);
160 }
161
ResetValueColors(ArkUIRuntimeCallInfo * runtimeCallInfo)162 ArkUINativeModuleValue DataPanelBridge::ResetValueColors(ArkUIRuntimeCallInfo* runtimeCallInfo)
163 {
164 EcmaVM* vm = runtimeCallInfo->GetVM();
165 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
166 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
167 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
168 GetArkUINodeModifiers()->getDataPanelModifier()->resetValueColors(nativeNode);
169 return panda::JSValueRef::Undefined(vm);
170 }
171
SetTrackShadow(ArkUIRuntimeCallInfo * runtimeCallInfo)172 ArkUINativeModuleValue DataPanelBridge::SetTrackShadow(ArkUIRuntimeCallInfo* runtimeCallInfo)
173 {
174 EcmaVM* vm = runtimeCallInfo->GetVM();
175 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
176 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
177 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(NUM_1);
178 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
179 if (secondArg->IsNull()) {
180 GetArkUINodeModifiers()->getDataPanelModifier()->setNullTrackShadow(nativeNode);
181 return panda::JSValueRef::Undefined(vm);
182 }
183 if (!secondArg->IsObject(vm)) {
184 GetArkUINodeModifiers()->getDataPanelModifier()->resetTrackShadow(nativeNode);
185 return panda::JSValueRef::Undefined(vm);
186 }
187 auto obj = secondArg->ToObject(vm);
188 auto jsRadius = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "radius"));
189 auto jsOffsetX = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "offsetX"));
190 auto jsOffsetY = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "offsetY"));
191 RefPtr<DataPanelTheme> theme = ArkTSUtils::GetTheme<DataPanelTheme>();
192 double radius = 0.0;
193 if (!ArkTSUtils::ParseJsDouble(vm, jsRadius, radius) || NonPositive(radius)) {
194 radius = theme->GetTrackShadowRadius().ConvertToVp();
195 }
196
197 double offsetX = 0.0;
198 if (!ArkTSUtils::ParseJsDouble(vm, jsOffsetX, offsetX)) {
199 offsetX = theme->GetTrackShadowOffsetX().ConvertToVp();
200 }
201
202 double offsetY = 0.0;
203 if (!ArkTSUtils::ParseJsDouble(vm, jsOffsetY, offsetY)) {
204 offsetY = theme->GetTrackShadowOffsetY().ConvertToVp();
205 }
206
207 auto colors = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "colors"));
208 std::vector<OHOS::Ace::NG::Gradient> shadowColors;
209 ConvertThemeColor(shadowColors);
210 if (!colors.IsEmpty() && colors->IsArray(vm)) {
211 shadowColors.clear();
212 auto colorsArray = panda::CopyableGlobal<panda::ArrayRef>(vm, colors);
213 for (size_t i = 0; i < colorsArray->Length(vm); ++i) {
214 auto item = colorsArray->GetValueAt(vm, colors, i);
215 OHOS::Ace::NG::Gradient gradient;
216 if (!ConvertGradientColor(vm, item, gradient)) {
217 shadowColors.clear();
218 ConvertThemeColor(shadowColors);
219 break;
220 }
221 shadowColors.emplace_back(gradient);
222 }
223 }
224 SetTrackShadowObject(nativeNode, shadowColors, radius, offsetX, offsetY);
225 return panda::JSValueRef::Undefined(vm);
226 }
227
ResetTrackShadow(ArkUIRuntimeCallInfo * runtimeCallInfo)228 ArkUINativeModuleValue DataPanelBridge::ResetTrackShadow(ArkUIRuntimeCallInfo* runtimeCallInfo)
229 {
230 EcmaVM* vm = runtimeCallInfo->GetVM();
231 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
232 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
233 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
234 GetArkUINodeModifiers()->getDataPanelModifier()->resetTrackShadow(nativeNode);
235 return panda::JSValueRef::Undefined(vm);
236 }
SetCloseEffect(ArkUIRuntimeCallInfo * runtimeCallInfo)237 ArkUINativeModuleValue DataPanelBridge::SetCloseEffect(ArkUIRuntimeCallInfo* runtimeCallInfo)
238 {
239 EcmaVM* vm = runtimeCallInfo->GetVM();
240 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
241 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
242 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(1);
243 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
244 bool boolValue = secondArg->ToBoolean(vm)->Value();
245 GetArkUINodeModifiers()->getDataPanelModifier()->setCloseEffect(nativeNode, boolValue);
246 return panda::JSValueRef::Undefined(vm);
247 }
248
ResetCloseEffect(ArkUIRuntimeCallInfo * runtimeCallInfo)249 ArkUINativeModuleValue DataPanelBridge::ResetCloseEffect(ArkUIRuntimeCallInfo* runtimeCallInfo)
250 {
251 EcmaVM* vm = runtimeCallInfo->GetVM();
252 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
253 Local<JSValueRef> nativeNodeArg = runtimeCallInfo->GetCallArgRef(0);
254 auto nativeNode = nodePtr(nativeNodeArg->ToNativePointer(vm)->Value());
255 GetArkUINodeModifiers()->getDataPanelModifier()->resetCloseEffect(nativeNode);
256 return panda::JSValueRef::Undefined(vm);
257 }
258
SetDataPanelTrackBackgroundColor(ArkUIRuntimeCallInfo * runtimeCallInfo)259 ArkUINativeModuleValue DataPanelBridge::SetDataPanelTrackBackgroundColor(ArkUIRuntimeCallInfo* runtimeCallInfo)
260 {
261 EcmaVM* vm = runtimeCallInfo->GetVM();
262 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
263 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
264 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(1);
265 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
266
267 Color color;
268 if (!ArkTSUtils::ParseJsColorAlpha(vm, secondArg, color)) {
269 RefPtr<DataPanelTheme> theme = ArkTSUtils::GetTheme<DataPanelTheme>();
270 color = theme->GetBackgroundColor();
271 }
272 GetArkUINodeModifiers()->getDataPanelModifier()->setDataPanelTrackBackgroundColor(nativeNode, color.GetValue());
273 return panda::JSValueRef::Undefined(vm);
274 }
275
ResetDataPanelTrackBackgroundColor(ArkUIRuntimeCallInfo * runtimeCallInfo)276 ArkUINativeModuleValue DataPanelBridge::ResetDataPanelTrackBackgroundColor(ArkUIRuntimeCallInfo* runtimeCallInfo)
277 {
278 EcmaVM* vm = runtimeCallInfo->GetVM();
279 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
280 Local<JSValueRef> nativeNodeArg = runtimeCallInfo->GetCallArgRef(0);
281 auto nativeNode = nodePtr(nativeNodeArg->ToNativePointer(vm)->Value());
282 GetArkUINodeModifiers()->getDataPanelModifier()->resetDataPanelTrackBackgroundColor(nativeNode);
283 return panda::JSValueRef::Undefined(vm);
284 }
285
SetDataPanelStrokeWidth(ArkUIRuntimeCallInfo * runtimeCallInfo)286 ArkUINativeModuleValue DataPanelBridge::SetDataPanelStrokeWidth(ArkUIRuntimeCallInfo* runtimeCallInfo)
287 {
288 EcmaVM* vm = runtimeCallInfo->GetVM();
289 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
290 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
291 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
292 Local<JSValueRef> jsValue = runtimeCallInfo->GetCallArgRef(1);
293
294 RefPtr<DataPanelTheme> theme = ArkTSUtils::GetTheme<DataPanelTheme>();
295 CalcDimension strokeWidth;
296
297 if (!ArkTSUtils::ParseJsDimensionVpNG(vm, jsValue, strokeWidth)) {
298 strokeWidth = theme->GetThickness();
299 }
300
301 if (jsValue->IsString(vm) && (jsValue->ToString(vm)->ToString(vm).empty() ||
302 !StringUtils::StringToDimensionWithUnitNG(jsValue->ToString(vm)->ToString(vm), strokeWidth))) {
303 strokeWidth = theme->GetThickness();
304 }
305
306 if (strokeWidth.IsNegative() || strokeWidth.Unit() == DimensionUnit::PERCENT) {
307 strokeWidth = theme->GetThickness();
308 }
309
310 GetArkUINodeModifiers()->getDataPanelModifier()->setDataPanelStrokeWidth(
311 nativeNode, strokeWidth.Value(), static_cast<int32_t>(strokeWidth.Unit()));
312 return panda::JSValueRef::Undefined(vm);
313 }
314
ResetDataPanelStrokeWidth(ArkUIRuntimeCallInfo * runtimeCallInfo)315 ArkUINativeModuleValue DataPanelBridge::ResetDataPanelStrokeWidth(ArkUIRuntimeCallInfo* runtimeCallInfo)
316 {
317 EcmaVM* vm = runtimeCallInfo->GetVM();
318 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
319 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
320 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
321 GetArkUINodeModifiers()->getDataPanelModifier()->resetDataPanelStrokeWidth(nativeNode);
322 return panda::JSValueRef::Undefined(vm);
323 }
324
SetContentModifierBuilder(ArkUIRuntimeCallInfo * runtimeCallInfo)325 ArkUINativeModuleValue DataPanelBridge::SetContentModifierBuilder(ArkUIRuntimeCallInfo* runtimeCallInfo)
326 {
327 EcmaVM* vm = runtimeCallInfo->GetVM();
328 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
329 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
330 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(NUM_1);
331 void* nativeNode = firstArg->ToNativePointer(vm)->Value();
332 auto* frameNode = reinterpret_cast<FrameNode*>(nativeNode);
333 if (!secondArg->IsObject(vm)) {
334 DataPanelModelNG::SetBuilderFunc(frameNode, nullptr);
335 return panda::JSValueRef::Undefined(vm);
336 }
337 panda::CopyableGlobal<panda::ObjectRef> globalObj(vm, secondArg);
338 auto containerId = Container::CurrentId();
339 DataPanelModelNG::SetBuilderFunc(frameNode,
340 [vm, frameNode, globalObj = std::move(globalObj), containerId](
341 DataPanelConfiguration config) -> RefPtr<FrameNode> {
342 ContainerScope scope(containerId);
343 CHECK_NULL_RETURN(Container::Current(), nullptr);
344 CHECK_NULL_RETURN(Container::Current()->GetFrontend(), nullptr);
345 auto context = NapiValueToLocalValue(Container::Current()->GetFrontend()->GetContextValue());
346 auto obj = panda::ObjectRef::New(vm);
347 auto valueArray = panda::ArrayRef::New(vm, config.values_.size());
348 for (uint32_t i = 0; i < config.values_.size(); ++i) {
349 panda::ArrayRef::SetValueAt(vm, valueArray, i, panda::NumberRef::New(vm, config.values_[i]));
350 }
351 obj->Set(vm, panda::StringRef::NewFromUtf8(vm, "values"), valueArray);
352 obj->Set(vm, panda::StringRef::NewFromUtf8(vm, "maxValue"), panda::NumberRef::New(vm, config.maxValue_));
353 obj->SetNativePointerFieldCount(vm, 1);
354 obj->SetNativePointerField(vm, 0, static_cast<void*>(frameNode));
355 panda::Local<panda::JSValueRef> params[NUM_2] = { context, obj };
356 LocalScope pandaScope(vm);
357 panda::TryCatch trycatch(vm);
358 auto jsObject = globalObj.ToLocal();
359 auto makeFunc = jsObject->Get(vm, panda::StringRef::NewFromUtf8(vm, "makeContentModifierNode"));
360 if (!makeFunc->IsFunction(vm)) { return nullptr; }
361 panda::Local<panda::FunctionRef> func = makeFunc;
362 auto result = func->Call(vm, jsObject, params, 2);
363 JSNApi::ExecutePendingJob(vm);
364 if (result.IsEmpty() || trycatch.HasCaught() || !result->IsObject(vm)) { return nullptr; }
365 auto resultObj = result->ToObject(vm);
366 panda::Local<panda::JSValueRef> nodeptr = resultObj->Get(vm,
367 panda::StringRef::NewFromUtf8(vm, DATA_PANEL_NODEPTR_OF_UINODE));
368 if (nodeptr.IsEmpty() || nodeptr->IsUndefined() || nodeptr->IsNull()) { return nullptr; }
369 auto* node = nodeptr->ToNativePointer(vm)->Value();
370 auto* frameNode = reinterpret_cast<FrameNode*>(node);
371 CHECK_NULL_RETURN(frameNode, nullptr);
372 return AceType::Claim(frameNode);
373 });
374 return panda::JSValueRef::Undefined(vm);
375 }
376 } // namespace OHOS::Ace::NG
377