1 /*
2 * Copyright (c) 2024 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_linear_indicator.h"
17
18 #include "base/log/ace_scoring_log.h"
19 #include "core/common/container.h"
20 #include "core/components_ng/base/view_abstract_model.h"
21 #include "core/components_ng/pattern/linear_indicator/linear_indicator_model.h"
22 #include "core/components_ng/pattern/linear_indicator/linear_indicator_model_ng.h"
23 #include "core/components_ng/pattern/linear_indicator/linear_indicator_theme.h"
24 #include "frameworks/bridge/declarative_frontend/jsview/js_linear_indicator_controller.h"
25
26 namespace OHOS::Ace {
27
28 std::unique_ptr<LinearIndicatorModel> LinearIndicatorModel::instance_ = nullptr;
29
GetInstance()30 LinearIndicatorModel* LinearIndicatorModel::GetInstance()
31 {
32 if (!instance_) {
33 instance_.reset(new NG::LinearIndicatorModelNG());
34 }
35 return instance_.get();
36 }
37
38 } // namespace OHOS::Ace
39
40 namespace OHOS::Ace::Framework {
41
Create(const JSCallbackInfo & info)42 void JSLinearIndicator::Create(const JSCallbackInfo& info)
43 {
44 const int32_t length = info.Length();
45 auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
46 CHECK_NULL_VOID(pipeline);
47 auto theme = pipeline->GetThemeManager()->GetTheme<NG::LinearIndicatorTheme>();
48 CHECK_NULL_VOID(theme);
49 int32_t progressCount = theme->GetDefaultProgressCount();
50 int32_t defaultProgressMin = theme->GetDefaultProgressMin();
51
52 if (length > 0) {
53 auto arg0 = info[0];
54 if (arg0->IsNumber()) {
55 progressCount = arg0->ToNumber<int32_t>();
56 if (progressCount < defaultProgressMin) {
57 progressCount = defaultProgressMin;
58 }
59 }
60 }
61 RefPtr<NG::LinearIndicatorController> controller = LinearIndicatorModel::GetInstance()->Create(progressCount);
62 if (length > 1) {
63 auto arg1 = info[1];
64 if (arg1->IsObject()) {
65 auto* jsController = JSRef<JSObject>::Cast(arg1)->Unwrap<JSLinearIndicatorController>();
66 if (jsController) {
67 jsController->SetController(controller);
68 }
69 }
70 }
71 }
72
SetStyle(const JSCallbackInfo & info)73 void JSLinearIndicator::SetStyle(const JSCallbackInfo& info)
74 {
75 if (info.Length() == 0) {
76 return;
77 }
78 auto arg0 = info[0];
79 if (!arg0->IsObject()) {
80 return;
81 }
82 auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
83 CHECK_NULL_VOID(pipeline);
84 auto theme = pipeline->GetThemeManager()->GetTheme<NG::LinearIndicatorTheme>();
85 CHECK_NULL_VOID(theme);
86 auto paramObject = JSRef<JSObject>::Cast(arg0);
87 SetSpace(paramObject, theme);
88 SetStrokeWidth(paramObject, theme);
89 SetStrokeRadius(paramObject, theme);
90 SetTrackBackgroundColor(paramObject, theme);
91 SetTrackColor(paramObject, theme);
92 }
93
Loop(const JSCallbackInfo & info)94 void JSLinearIndicator::Loop(const JSCallbackInfo& info)
95 {
96 auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
97 CHECK_NULL_VOID(pipeline);
98 auto theme = pipeline->GetThemeManager()->GetTheme<NG::LinearIndicatorTheme>();
99 CHECK_NULL_VOID(theme);
100 bool value = theme->GetDefaultLoop();
101 if (info.Length() > 0) {
102 auto arg0 = info[0];
103 if (arg0->IsBoolean()) {
104 value = arg0->ToBoolean();
105 }
106 }
107 LinearIndicatorModel::GetInstance()->Loop(value);
108 }
109
OnChange(const JSCallbackInfo & info)110 void JSLinearIndicator::OnChange(const JSCallbackInfo& info)
111 {
112 if ((info.Length() == 0)) {
113 return;
114 }
115 auto arg0 = info[0];
116 if (!arg0->IsFunction()) {
117 return;
118 }
119
120 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(arg0));
121 auto onChangeCallback = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](
122 int32_t index, float progress) {
123 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
124 ACE_SCORING_EVENT("LinearIndicator::onChange");
125 JSRef<JSVal> params[2] = { JSRef<JSVal>::Make(ToJSValue(index)), JSRef<JSVal>::Make(ToJSValue(progress)) };
126 func->ExecuteJS(2, params);
127 };
128 LinearIndicatorModel::GetInstance()->OnChange(std::move(onChangeCallback));
129 }
130
JSBind(BindingTarget globalObj)131 void JSLinearIndicator::JSBind(BindingTarget globalObj)
132 {
133 JSClass<JSLinearIndicator>::Declare("LinearIndicator");
134 MethodOptions opt = MethodOptions::NONE;
135 JSClass<JSLinearIndicator>::StaticMethod("create", &JSLinearIndicator::Create, opt);
136 JSClass<JSLinearIndicator>::StaticMethod("indicatorStyle", &JSLinearIndicator::SetStyle, opt);
137 JSClass<JSLinearIndicator>::StaticMethod("indicatorLoop", &JSLinearIndicator::Loop, opt);
138 JSClass<JSLinearIndicator>::StaticMethod("onChange", &JSLinearIndicator::OnChange, opt);
139 JSClass<JSLinearIndicator>::StaticMethod("height", &JSLinearIndicator::JsHeight, opt);
140 JSClass<JSLinearIndicator>::StaticMethod("padding", &JSLinearIndicator::JsPadding, opt);
141 JSClass<JSLinearIndicator>::StaticMethod("paddingLeft", &JSLinearIndicator::SetPaddingLeft, opt);
142 JSClass<JSLinearIndicator>::StaticMethod("paddingRight", &JSLinearIndicator::SetPaddingRight, opt);
143 JSClass<JSViewAbstract>::StaticMethod("paddingTop", &JSLinearIndicator::JsIgnore, opt);
144 JSClass<JSViewAbstract>::StaticMethod("paddingBottom", &JSLinearIndicator::JsIgnore, opt);
145 JSClass<JSLinearIndicator>::Inherit<JSViewAbstract>();
146 JSClass<JSLinearIndicator>::Inherit<JSInteractableView>();
147 JSClass<JSLinearIndicator>::Bind<>(globalObj);
148 }
149
SetSpace(const JSRef<JSObject> & paramObject,const RefPtr<NG::LinearIndicatorTheme> & theme)150 void JSLinearIndicator::SetSpace(const JSRef<JSObject>& paramObject, const RefPtr<NG::LinearIndicatorTheme>& theme)
151 {
152 CalcDimension spaceDimension;
153 CalcDimension defaultSpace = theme->GetDefaultSpace();
154 auto space = paramObject->GetProperty("space");
155 if (space->IsUndefined() || space->IsNull() || !ParseLengthMetricsToDimension(space, spaceDimension)) {
156 spaceDimension = defaultSpace;
157 }
158 if (LessNotEqual(spaceDimension.Value(), 0.0f) || spaceDimension.Unit() == DimensionUnit::PERCENT) {
159 spaceDimension = defaultSpace;
160 }
161 LinearIndicatorModel::GetInstance()->SetSpace(spaceDimension);
162 }
163
SetStrokeWidth(const JSRef<JSObject> & paramObject,const RefPtr<NG::LinearIndicatorTheme> & theme)164 void JSLinearIndicator::SetStrokeWidth(
165 const JSRef<JSObject>& paramObject, const RefPtr<NG::LinearIndicatorTheme>& theme)
166 {
167 CalcDimension strokeWidthDimension;
168 CalcDimension defaultStrokeWidth = theme->GetDefaultStrokeWidth();
169 CalcDimension defaultStrokeWidthMin = theme->GetDefaultStrokeWidthMin();
170 auto strokeWidth = paramObject->GetProperty("strokeWidth");
171 if (strokeWidth->IsUndefined() || strokeWidth->IsNull() ||
172 !ParseLengthMetricsToDimension(strokeWidth, strokeWidthDimension)) {
173 strokeWidthDimension = defaultStrokeWidth;
174 }
175 if (LessNotEqual(strokeWidthDimension.Value(), 0.0f) || strokeWidthDimension.Unit() == DimensionUnit::PERCENT) {
176 strokeWidthDimension = defaultStrokeWidth;
177 }
178 if (strokeWidthDimension.ConvertToVp() < defaultStrokeWidthMin.ConvertToVp()) {
179 strokeWidthDimension = defaultStrokeWidthMin;
180 }
181 LinearIndicatorModel::GetInstance()->SetStrokeWidth(strokeWidthDimension);
182 }
183
SetStrokeRadius(const JSRef<JSObject> & paramObject,const RefPtr<NG::LinearIndicatorTheme> & theme)184 void JSLinearIndicator::SetStrokeRadius(
185 const JSRef<JSObject>& paramObject, const RefPtr<NG::LinearIndicatorTheme>& theme)
186 {
187 CalcDimension strokeRadiusDimension;
188 CalcDimension defaultStrokeRadius = theme->GetDefaultStrokeRadius();
189 auto strokeRadius = paramObject->GetProperty("strokeRadius");
190 if (strokeRadius->IsUndefined() || strokeRadius->IsNull() ||
191 !ParseLengthMetricsToDimension(strokeRadius, strokeRadiusDimension)) {
192 strokeRadiusDimension = defaultStrokeRadius;
193 }
194 if (LessNotEqual(strokeRadiusDimension.Value(), 0.0f) || strokeRadiusDimension.Unit() == DimensionUnit::PERCENT) {
195 strokeRadiusDimension = defaultStrokeRadius;
196 }
197 LinearIndicatorModel::GetInstance()->SetStrokeRadius(strokeRadiusDimension);
198 }
199
SetTrackBackgroundColor(const JSRef<JSObject> & paramObject,const RefPtr<NG::LinearIndicatorTheme> & theme)200 void JSLinearIndicator::SetTrackBackgroundColor(
201 const JSRef<JSObject>& paramObject, const RefPtr<NG::LinearIndicatorTheme>& theme)
202 {
203 Color trackBackgroundColorValue;
204 auto trackBackgroundColor = paramObject->GetProperty("trackBackgroundColor");
205 if (trackBackgroundColor->IsUndefined() || trackBackgroundColor->IsNull() ||
206 !ParseColorMetricsToColor(trackBackgroundColor, trackBackgroundColorValue)) {
207 trackBackgroundColorValue = theme->GetTrackBackgroundColor();
208 }
209 LinearIndicatorModel::GetInstance()->SetTrackBackgroundColor(trackBackgroundColorValue);
210 }
211
SetTrackColor(const JSRef<JSObject> & paramObject,const RefPtr<NG::LinearIndicatorTheme> & theme)212 void JSLinearIndicator::SetTrackColor(const JSRef<JSObject>& paramObject, const RefPtr<NG::LinearIndicatorTheme>& theme)
213 {
214 Color trackColorValue;
215 auto trackColor = paramObject->GetProperty("trackColor");
216 if (trackColor->IsUndefined() || trackColor->IsNull() || !ParseColorMetricsToColor(trackColor, trackColorValue)) {
217 trackColorValue = theme->GetTrackColor();
218 }
219 LinearIndicatorModel::GetInstance()->SetTrackColor(trackColorValue);
220 }
221
JsHeight(const JSCallbackInfo & info)222 void JSLinearIndicator::JsHeight(const JSCallbackInfo& info)
223 {
224 if (info.Length() == 0) {
225 return;
226 }
227 auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
228 CHECK_NULL_VOID(pipeline);
229 auto theme = pipeline->GetThemeManager()->GetTheme<NG::LinearIndicatorTheme>();
230 CHECK_NULL_VOID(theme);
231 Dimension defaultHeight = theme->GetDefaultHeight();
232
233 CalcDimension value = defaultHeight;
234 auto jsValue = info[0];
235 if (jsValue->IsUndefined()) {
236 value = defaultHeight;
237 } else if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
238 if (!ParseJsDimensionVpNG(jsValue, value)) {
239 value = defaultHeight;
240 }
241 } else if (!ParseJsDimensionVp(jsValue, value)) {
242 value = defaultHeight;
243 }
244 if (LessNotEqual(value.Value(), 0.0)) {
245 value = defaultHeight;
246 }
247 ViewAbstractModel::GetInstance()->SetHeight(value);
248 }
249
JsPadding(const JSCallbackInfo & info)250 void JSLinearIndicator::JsPadding(const JSCallbackInfo& info)
251 {
252 if (info.Length() == 0) {
253 return;
254 }
255 auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
256 CHECK_NULL_VOID(pipeline);
257 auto theme = pipeline->GetThemeManager()->GetTheme<NG::LinearIndicatorTheme>();
258 CHECK_NULL_VOID(theme);
259 Dimension defaultLeft = theme->GetPaddingLeft();
260 Dimension defaultRight = theme->GetPaddingRight();
261
262 auto jsVal = info[0];
263 if ((!jsVal->IsObject()) && (!jsVal->IsString()) && (!jsVal->IsNumber())) {
264 ViewAbstractModel::GetInstance()->SetPaddings(std::nullopt, std::nullopt, defaultLeft, defaultRight);
265 return;
266 }
267 if (jsVal->IsObject()) {
268 CommonCalcDimension commonCalcDimension;
269 JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(jsVal);
270 ParseCommonMarginOrPaddingCorner(paddingObj, commonCalcDimension);
271 if (!commonCalcDimension.left.has_value() || LessNotEqual(commonCalcDimension.left.value().Value(), 0.0)) {
272 commonCalcDimension.left = defaultLeft;
273 }
274 if (!commonCalcDimension.right.has_value() || LessNotEqual(commonCalcDimension.right.value().Value(), 0.0)) {
275 commonCalcDimension.right = defaultRight;
276 }
277 ViewAbstractModel::GetInstance()->SetPaddings(
278 std::nullopt, std::nullopt, commonCalcDimension.left, commonCalcDimension.right);
279 return;
280 }
281 CalcDimension length;
282 if (ParseJsDimensionVp(jsVal, length) && (!LessNotEqual(length.Value(), 0.0))) {
283 ViewAbstractModel::GetInstance()->SetPaddings(std::nullopt, std::nullopt, length, length);
284 } else {
285 ViewAbstractModel::GetInstance()->SetPaddings(std::nullopt, std::nullopt, defaultLeft, defaultRight);
286 }
287 }
288
SetPaddingLeft(const JSCallbackInfo & info)289 void JSLinearIndicator::SetPaddingLeft(const JSCallbackInfo& info)
290 {
291 if (info.Length() == 0) {
292 return;
293 }
294 auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
295 CHECK_NULL_VOID(pipeline);
296 auto theme = pipeline->GetThemeManager()->GetTheme<NG::LinearIndicatorTheme>();
297 CHECK_NULL_VOID(theme);
298 Dimension defaultLeft = theme->GetPaddingLeft();
299 CalcDimension value;
300 if (!ParseJsDimensionVp(info[0], value)) {
301 value = defaultLeft;
302 }
303 ViewAbstractModel::GetInstance()->SetPaddings(std::nullopt, std::nullopt, value, std::nullopt);
304 }
305
SetPaddingRight(const JSCallbackInfo & info)306 void JSLinearIndicator::SetPaddingRight(const JSCallbackInfo& info)
307 {
308 if (info.Length() == 0) {
309 return;
310 }
311 auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
312 CHECK_NULL_VOID(pipeline);
313 auto theme = pipeline->GetThemeManager()->GetTheme<NG::LinearIndicatorTheme>();
314 CHECK_NULL_VOID(theme);
315 Dimension defaultRight = theme->GetPaddingRight();
316 CalcDimension value;
317 if (!ParseJsDimensionVp(info[0], value)) {
318 value = defaultRight;
319 }
320 ViewAbstractModel::GetInstance()->SetPaddings(std::nullopt, std::nullopt, std::nullopt, value);
321 }
322
JsIgnore(const JSCallbackInfo & info)323 void JSLinearIndicator::JsIgnore(const JSCallbackInfo& info) {}
324
325 } // namespace OHOS::Ace::Framework
326