• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 
16 #include "frameworks/bridge/declarative_frontend/jsview/js_slider.h"
17 
18 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
19 #include "bridge/declarative_frontend/jsview/models/slider_model_impl.h"
20 #include "core/components/slider/render_slider.h"
21 #include "core/components/slider/slider_element.h"
22 #include "core/components_ng/pattern/slider/slider_model_ng.h"
23 #include "frameworks/bridge/declarative_frontend/engine/functions/js_function.h"
24 #include "frameworks/bridge/declarative_frontend/jsview/js_shape_abstract.h"
25 
26 namespace OHOS::Ace {
27 namespace {
28 constexpr int SLIDER_SHOW_TIPS_MAX_PARAMS = 2;
29 } // namespace
30 
31 std::unique_ptr<SliderModel> SliderModel::instance_ = nullptr;
32 std::mutex SliderModel::mutex_;
33 
GetInstance()34 SliderModel* SliderModel::GetInstance()
35 {
36     if (!instance_) {
37         std::lock_guard<std::mutex> lock(mutex_);
38         if (!instance_) {
39 #ifdef NG_BUILD
40             instance_.reset(new NG::SliderModelNG());
41 #else
42             if (Container::IsCurrentUseNewPipeline()) {
43                 instance_.reset(new NG::SliderModelNG());
44             } else {
45                 instance_.reset(new Framework::SliderModelImpl());
46             }
47 #endif
48         }
49     }
50     return instance_.get();
51 }
52 
53 } // namespace OHOS::Ace
54 
55 namespace OHOS::Ace::Framework {
56 
JSBind(BindingTarget globalObj)57 void JSSlider::JSBind(BindingTarget globalObj)
58 {
59     JSClass<JSSlider>::Declare("Slider");
60     MethodOptions opt = MethodOptions::NONE;
61     JSClass<JSSlider>::StaticMethod("create", &JSSlider::Create, opt);
62     JSClass<JSSlider>::StaticMethod("blockColor", &JSSlider::SetBlockColor);
63     JSClass<JSSlider>::StaticMethod("trackColor", &JSSlider::SetTrackColor);
64     JSClass<JSSlider>::StaticMethod("trackThickness", &JSSlider::SetThickness);
65     JSClass<JSSlider>::StaticMethod("selectedColor", &JSSlider::SetSelectedColor);
66     JSClass<JSSlider>::StaticMethod("minLabel", &JSSlider::SetMinLabel);
67     JSClass<JSSlider>::StaticMethod("maxLabel", &JSSlider::SetMaxLabel);
68     JSClass<JSSlider>::StaticMethod("showSteps", &JSSlider::SetShowSteps);
69     JSClass<JSSlider>::StaticMethod("showTips", &JSSlider::SetShowTips);
70     JSClass<JSSlider>::StaticMethod("blockBorderColor", &JSSlider::SetBlockBorderColor);
71     JSClass<JSSlider>::StaticMethod("blockBorderWidth", &JSSlider::SetBlockBorderWidth);
72     JSClass<JSSlider>::StaticMethod("stepColor", &JSSlider::SetStepColor);
73     JSClass<JSSlider>::StaticMethod("trackBorderRadius", &JSSlider::SetTrackBorderRadius);
74     JSClass<JSSlider>::StaticMethod("blockSize", &JSSlider::SetBlockSize);
75     JSClass<JSSlider>::StaticMethod("blockStyle", &JSSlider::SetBlockStyle);
76     JSClass<JSSlider>::StaticMethod("stepSize", &JSSlider::SetStepSize);
77     JSClass<JSSlider>::StaticMethod("onChange", &JSSlider::OnChange);
78     JSClass<JSSlider>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
79     JSClass<JSSlider>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
80     JSClass<JSSlider>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
81     JSClass<JSSlider>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
82     JSClass<JSSlider>::InheritAndBind<JSViewAbstract>(globalObj);
83 }
84 
GetStep(double step,double max,double min)85 double GetStep(double step, double max, double min)
86 {
87     if (LessOrEqual(step, 0.0) || step > max - min) {
88         step = 1;
89     }
90     return step;
91 }
92 
GetValue(double value,double max,double min)93 double GetValue(double value, double max, double min)
94 {
95     if (value < min) {
96         value = min;
97     }
98 
99     if (value > max) {
100         value = max;
101     }
102     return value;
103 }
104 
ParseSliderValueObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal)105 void ParseSliderValueObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
106 {
107     CHECK_NULL_VOID(changeEventVal->IsFunction());
108 
109     JsEventCallback<void(float)> onChangeEvent(info.GetExecutionContext(), JSRef<JSFunc>::Cast(changeEventVal));
110     SliderModel::GetInstance()->SetOnChangeEvent(std::move(onChangeEvent));
111 }
112 
Create(const JSCallbackInfo & info)113 void JSSlider::Create(const JSCallbackInfo& info)
114 {
115     static const double valueMin = -1000000.0f;
116     double value = valueMin; // value:Current progress value. The default value is min.
117     double min = 0;   // min:Set the minimum value. The default value is 0.
118     double max = 100; // max:Set the maximum value. The default value is 100.
119     double step = 1;  // step:Sets the sliding jump value of the slider. The default value is 1.
120     bool reverse = false;
121 
122     if (!info[0]->IsObject()) {
123         SliderModel::GetInstance()->Create(
124             static_cast<float>(value), static_cast<float>(step), static_cast<float>(min), static_cast<float>(max));
125         return;
126     }
127 
128     auto paramObject = JSRef<JSObject>::Cast(info[0]);
129     auto getValue = paramObject->GetProperty("value");
130     auto getMin = paramObject->GetProperty("min");
131     auto getMax = paramObject->GetProperty("max");
132     auto getStep = paramObject->GetProperty("step");
133     auto getStyle = paramObject->GetProperty("style");
134     auto direction = paramObject->GetProperty("direction");
135     auto isReverse = paramObject->GetProperty("reverse");
136     JSRef<JSVal> changeEventVal;
137 
138     if (!getValue->IsNull() && getValue->IsNumber()) {
139         value = getValue->ToNumber<double>();
140     } else if (!getValue->IsNull() && getValue->IsObject()) {
141         JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(getValue);
142         changeEventVal = valueObj->GetProperty("changeEvent");
143         auto valueProperty = valueObj->GetProperty("value");
144         value = valueProperty->ToNumber<double>();
145     }
146 
147     if (!getMin->IsNull() && getMin->IsNumber()) {
148         min = getMin->ToNumber<double>();
149     }
150 
151     if (!getMax->IsNull() && getMax->IsNumber()) {
152         max = getMax->ToNumber<double>();
153     }
154 
155     if (!getStep->IsNull() && getStep->IsNumber()) {
156         step = getStep->ToNumber<double>();
157     }
158 
159     if (!isReverse->IsNull() && isReverse->IsBoolean()) {
160         reverse = isReverse->ToBoolean();
161     }
162 
163     if (GreatOrEqual(min, max)) {
164         min = 0;
165         max = 100;
166     }
167 
168     step = GetStep(step, max, min);
169 
170     if (!Container::IsCurrentUseNewPipeline()) {
171         value = GetValue(value, max, min);
172     }
173 
174     auto sliderStyle = SliderStyle::OUTSET;
175     auto sliderMode = SliderModel::SliderMode::OUTSET;
176     if (!getStyle->IsNull() && getStyle->IsNumber()) {
177         sliderStyle = static_cast<SliderStyle>(getStyle->ToNumber<int32_t>());
178     }
179     if (sliderStyle == SliderStyle::INSET) {
180         sliderMode = SliderModel::SliderMode::INSET;
181     } else if (sliderStyle == SliderStyle::CAPSULE) {
182         sliderMode = SliderModel::SliderMode::CAPSULE;
183     } else {
184         sliderMode = SliderModel::SliderMode::OUTSET;
185     }
186 
187     auto sliderDirection = Axis::HORIZONTAL;
188     if (!direction->IsNull() && direction->IsNumber()) {
189         sliderDirection = static_cast<Axis>(direction->ToNumber<int32_t>());
190     }
191     if (sliderDirection != Axis::VERTICAL) {
192         sliderDirection = Axis::HORIZONTAL;
193     }
194 
195     SliderModel::GetInstance()->Create(
196         static_cast<float>(value), static_cast<float>(step), static_cast<float>(min), static_cast<float>(max));
197     SliderModel::GetInstance()->SetSliderMode(sliderMode);
198     SliderModel::GetInstance()->SetDirection(sliderDirection);
199     SliderModel::GetInstance()->SetReverse(reverse);
200     if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
201         ParseSliderValueObject(info, changeEventVal);
202     }
203 }
204 
SetThickness(const JSCallbackInfo & info)205 void JSSlider::SetThickness(const JSCallbackInfo& info)
206 {
207     if (info.Length() < 1) {
208         return;
209     }
210     CalcDimension value;
211     if (!ParseJsDimensionVp(info[0], value)) {
212         value = CalcDimension(0.0);
213     }
214     SliderModel::GetInstance()->SetThickness(value);
215 }
216 
SetBlockColor(const JSCallbackInfo & info)217 void JSSlider::SetBlockColor(const JSCallbackInfo& info)
218 {
219     if (info.Length() < 1) {
220         return;
221     }
222     Color colorVal;
223     if (!ParseJsColor(info[0], colorVal)) {
224         auto theme = GetTheme<SliderTheme>();
225         CHECK_NULL_VOID(theme);
226         colorVal = theme->GetBlockColor();
227     }
228     SliderModel::GetInstance()->SetBlockColor(colorVal);
229 }
230 
SetTrackColor(const JSCallbackInfo & info)231 void JSSlider::SetTrackColor(const JSCallbackInfo& info)
232 {
233     if (info.Length() < 1) {
234         return;
235     }
236     Color colorVal;
237     if (!ParseJsColor(info[0], colorVal)) {
238         auto theme = GetTheme<SliderTheme>();
239         CHECK_NULL_VOID(theme);
240         colorVal = theme->GetTrackBgColor();
241     }
242     SliderModel::GetInstance()->SetTrackBackgroundColor(colorVal);
243 }
244 
SetSelectedColor(const JSCallbackInfo & info)245 void JSSlider::SetSelectedColor(const JSCallbackInfo& info)
246 {
247     if (info.Length() < 1) {
248         return;
249     }
250     Color colorVal;
251     if (!ParseJsColor(info[0], colorVal)) {
252         auto theme = GetTheme<SliderTheme>();
253         CHECK_NULL_VOID(theme);
254         colorVal = theme->GetTrackSelectedColor();
255     }
256     SliderModel::GetInstance()->SetSelectColor(colorVal);
257 }
258 
SetMinLabel(const JSCallbackInfo & info)259 void JSSlider::SetMinLabel(const JSCallbackInfo& info)
260 {
261     if (!info[0]->IsString()) {
262         return;
263     }
264     SliderModel::GetInstance()->SetMinLabel(info[0]->ToNumber<float>());
265 }
266 
SetMaxLabel(const JSCallbackInfo & info)267 void JSSlider::SetMaxLabel(const JSCallbackInfo& info)
268 {
269     if (!info[0]->IsString()) {
270         return;
271     }
272     SliderModel::GetInstance()->SetMaxLabel(info[0]->ToNumber<float>());
273 }
274 
SetShowSteps(const JSCallbackInfo & info)275 void JSSlider::SetShowSteps(const JSCallbackInfo& info)
276 {
277     if (info.Length() < 1) {
278         return;
279     }
280     bool showSteps = false;
281     if (info[0]->IsBoolean()) {
282         showSteps = info[0]->ToBoolean();
283     }
284     SliderModel::GetInstance()->SetShowSteps(showSteps);
285 }
286 
SetShowTips(const JSCallbackInfo & info)287 void JSSlider::SetShowTips(const JSCallbackInfo& info)
288 {
289     if (info.Length() < 1) {
290         return;
291     }
292     bool showTips = false;
293     if (info[0]->IsBoolean()) {
294         showTips = info[0]->ToBoolean();
295     }
296 
297     std::optional<std::string> content;
298     if (info.Length() == SLIDER_SHOW_TIPS_MAX_PARAMS) {
299         std::string str;
300         if (ParseJsString(info[1], str)) {
301             content = str;
302         }
303     }
304 
305     SliderModel::GetInstance()->SetShowTips(showTips, content);
306 }
307 
SetBlockBorderColor(const JSCallbackInfo & info)308 void JSSlider::SetBlockBorderColor(const JSCallbackInfo& info)
309 {
310     if (info.Length() < 1) {
311         return;
312     }
313 
314     Color colorVal;
315     if (!ParseJsColor(info[0], colorVal)) {
316         SliderModel::GetInstance()->ResetBlockBorderColor();
317         return;
318     }
319     SliderModel::GetInstance()->SetBlockBorderColor(colorVal);
320 }
321 
SetBlockBorderWidth(const JSCallbackInfo & info)322 void JSSlider::SetBlockBorderWidth(const JSCallbackInfo& info)
323 {
324     if (info.Length() < 1) {
325         return;
326     }
327 
328     CalcDimension blockBorderWidth;
329     if (!ParseJsDimensionVp(info[0], blockBorderWidth)) {
330         SliderModel::GetInstance()->ResetBlockBorderWidth();
331         return;
332     }
333     if (LessNotEqual(blockBorderWidth.Value(), 0.0)) {
334         SliderModel::GetInstance()->ResetBlockBorderWidth();
335         return;
336     }
337     SliderModel::GetInstance()->SetBlockBorderWidth(blockBorderWidth);
338 }
339 
SetStepColor(const JSCallbackInfo & info)340 void JSSlider::SetStepColor(const JSCallbackInfo& info)
341 {
342     if (info.Length() < 1) {
343         return;
344     }
345 
346     Color colorVal;
347     if (!ParseJsColor(info[0], colorVal)) {
348         SliderModel::GetInstance()->ResetStepColor();
349         return;
350     }
351     SliderModel::GetInstance()->SetStepColor(colorVal);
352 }
353 
SetTrackBorderRadius(const JSCallbackInfo & info)354 void JSSlider::SetTrackBorderRadius(const JSCallbackInfo& info)
355 {
356     if (info.Length() < 1) {
357         return;
358     }
359 
360     CalcDimension trackBorderRadius;
361     if (!ParseJsDimensionVpNG(info[0], trackBorderRadius, true)) {
362         SliderModel::GetInstance()->ResetTrackBorderRadius();
363         return;
364     }
365     if (LessNotEqual(trackBorderRadius.Value(), 0.0)) {
366         SliderModel::GetInstance()->ResetTrackBorderRadius();
367         return;
368     }
369     SliderModel::GetInstance()->SetTrackBorderRadius(trackBorderRadius);
370 }
371 
SetBlockSize(const JSCallbackInfo & info)372 void JSSlider::SetBlockSize(const JSCallbackInfo& info)
373 {
374     if (info.Length() < 1) {
375         return;
376     }
377     if (!info[0]->IsObject()) {
378         SliderModel::GetInstance()->ResetBlockSize();
379         return;
380     }
381     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
382 
383     CalcDimension width;
384     JSRef<JSVal> jsWidth = sizeObj->GetProperty("width");
385     if (!ParseJsDimensionVp(jsWidth, width)) {
386         width.SetValue(0.0);
387     }
388     if (LessNotEqual(width.Value(), 0.0)) {
389         width.SetValue(0.0);
390     }
391 
392     CalcDimension height;
393     JSRef<JSVal> jsHeight = sizeObj->GetProperty("height");
394     if (!ParseJsDimensionVp(jsHeight, height)) {
395         height.SetValue(0.0);
396     }
397     if (LessNotEqual(height.Value(), 0.0)) {
398         height.SetValue(0.0);
399     }
400 
401     SliderModel::GetInstance()->SetBlockSize(width, height);
402 }
403 
SetBlockStyle(const JSCallbackInfo & info)404 void JSSlider::SetBlockStyle(const JSCallbackInfo& info)
405 {
406     if (!info[0]->IsObject()) {
407         ResetBlockStyle();
408         return;
409     }
410     auto jsObj = JSRef<JSObject>::Cast(info[0]);
411     auto getType = jsObj->GetProperty("type");
412     if (getType->IsNull() || !getType->IsNumber()) {
413         ResetBlockStyle();
414         return;
415     }
416     auto type = static_cast<SliderModel::BlockStyleType>(getType->ToNumber<int32_t>());
417     if (type == SliderModel::BlockStyleType::IMAGE) {
418         std::string src;
419         auto image = jsObj->GetProperty("image");
420         if (!ParseJsMedia(image, src)) {
421             ResetBlockStyle();
422             return;
423         }
424         std::string bundleName;
425         std::string moduleName;
426         GetJsMediaBundleInfo(image, bundleName, moduleName);
427         SliderModel::GetInstance()->SetBlockImage(src, bundleName, moduleName);
428     } else if (type == SliderModel::BlockStyleType::SHAPE) {
429         auto shape = jsObj->GetProperty("shape");
430         if (!shape->IsObject()) {
431             ResetBlockStyle();
432             return;
433         }
434         JSShapeAbstract* shapeAbstract = JSRef<JSObject>::Cast(shape)->Unwrap<JSShapeAbstract>();
435         if (shapeAbstract == nullptr) {
436             ResetBlockStyle();
437             return;
438         }
439         SliderModel::GetInstance()->SetBlockShape(shapeAbstract->GetBasicShape());
440     }
441     SliderModel::GetInstance()->SetBlockType(type);
442 }
443 
SetStepSize(const JSCallbackInfo & info)444 void JSSlider::SetStepSize(const JSCallbackInfo& info)
445 {
446     if (info.Length() < 1) {
447         return;
448     }
449 
450     CalcDimension stepSize;
451     if (!ParseJsDimensionVp(info[0], stepSize)) {
452         SliderModel::GetInstance()->ResetStepSize();
453         return;
454     }
455     if (LessNotEqual(stepSize.Value(), 0.0)) {
456         auto theme = GetTheme<SliderTheme>();
457         CHECK_NULL_VOID(theme);
458         stepSize = theme->GetMarkerSize();
459     }
460     SliderModel::GetInstance()->SetStepSize(stepSize);
461 }
462 
OnChange(const JSCallbackInfo & info)463 void JSSlider::OnChange(const JSCallbackInfo& info)
464 {
465     if (!info[0]->IsFunction()) {
466         return;
467     }
468     SliderModel::GetInstance()->SetOnChange(
469         JsEventCallback<void(float, int32_t)>(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0])));
470     info.ReturnSelf();
471 }
472 
ResetBlockStyle()473 void JSSlider::ResetBlockStyle()
474 {
475     SliderModel::GetInstance()->ResetBlockType();
476     SliderModel::GetInstance()->ResetBlockImage();
477     SliderModel::GetInstance()->ResetBlockShape();
478 }
479 } // namespace OHOS::Ace::Framework
480