• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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/common/dom/dom_progress.h"
17 
18 #include "base/utils/utils.h"
19 #include "core/components/common/properties/decoration.h"
20 #include "core/components/progress/progress_theme.h"
21 #include "core/components/theme/theme_manager.h"
22 #include "frameworks/bridge/common/utils/utils.h"
23 
24 namespace OHOS::Ace::Framework {
25 
26 
IsGradient(const std::string & value)27 bool IsGradient(const std::string& value)
28 {
29     auto gradientJson = JsonUtil::ParseJsonString(value);
30     if (!gradientJson->IsObject()) {
31         return false;
32     }
33     return true;
34 }
35 
ParseGradient(const DOMProgress & progress,const std::string & value)36 Gradient ParseGradient(const DOMProgress& progress, const std::string& value)
37 {
38     // only support linear gradient
39     auto gradientJson = JsonUtil::ParseJsonString(value);
40     Gradient gradient = Gradient();
41     if (!gradientJson->IsObject()) {
42         LOGW("gradientJson json param error");
43         return gradient;
44     }
45     auto gradientValue = gradientJson->GetValue(DOM_VALUES);
46     if ((gradientValue == nullptr) || (!gradientValue->IsArray()) || (gradientValue->GetArraySize() <= 0)) {
47         LOGW("gradientValue json param error");
48         return gradient;
49     }
50     auto values = gradientValue->GetArrayItem(0);
51     gradient.SetDirection(GradientDirection::START_TO_END);
52     auto colors = values->GetValue(DOM_GRADIENT_VALUES);
53     if (colors != nullptr && colors->IsArray()) {
54         for (int32_t index = 0; index < colors->GetArraySize(); index++) {
55             // remove the " at front and end. check the color string longer than ""
56             // "#FFFFFF" -> #FFFFFF
57             if (colors->GetArrayItem(index)->ToString().length() > 2) {
58                 gradient.AddColor(GradientColor(progress.ParseColor(colors->GetArrayItem(index)->ToString().substr(
59                     1, colors->GetArrayItem(index)->ToString().length() - 2))));
60             }
61         }
62     }
63     return gradient;
64 }
65 
CreateProgressComponent(double min,double percent,double cachedValue,double max,ProgressType type)66 RefPtr<ProgressComponent> DOMProgress::CreateProgressComponent(
67     double min, double percent, double cachedValue, double max, ProgressType type)
68 {
69     if (type == ProgressType::CIRCLE) {
70         return AceType::MakeRefPtr<ProgressComponent>(min, percent, cachedValue, max, ProgressType::LINEAR);
71     }
72     return AceType::MakeRefPtr<ProgressComponent>(min, percent, cachedValue, max, type);
73 }
74 
DOMProgress(NodeId nodeId,const std::string & nodeName)75 DOMProgress::DOMProgress(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName) {}
76 
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)77 bool DOMProgress::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
78 {
79     static const LinearMapNode<void (*)(const std::string&, DOMProgress&)> progressAttrsOperators[] = {
80         { DOM_RING_CLOCKWISH_DIRECTION,
81             [](const std::string& val, DOMProgress& progress) { progress.clockwiseDirection_ = StringToBool(val); } },
82         { DOM_EFFECTS_ON,
83             [](const std::string& val, DOMProgress& progress) { progress.showAnimationEffect_ = StringToBool(val); } },
84         { DOM_PROGRESS_PERCENT,
85             [](const std::string& val, DOMProgress& progress) {
86                 progress.percent_ = StringToDouble(val);
87                 if (progress.percent_ > progress.max_) {
88                     progress.percent_ = progress.max_;
89                 }
90                 if (progress.percent_ < progress.min_) {
91                     progress.percent_ = progress.min_;
92                 }
93             } },
94         { DOM_PROGRESS_SECONDARY_PERCENT,
95             [](const std::string& val, DOMProgress& progress) {
96                 progress.cachedValue_ = StringToDouble(val);
97                 if (progress.cachedValue_ > progress.max_) {
98                     progress.cachedValue_ = progress.max_;
99                 }
100                 if (progress.cachedValue_ < progress.min_) {
101                     progress.cachedValue_ = progress.min_;
102                 }
103             } },
104         { DOM_PROGRESS_TYPE,
105             [](const std::string& val, DOMProgress& progress) {
106                 if (val == DOM_PROGRESS_TYPE_CIRCULAR) {
107                     progress.type_ = ProgressType::CIRCLE;
108                 } else if (val == DOM_PROGRESS_TYPE_RING) {
109                     progress.type_ = ProgressType::RING;
110                 } else if (val == DOM_PROGRESS_TYPE_HORIZONTAL) {
111                     progress.type_ = ProgressType::LINEAR;
112                 } else if (val == DOM_PROGRESS_TYPE_SCALE) {
113                     progress.type_ = ProgressType::SCALE;
114                 } else if (val == DOM_PROGRESS_TYPE_MOON) {
115                     progress.type_ = ProgressType::MOON;
116                 } else if ((val == DOM_PROGRESS_TYPE_ARC)) {
117                     progress.type_ = ProgressType::ARC;
118                 } else if ((val == DOM_PROGRESS_TYPE_BUBBLE)) {
119                     progress.type_ = ProgressType::BUBBLE;
120                 } else {
121                     progress.type_ = ProgressType::LINEAR;
122                 }
123             } },
124     };
125     auto operatorIter =
126         BinarySearchFindIndex(progressAttrsOperators, ArraySize(progressAttrsOperators), attr.first.c_str());
127     if (operatorIter != -1) {
128         progressAttrsOperators[operatorIter].value(attr.second, *this);
129         return true;
130     }
131     return false;
132 }
133 
SetSpecializedStyle(const std::pair<std::string,std::string> & style)134 bool DOMProgress::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
135 {
136     // static linear map must be sorted by key.
137     static const LinearMapNode<void (*)(const std::string&, DOMProgress&)> progressStylesOperators[] = {
138         { DOM_PROGRESS_BACKGROUND_COLOR,
139             [](const std::string& val, DOMProgress& progress) {
140                 progress.backgroundColor_.first = progress.ParseColor(val);
141                 progress.backgroundColor_.second = true;
142             } },
143         { DOM_PROGRESS_BUBBLE_RADIUS,
144             [](const std::string& val, DOMProgress& progress) {
145                 progress.diameter_ = progress.ParseDimension(val);
146             } },
147         { DOM_CENTER_X,
148             [](const std::string& val, DOMProgress& progress) {
149                 progress.centerX_.first = StringToDouble(val);
150                 progress.centerX_.second = true;
151             } },
152         { DOM_CENTER_Y,
153             [](const std::string& val, DOMProgress& progress) {
154                 progress.centerY_.first = StringToDouble(val);
155                 progress.centerY_.second = true;
156             } },
157         { DOM_PROGRESS_COLOR,
158             [](const std::string& val, DOMProgress& progress) {
159                 if (IsGradient(val)) {
160                     progress.gradient_ = ParseGradient(progress, val);
161                 } else {
162                     progress.color_.first = progress.ParseColor(val);
163                     progress.color_.second = true;
164                 }
165             } },
166         { DOM_PROGRESS_DIAMETER,
167             [](const std::string& val, DOMProgress& progress) {
168                 progress.bubbleRadius_ = progress.ParseDimension(val);
169             } },
170         { DOM_DIRECTION,
171             [](const std::string& val, DOMProgress& progress) { progress.isStartToEnd_ = val == DOM_START_TO_END; } },
172         { DOM_PROGRESS_RADIUS,
173             [](const std::string& val, DOMProgress& progress) {
174                 progress.radius_.first = StringToDouble(val);
175                 progress.radius_.second = true;
176             } },
177         { DOM_SCALE_NUMBER,
178             [](const std::string& val, DOMProgress& progress) {
179                 progress.scaleNumber_.first = StringUtils::StringToInt(val);
180                 progress.scaleNumber_.second = true;
181             } },
182         { DOM_SCALE_WIDTH,
183             [](const std::string& val, DOMProgress& progress) {
184                 progress.scaleWidth_.first = progress.ParseDimension(val);
185                 progress.scaleWidth_.second = true;
186             } },
187         { DOM_PROGRESS_SECONDARY_COLOR,
188             [](const std::string& val, DOMProgress& progress) {
189                 progress.cachedColor_.first = progress.ParseColor(val);
190                 progress.cachedColor_.second = true;
191             } },
192         { DOM_START_DEGREE,
193             [](const std::string& val, DOMProgress& progress) { progress.startDegree_ = StringToDouble(val); } },
194         { DOM_PROGRESS_STROKE_WIDTH,
195             [](const std::string& val, DOMProgress& progress) {
196                 progress.strokeWidth_.first = progress.ParseDimension(val);
197                 progress.strokeWidth_.second = true;
198             } },
199         { DOM_SWEEP_DEGREE,
200             [](const std::string& val, DOMProgress& progress) { progress.sweepDegree_ = StringToDouble(val); } },
201     };
202     auto operatorIter =
203         BinarySearchFindIndex(progressStylesOperators, ArraySize(progressStylesOperators), style.first.c_str());
204     if (operatorIter != -1) {
205         progressStylesOperators[operatorIter].value(style.second, *this);
206         return true;
207     }
208     return false;
209 }
210 
PrepareSpecializedComponent()211 void DOMProgress::PrepareSpecializedComponent()
212 {
213     InitProgressIfNeed();
214     if (type_ == ProgressType::CIRCLE) {
215         loadingProgressChild_->SetProgressColor(color_.first);
216         return;
217     }
218     if (type_ == ProgressType::BUBBLE) {
219         bubbleProgressChild_->SetBubbleRadius(bubbleRadius_);
220         bubbleProgressChild_->SetDiameter(diameter_);
221         return;
222     }
223     progressChild_->SetMaxValue(max_);
224     progressChild_->SetMinValue(min_);
225     progressChild_->SetValue(percent_);
226     progressChild_->SetCachedValue(cachedValue_);
227     progressChild_->GetTrack()->SetSelectColor(color_.first);
228     progressChild_->GetTrack()->SetCachedColor(cachedColor_.first);
229     progressChild_->GetTrack()->SetBackgroundColor(backgroundColor_.first);
230     progressChild_->GetTrack()->SetTrackThickness(strokeWidth_.first);
231     progressChild_->GetTrack()->SetShowAnimation(showAnimationEffect_);
232     progressChild_->SetAnimationPlay(showAnimationEffect_);
233     progressChild_->GetTrack()->SetTextDirection(
234         IsRightToLeft() && isStartToEnd_ ? TextDirection::RTL : TextDirection::LTR);
235     if (gradient_.IsValid()) {
236         progressChild_->GetTrack()->SetSelectGradient(gradient_);
237     }
238     if (type_ == ProgressType::RING) {
239         auto info = progressChild_->GetTrack()->GetTrackInfo();
240         info->SetClockwise(clockwiseDirection_);
241     } else if (type_ == ProgressType::SCALE) {
242         auto info = progressChild_->GetTrack()->GetTrackInfo();
243         info->SetScaleWidth(scaleWidth_.first);
244         info->SetScaleNumber(scaleNumber_.first);
245         info->SetClockwise(clockwiseDirection_);
246     } else if (type_ == ProgressType::ARC) {
247         // draw arc progress
248         progressChild_->GetTrack()->GetTrackInfo()->SetStartDegree(startDegree_);
249         progressChild_->GetTrack()->GetTrackInfo()->SetSweepDegree(sweepDegree_);
250         if (radius_.second) {
251             progressChild_->GetTrack()->SetRadius(radius_.first);
252         }
253         if (centerX_.second) {
254             progressChild_->GetTrack()->SetCenterX(centerX_.first);
255         }
256         if (centerY_.second) {
257             progressChild_->GetTrack()->SetCenterY(centerY_.first);
258         }
259     }
260 }
261 
OnSetStyleFinished()262 void DOMProgress::OnSetStyleFinished()
263 {
264     // the range is from -360 to 360 degree
265     static constexpr double defaultStartDegree = -120;
266     static constexpr double defaultSweepDegree = 240;
267     if (startDegree_ > 360.0 || startDegree_ < -360.0) {
268         startDegree_ = defaultStartDegree;
269         sweepDegree_ = defaultSweepDegree;
270         return;
271     }
272     if (sweepDegree_ > 360.0 || sweepDegree_ < -360.0) {
273         startDegree_ = defaultStartDegree;
274         sweepDegree_ = defaultSweepDegree;
275         return;
276     }
277 }
278 
GetSpecializedComponent()279 RefPtr<Component> DOMProgress::GetSpecializedComponent()
280 {
281     if (type_ == ProgressType::CIRCLE) {
282         return loadingProgressChild_;
283     } else if (type_ == ProgressType::BUBBLE) {
284         return bubbleProgressChild_;
285     } else {
286         return progressChild_;
287     }
288 }
289 
InitProgressIfNeed()290 void DOMProgress::InitProgressIfNeed()
291 {
292     auto theme = GetTheme<ProgressTheme>();
293     if (type_ == ProgressType::CIRCLE) {
294         // Width_ and height_ in circular progress are usually the same with diameter in loading progress component.
295         // If width_ and height_ are different, choose smaller one as diameter.
296         if (!loadingProgressChild_) {
297             loadingProgressChild_ = AceType::MakeRefPtr<LoadingProgressComponent>();
298         }
299         if (theme) {
300             if (!color_.second) {
301                 color_.first = theme->GetProgressColor();
302             }
303             loadingProgressChild_->SetMoveRatio(theme->GetMoveRatio());
304             loadingProgressChild_->SetRingRadius(theme->GetRingRadius());
305             loadingProgressChild_->SetOrbitRadius(theme->GetOrbitRadius());
306             loadingProgressChild_->SetCometTailLen(theme->GetCometTailLen());
307         }
308         return;
309     }
310 
311     if (type_ == ProgressType::BUBBLE) {
312         if (!bubbleProgressChild_) {
313             bubbleProgressChild_ = AceType::MakeRefPtr<BubbleProgressComponent>();
314         }
315         return;
316     }
317 
318     if (!progressChild_ || progressChild_->GetType() != type_) {
319         progressChild_ = CreateProgressComponent(min_, percent_, cachedValue_, max_, type_);
320     }
321     if (!theme) {
322         return;
323     }
324     if (!color_.second) {
325         color_.first = type_ == ProgressType::MOON ? theme->GetMoonFrontColor() : theme->GetTrackSelectedColor();
326     }
327     if (!backgroundColor_.second) {
328         backgroundColor_.first =
329             type_ == ProgressType::MOON ? theme->GetMoonBackgroundColor() : theme->GetTrackBgColor();
330     }
331     if (!cachedColor_.second) {
332         cachedColor_.first = theme->GetTrackCachedColor();
333     }
334     if (!strokeWidth_.second) {
335         if (type_ == ProgressType::SCALE) {
336             strokeWidth_.first = theme->GetScaleLength();
337         } else if (type_ == ProgressType::RING) {
338             strokeWidth_.first = theme->GetRingThickness();
339         } else {
340             strokeWidth_.first = theme->GetTrackThickness();
341         }
342     }
343     if (!scaleWidth_.second) {
344         scaleWidth_.first = theme->GetScaleWidth();
345     }
346     if (!scaleNumber_.second) {
347         scaleNumber_.first = theme->GetScaleNumber();
348     }
349 }
350 
351 } // namespace OHOS::Ace::Framework
352