• 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 "bridge/declarative_frontend/jsview/js_data_panel.h"
17 
18 #include <vector>
19 
20 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
21 #include "bridge/declarative_frontend/jsview/js_linear_gradient.h"
22 #include "bridge/declarative_frontend/jsview/js_utils.h"
23 #include "bridge/declarative_frontend/jsview/models/data_panel_model_impl.h"
24 #include "core/components/data_panel/data_panel_theme.h"
25 #include "core/components_ng/pattern/data_panel/data_panel_model_ng.h"
26 
27 namespace OHOS::Ace {
28 
29 std::unique_ptr<DataPanelModel> DataPanelModel::instance_ = nullptr;
30 std::mutex DataPanelModel::mutex_;
31 
GetInstance()32 DataPanelModel* DataPanelModel::GetInstance()
33 {
34     if (!instance_) {
35         std::lock_guard<std::mutex> lock(mutex_);
36         if (!instance_) {
37 #ifdef NG_BUILD
38             instance_.reset(new NG::DataPanelModelNG());
39 #else
40             if (Container::IsCurrentUseNewPipeline()) {
41                 instance_.reset(new NG::DataPanelModelNG());
42             } else {
43                 instance_.reset(new Framework::DataPanelModelImpl());
44             }
45 #endif
46         }
47     }
48     return instance_.get();
49 }
50 
51 } // namespace OHOS::Ace
52 namespace OHOS::Ace::Framework {
53 
54 constexpr size_t MAX_COUNT = 9;
55 
JSBind(BindingTarget globalObj)56 void JSDataPanel::JSBind(BindingTarget globalObj)
57 {
58     JSClass<JSDataPanel>::Declare("DataPanel");
59     JSClass<JSDataPanel>::StaticMethod("create", &JSDataPanel::Create);
60     JSClass<JSDataPanel>::StaticMethod("closeEffect", &JSDataPanel::CloseEffect);
61 
62     JSClass<JSDataPanel>::StaticMethod("valueColors", &JSDataPanel::ValueColors);
63     JSClass<JSDataPanel>::StaticMethod("trackBackgroundColor", &JSDataPanel::TrackBackground);
64     JSClass<JSDataPanel>::StaticMethod("strokeWidth", &JSDataPanel::StrokeWidth);
65     JSClass<JSDataPanel>::StaticMethod("trackShadow", &JSDataPanel::ShadowOption);
66 
67     JSClass<JSDataPanel>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
68     JSClass<JSDataPanel>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
69     JSClass<JSDataPanel>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
70     JSClass<JSDataPanel>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
71     JSClass<JSDataPanel>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
72     JSClass<JSDataPanel>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
73     JSClass<JSDataPanel>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
74 
75     JSClass<JSDataPanel>::InheritAndBind<JSViewAbstract>(globalObj);
76 }
77 
Create(const JSCallbackInfo & info)78 void JSDataPanel::Create(const JSCallbackInfo& info)
79 {
80     if (!info[0]->IsObject()) {
81         return;
82     }
83     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
84     // max
85     double max = jsObj->GetPropertyValue<double>("max", 100.0);
86     // values
87     JSRef<JSVal> jsValue = jsObj->GetProperty("values");
88     if (!jsValue->IsArray()) {
89         return;
90     }
91     JSRef<JSArray> jsArray = JSRef<JSArray>::Cast(jsValue);
92     size_t length = jsArray->Length();
93     std::vector<double> dateValues;
94     double dataSum = 0.0;
95     size_t count = std::min(length, MAX_COUNT);
96     for (size_t i = 0; i < count; ++i) {
97         JSRef<JSVal> item = jsArray->GetValueAt(i);
98         if (!item->IsNumber()) {
99             continue;
100         }
101         double value = item->ToNumber<double>();
102         if (LessOrEqual(value, 0.0)) {
103             value = 0.0;
104         }
105         // if the sum of values exceeds the maximum value, only fill in to the maximum value
106         if (GreatOrEqual(dataSum + value, max) && GreatNotEqual(max, 0)) {
107             dateValues.emplace_back(max - dataSum);
108             break;
109         }
110         dataSum += value;
111         dateValues.emplace_back(value);
112     }
113     if (LessOrEqual(max, 0.0)) {
114         max = dataSum;
115     }
116 
117     size_t dataPanelType = 0;
118     int32_t type = jsObj->GetPropertyValue<int32_t>("type", static_cast<int32_t>(ChartType::RAINBOW));
119     if (type == static_cast<int32_t>(ChartType::LINE)) {
120         dataPanelType = 1;
121     }
122     DataPanelModel::GetInstance()->Create(dateValues, max, dataPanelType);
123 }
124 
CloseEffect(const JSCallbackInfo & info)125 void JSDataPanel::CloseEffect(const JSCallbackInfo& info)
126 {
127     bool isCloseEffect = true;
128     if (info[0]->IsBoolean()) {
129         isCloseEffect = info[0]->ToBoolean();
130     }
131     DataPanelModel::GetInstance()->SetEffect(isCloseEffect);
132 }
133 
ValueColors(const JSCallbackInfo & info)134 void JSDataPanel::ValueColors(const JSCallbackInfo& info)
135 {
136     if (info.Length() < 1) {
137         return;
138     }
139 
140     std::vector<OHOS::Ace::NG::Gradient> valueColors;
141     if (!info[0]->IsArray() || info[0]->IsEmpty()) {
142         ConvertThemeColor(valueColors);
143         DataPanelModel::GetInstance()->SetValueColors(valueColors);
144         return;
145     }
146 
147     auto paramArray = JSRef<JSArray>::Cast(info[0]);
148     size_t length = paramArray->Length();
149     size_t count = std::min(length, MAX_COUNT);
150     for (size_t i = 0; i < count; ++i) {
151         auto item = paramArray->GetValueAt(i);
152         OHOS::Ace::NG::Gradient gradient;
153         if (!ConvertGradientColor(item, gradient)) {
154             valueColors.clear();
155             ConvertThemeColor(valueColors);
156             break;
157         }
158         valueColors.emplace_back(gradient);
159     }
160     DataPanelModel::GetInstance()->SetValueColors(valueColors);
161 }
162 
TrackBackground(const JSCallbackInfo & info)163 void JSDataPanel::TrackBackground(const JSCallbackInfo& info)
164 {
165     if (info.Length() < 1) {
166         return;
167     }
168     Color color;
169     if (!ParseJsColor(info[0], color)) {
170         RefPtr<DataPanelTheme> theme = GetTheme<DataPanelTheme>();
171         color = theme->GetBackgroundColor();
172     }
173 
174     DataPanelModel::GetInstance()->SetTrackBackground(color);
175 }
176 
StrokeWidth(const JSCallbackInfo & info)177 void JSDataPanel::StrokeWidth(const JSCallbackInfo& info)
178 {
179     if (info.Length() < 1) {
180         return;
181     }
182 
183     RefPtr<DataPanelTheme> theme = GetTheme<DataPanelTheme>();
184     CalcDimension strokeWidthDimension;
185     if (!ParseJsDimensionVp(info[0], strokeWidthDimension)) {
186         strokeWidthDimension = theme->GetThickness();
187     }
188 
189     // If the parameter value is string(''), parse result 0.
190     // The value of 0 is allowed, but the value of string('') is not allowed, so use theme value.
191     if (info[0]->IsString() && (info[0]->ToString().empty() || !StringUtils::StringToDimensionWithUnitNG(
192         info[0]->ToString(), strokeWidthDimension))) {
193         strokeWidthDimension = theme->GetThickness();
194     }
195 
196     if (strokeWidthDimension.IsNegative() || strokeWidthDimension.Unit() == DimensionUnit::PERCENT) {
197         strokeWidthDimension = theme->GetThickness();
198     }
199     DataPanelModel::GetInstance()->SetStrokeWidth(strokeWidthDimension);
200 }
201 
ShadowOption(const JSCallbackInfo & info)202 void JSDataPanel::ShadowOption(const JSCallbackInfo& info)
203 {
204     OHOS::Ace::NG::DataPanelShadow shadow;
205     if (info[0]->IsNull()) {
206         shadow.isShadowVisible = false;
207         DataPanelModel::GetInstance()->SetShadowOption(shadow);
208         return;
209     }
210     RefPtr<DataPanelTheme> theme = GetTheme<DataPanelTheme>();
211     double radius = theme->GetTrackShadowRadius().ConvertToVp();
212     double offsetX = theme->GetTrackShadowOffsetX().ConvertToVp();
213     double offsetY = theme->GetTrackShadowOffsetY().ConvertToVp();
214     std::vector<OHOS::Ace::NG::Gradient> shadowColors;
215     ConvertThemeColor(shadowColors);
216     if (info[0]->IsObject()) {
217         auto paramObject = JSRef<JSObject>::Cast(info[0]);
218         JSRef<JSVal> jsRadius = paramObject->GetProperty("radius");
219         JSRef<JSVal> jsOffsetX = paramObject->GetProperty("offsetX");
220         JSRef<JSVal> jsOffsetY = paramObject->GetProperty("offsetY");
221         ParseJsDouble(jsRadius, radius);
222         if (NonPositive(radius)) {
223             radius = theme->GetTrackShadowRadius().ConvertToVp();
224         }
225         ParseJsDouble(jsOffsetX, offsetX);
226         ParseJsDouble(jsOffsetY, offsetY);
227 
228         auto colors = paramObject->GetProperty("colors");
229         if (!colors->IsArray()) {
230             shadow.radius = radius;
231             shadow.offsetX = offsetX;
232             shadow.offsetY = offsetY;
233             shadow.colors = shadowColors;
234             DataPanelModel::GetInstance()->SetShadowOption(shadow);
235             return;
236         }
237         shadowColors.clear();
238         auto colorsArray = JSRef<JSArray>::Cast(colors);
239         for (size_t i = 0; i < colorsArray->Length(); ++i) {
240             auto item = colorsArray->GetValueAt(i);
241             OHOS::Ace::NG::Gradient gradient;
242             if (!ConvertGradientColor(item, gradient)) {
243                 shadowColors.clear();
244                 ConvertThemeColor(shadowColors);
245                 break;
246             }
247             shadowColors.emplace_back(gradient);
248         }
249     }
250 
251     shadow.radius = radius;
252     shadow.offsetX = offsetX;
253     shadow.offsetY = offsetY;
254     shadow.colors = shadowColors;
255     DataPanelModel::GetInstance()->SetShadowOption(shadow);
256 }
257 
ConvertGradientColor(const JsiRef<JsiValue> & itemParam,OHOS::Ace::NG::Gradient & gradient)258 bool JSDataPanel::ConvertGradientColor(const JsiRef<JsiValue>& itemParam, OHOS::Ace::NG::Gradient& gradient)
259 {
260     if (!itemParam->IsObject()) {
261         return ConvertResourceColor(itemParam, gradient);
262     }
263 
264     JSLinearGradient* jsLinearGradient = JSRef<JSObject>::Cast(itemParam)->Unwrap<JSLinearGradient>();
265     if (!jsLinearGradient) {
266         return ConvertResourceColor(itemParam, gradient);
267     }
268 
269     size_t colorLength = jsLinearGradient->GetGradient().size();
270     if (colorLength == 0) {
271         return false;
272     }
273     for (size_t colorIndex = 0; colorIndex < colorLength; ++colorIndex) {
274         OHOS::Ace::NG::GradientColor gradientColor;
275         gradientColor.SetLinearColor(LinearColor(jsLinearGradient->GetGradient().at(colorIndex).first));
276         gradientColor.SetDimension(jsLinearGradient->GetGradient().at(colorIndex).second);
277         gradient.AddColor(gradientColor);
278     }
279     return true;
280 }
281 
ConvertResourceColor(const JsiRef<JsiValue> & itemParam,OHOS::Ace::NG::Gradient & gradient)282 bool JSDataPanel::ConvertResourceColor(const JsiRef<JsiValue>& itemParam, OHOS::Ace::NG::Gradient& gradient)
283 {
284     Color color;
285     if (!ParseJsColor(itemParam, color)) {
286         return false;
287     }
288     OHOS::Ace::NG::GradientColor gradientColorStart;
289     gradientColorStart.SetLinearColor(LinearColor(color));
290     gradientColorStart.SetDimension(Dimension(0.0));
291     gradient.AddColor(gradientColorStart);
292     OHOS::Ace::NG::GradientColor gradientColorEnd;
293     gradientColorEnd.SetLinearColor(LinearColor(color));
294     gradientColorEnd.SetDimension(Dimension(1.0));
295     gradient.AddColor(gradientColorEnd);
296     return true;
297 }
298 
ConvertThemeColor(std::vector<OHOS::Ace::NG::Gradient> & colors)299 void JSDataPanel::ConvertThemeColor(std::vector<OHOS::Ace::NG::Gradient>& colors)
300 {
301     RefPtr<DataPanelTheme> theme = GetTheme<DataPanelTheme>();
302     auto themeColors = theme->GetColorsArray();
303     for (const auto& item : themeColors) {
304         OHOS::Ace::NG::Gradient gradient;
305         OHOS::Ace::NG::GradientColor gradientColorStart;
306         gradientColorStart.SetLinearColor(LinearColor(item.first));
307         gradientColorStart.SetDimension(Dimension(0.0));
308         gradient.AddColor(gradientColorStart);
309         OHOS::Ace::NG::GradientColor gradientColorEnd;
310         gradientColorEnd.SetLinearColor(LinearColor(item.second));
311         gradientColorEnd.SetDimension(Dimension(1.0));
312         gradient.AddColor(gradientColorEnd);
313         colors.emplace_back(gradient);
314     }
315 }
316 } // namespace OHOS::Ace::Framework
317