1 /*
2  * Copyright (c) 2022-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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GAUGE_GAUGE_PAINT_PROPERTY_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GAUGE_GAUGE_PAINT_PROPERTY_H
18 
19 #include "core/common/container.h"
20 #include "core/components/common/layout/constants.h"
21 #include "core/components/common/properties/color.h"
22 #include "core/components_ng/base/inspector_filter.h"
23 #include "core/components_ng/pattern/gauge/gauge_theme.h"
24 #include "core/components_ng/render/paint_property.h"
25 #include "core/image/image_source_info.h"
26 
27 namespace OHOS::Ace::NG {
28 using ColorStopArray = std::vector<std::pair<Color, Dimension>>;
29 enum class GaugeType : int32_t {
30     TYPE_CIRCULAR_MULTI_SEGMENT_GRADIENT = 0,
31     TYPE_CIRCULAR_SINGLE_SEGMENT_GRADIENT = 1,
32     TYPE_CIRCULAR_MONOCHROME = 2,
33 };
34 
35 struct GaugeShadowOptions {
36     bool isShadowVisible = true;
37     float radius = DEFAULT_GAUGE_SHADOW_RADIUS;
38     float offsetX = DEFAULT_GAUGE_SHADOW_OFFSETX;
39     float offsetY = DEFAULT_GAUGE_SHADOW_OFFSETY;
40     bool operator==(const GaugeShadowOptions& rhs) const
41     {
42         return radius == rhs.radius && offsetX == rhs.offsetX && offsetY == rhs.offsetY &&
43                isShadowVisible == rhs.isShadowVisible;
44     }
45 };
46 class GaugePaintProperty : public PaintProperty {
47     DECLARE_ACE_TYPE(GaugePaintProperty, PaintProperty)
48 
49 public:
50     GaugePaintProperty() = default;
51     ~GaugePaintProperty() override = default;
52 
Clone()53     RefPtr<PaintProperty> Clone() const override
54     {
55         auto paintProperty = MakeRefPtr<GaugePaintProperty>();
56         paintProperty->UpdatePaintProperty(this);
57         paintProperty->propValue_ = CloneValue();
58         paintProperty->propMin_ = CloneMin();
59         paintProperty->propMax_ = CloneMax();
60         paintProperty->propStartAngle_ = CloneStartAngle();
61         paintProperty->propEndAngle_ = CloneEndAngle();
62         paintProperty->propColors_ = CloneColors();
63         paintProperty->propGradientColors_ = CloneGradientColors();
64         paintProperty->propValues_ = CloneValues();
65         paintProperty->propStrokeWidth_ = CloneStrokeWidth();
66         paintProperty->propGaugeType_ = CloneGaugeType();
67         paintProperty->propShadowOptions_ = CloneShadowOptions();
68         paintProperty->propIsShowIndicator_ = CloneIsShowIndicator();
69         paintProperty->propIndicatorIconSourceInfo_ = CloneIndicatorIconSourceInfo();
70         paintProperty->propIndicatorSpace_ = CloneIndicatorSpace();
71         paintProperty->propIndicatorChange_ = CloneIndicatorChange();
72         paintProperty->propIsSensitive_ = CloneIsSensitive();
73         return paintProperty;
74     }
75 
Reset()76     void Reset() override
77     {
78         PaintProperty::Reset();
79         ResetValue();
80         ResetMin();
81         ResetMax();
82         ResetStartAngle();
83         ResetEndAngle();
84         ResetColors();
85         ResetGradientColors();
86         ResetValues();
87         ResetStrokeWidth();
88         ResetGaugeType();
89         ResetShadowOptions();
90         ResetIsShowIndicator();
91         ResetIndicatorIconSourceInfo();
92         ResetIndicatorSpace();
93         ResetIsSensitive();
94     }
95 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter)96     void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override
97     {
98         PaintProperty::ToJsonValue(json, filter);
99         /* no fixed attr below, just return */
100         if (filter.IsFastFilter()) {
101             if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
102                 ToJsonColor(json, filter);
103                 ToJsonIndicator(json, filter);
104                 ToJsonTrackShadow(json, filter);
105             }
106             return;
107         }
108         json->PutExtAttr("value", StringUtils::DoubleToString(propValue_.value_or(0)).c_str(), filter);
109         json->PutExtAttr("max", StringUtils::DoubleToString(propMax_.value_or(100)).c_str(), filter);
110         json->PutExtAttr("min", StringUtils::DoubleToString(propMin_.value_or(0)).c_str(), filter);
111         json->PutExtAttr("startAngle", StringUtils::DoubleToString(propStartAngle_.value_or(0)).c_str(), filter);
112         json->PutExtAttr("endAngle", StringUtils::DoubleToString(propEndAngle_.value_or(360)).c_str(), filter);
113         json->PutExtAttr("isSensitive", std::to_string(GetIsSensitive().value_or(false)).c_str(), filter);
114         if (propStrokeWidth_.has_value()) {
115             json->PutExtAttr("strokeWidth", propStrokeWidth_.value().ToString().c_str(), filter);
116         } else {
117             json->PutExtAttr("strokeWidth", "", filter);
118         }
119 
120         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
121             auto jsonColors = JsonUtil::CreateArray(true);
122             if (propColors_.has_value() && propColors_.has_value()) {
123                 for (size_t i = 0; i < propValues_.value().size(); i++) {
124                     auto jsonObject = JsonUtil::CreateArray(true);
125                     jsonObject->Put("0", propColors_.value()[i].ColorToString().c_str());
126                     jsonObject->Put("1", propValues_.value()[i]);
127                     auto index = std::to_string(i);
128                     jsonColors->Put(index.c_str(), jsonObject);
129                 }
130             }
131             json->PutExtAttr("colors", jsonColors->ToString().c_str(), filter);
132         } else {
133             ToJsonColor(json, filter);
134             ToJsonIndicator(json, filter);
135             ToJsonTrackShadow(json, filter);
136         }
137     }
138 
ToJsonColor(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter)139     void ToJsonColor(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
140     {
141         /* no fixed attr below, just return */
142         if (filter.IsFastFilter()) {
143             return;
144         }
145         if (!propGaugeType_.has_value()) {
146             auto jsonColor = JsonUtil::CreateArray(true);
147             for (size_t j = 0; j < GAUGE_DEFAULT_COLOR.size(); j++) {
148                 jsonColor->Put(std::to_string(j).c_str(), GAUGE_DEFAULT_COLOR[j].ColorToString().c_str());
149             }
150             json->PutExtAttr("colors", jsonColor->ToString().c_str(), filter);
151             return;
152         }
153 
154         if (propGaugeType_.value() == GaugeType::TYPE_CIRCULAR_MONOCHROME) {
155             if (propGradientColors_.has_value()) {
156                 json->PutExtAttr("colors",
157                     propGradientColors_.value().at(0).at(0).first.ColorToString().c_str(), filter);
158             }
159             return;
160         }
161 
162         if (propGaugeType_.value() == GaugeType::TYPE_CIRCULAR_SINGLE_SEGMENT_GRADIENT) {
163             if (propGradientColors_.has_value()) {
164                 auto jsonColor = JsonUtil::CreateArray(true);
165                 auto colorStopArray = propGradientColors_.value().at(0);
166                 for (size_t j = 0; j < colorStopArray.size(); j++) {
167                     auto jsonColorObject = JsonUtil::CreateArray(true);
168                     jsonColorObject->Put("0", colorStopArray[j].first.ColorToString().c_str());
169                     jsonColorObject->Put("1", std::to_string(colorStopArray[j].second.Value()).c_str());
170                     auto indexStr = std::to_string(j);
171                     jsonColor->Put(indexStr.c_str(), jsonColorObject);
172                 }
173                 json->PutExtAttr("colors", jsonColor->ToString().c_str(), filter);
174             }
175             return;
176         }
177         ToJsonColorHasValue(json, filter);
178     }
179 
ToJsonColorHasValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter)180     void ToJsonColorHasValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
181     {
182         auto jsonGradientColors = JsonUtil::CreateArray(true);
183         if (propGradientColors_.has_value() && propValues_.has_value() &&
184             (propGradientColors_.value().size() == propValues_.value().size())) {
185             for (size_t i = 0; i < propValues_.value().size(); i++) {
186                 auto jsonObject = JsonUtil::CreateArray(true);
187                 auto jsonColor = JsonUtil::CreateArray(true);
188                 auto colorStopArray = propGradientColors_.value()[i];
189                 for (size_t j = 0; j < colorStopArray.size(); j++) {
190                     auto jsonColorObject = JsonUtil::CreateArray(true);
191                     jsonColorObject->Put("0", colorStopArray[j].first.ColorToString().c_str());
192                     jsonColorObject->Put("1", std::to_string(colorStopArray[j].second.Value()).c_str());
193                     auto indexStr = std::to_string(j);
194                     jsonColor->Put(indexStr.c_str(), jsonColorObject);
195                 }
196                 jsonObject->Put("0", jsonColor);
197                 jsonObject->Put("1", propValues_.value()[i]);
198                 auto index = std::to_string(i);
199                 jsonGradientColors->Put(index.c_str(), jsonObject);
200             }
201         }
202         json->PutExtAttr("colors", jsonGradientColors->ToString().c_str(), filter);
203     }
204 
ToJsonIndicator(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter)205     void ToJsonIndicator(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
206     {
207         /* no fixed attr below, just return */
208         if (filter.IsFastFilter()) {
209             return;
210         }
211         if (!propIsShowIndicator_.value_or(true)) {
212             json->PutExtAttr("indicator", "null", filter);
213             return;
214         }
215         auto indicatorJsonValue = JsonUtil::Create(true);
216         if (propIndicatorIconSourceInfo_.has_value()) {
217             indicatorJsonValue->Put("icon", propIndicatorIconSourceInfo_.value().GetSrc().c_str());
218         } else {
219             indicatorJsonValue->Put("icon", "SystemStyle");
220         }
221 
222         if (propIndicatorSpace_.has_value()) {
223             indicatorJsonValue->Put("space", propIndicatorSpace_.value().ToString().c_str());
224         } else {
225             indicatorJsonValue->Put("space", INDICATOR_DISTANCE_TO_TOP.ToString().c_str());
226         }
227         json->PutExtAttr("indicator", indicatorJsonValue, filter);
228     }
229 
ToJsonTrackShadow(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter)230     void ToJsonTrackShadow(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
231     {
232         /* no fixed attr below, just return */
233         if (filter.IsFastFilter()) {
234             return;
235         }
236         GaugeShadowOptions trackShadow;
237         if (propShadowOptions_.has_value()) {
238             trackShadow.radius = propShadowOptions_.value().radius;
239             trackShadow.offsetX = propShadowOptions_.value().offsetX;
240             trackShadow.offsetY = propShadowOptions_.value().offsetY;
241             trackShadow.isShadowVisible = propShadowOptions_.value().isShadowVisible;
242         } else {
243             trackShadow.radius = DEFAULT_GAUGE_SHADOW_RADIUS;
244             trackShadow.offsetX = DEFAULT_GAUGE_SHADOW_OFFSETX;
245             trackShadow.offsetY = DEFAULT_GAUGE_SHADOW_OFFSETY;
246         }
247 
248         if (!trackShadow.isShadowVisible) {
249             json->PutExtAttr("trackShadow", "null", filter);
250             return;
251         }
252 
253         auto shadowOptionJson = JsonUtil::Create(true);
254         shadowOptionJson->Put("radius", std::to_string(trackShadow.radius).c_str());
255         shadowOptionJson->Put("offsetX", std::to_string(trackShadow.offsetX).c_str());
256         shadowOptionJson->Put("offsetY", std::to_string(trackShadow.offsetY).c_str());
257 
258         json->PutExtAttr("trackShadow", shadowOptionJson, filter);
259     }
260 
261     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(Value, float, PROPERTY_UPDATE_RENDER);
262     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(Min, float, PROPERTY_UPDATE_RENDER);
263     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(Max, float, PROPERTY_UPDATE_RENDER);
264     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(StartAngle, float, PROPERTY_UPDATE_RENDER);
265     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(EndAngle, float, PROPERTY_UPDATE_RENDER);
266     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(GaugeType, GaugeType, PROPERTY_UPDATE_RENDER);
267     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(Colors, std::vector<Color>, PROPERTY_UPDATE_RENDER);
268     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(GradientColors, std::vector<ColorStopArray>, PROPERTY_UPDATE_RENDER);
269     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(Values, std::vector<float>, PROPERTY_UPDATE_RENDER);
270     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(StrokeWidth, Dimension, PROPERTY_UPDATE_RENDER);
271     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(ShadowOptions, GaugeShadowOptions, PROPERTY_UPDATE_RENDER);
272     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(IsShowIndicator, bool, PROPERTY_UPDATE_RENDER);
273     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(IndicatorIconSourceInfo, ImageSourceInfo, PROPERTY_UPDATE_RENDER);
274     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(IndicatorSpace, Dimension, PROPERTY_UPDATE_RENDER);
275     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(IndicatorChange, bool, PROPERTY_UPDATE_RENDER);
276     ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(IsSensitive, bool, PROPERTY_UPDATE_RENDER);
277     ACE_DISALLOW_COPY_AND_MOVE(GaugePaintProperty);
278 };
279 
280 } // namespace OHOS::Ace::NG
281 
282 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GAUGE_GAUGE_PAINT_PROPERTY_H
283