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