1 /*
2 * Copyright (c) 2024 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 #include "core/components_ng/pattern/linear_indicator/linear_indicator_pattern.h"
16
17 #include "base/log/dump_log.h"
18 #include "core/components_ng/pattern/linear_indicator/linear_indicator_accessibility_property.h"
19 #include "core/components_ng/pattern/progress/progress_pattern.h"
20 #include "core/pipeline_ng/pipeline_context.h"
21
22 namespace OHOS::Ace::NG {
23
LinearIndicatorPattern()24 LinearIndicatorPattern::LinearIndicatorPattern()
25 : LinearLayoutPattern(false), direction_(TextDirection::AUTO), hasVisibleChangeRegistered_(false),
26 isVisibleChangePause_(false)
27 {
28 controller_ = AceType::MakeRefPtr<LinearIndicatorController>(AceType::WeakClaim(this));
29 auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
30 CHECK_NULL_VOID(pipeline);
31 theme_ = pipeline->GetThemeManager()->GetTheme<LinearIndicatorTheme>();
32 CHECK_NULL_VOID(theme_);
33 strokeWidth_ = theme_->GetDefaultStrokeWidth();
34 strokeRadius_ = theme_->GetDefaultStrokeRadius();
35 trackBackgroundColor_ = theme_->GetTrackBackgroundColor();
36 trackColor_ = theme_->GetTrackColor();
37 };
38
39 LinearIndicatorPattern::~LinearIndicatorPattern() = default;
40
CreateLayoutProperty()41 RefPtr<LayoutProperty> LinearIndicatorPattern::CreateLayoutProperty()
42 {
43 auto property = MakeRefPtr<LinearIndicatorLayoutProperty>();
44 if (theme_) {
45 property->UpdatePadding({ CalcLength(theme_->GetPaddingLeft()), CalcLength(theme_->GetPaddingRight()),
46 CalcLength(theme_->GetPaddingTop()), CalcLength(theme_->GetPaddingBottom()) });
47 property->UpdateSpace(theme_->GetDefaultSpace());
48 property->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(theme_->GetDefaultHeight())));
49 }
50 return property;
51 }
52
OnModifyDone()53 void LinearIndicatorPattern::OnModifyDone()
54 {
55 LinearLayoutPattern::OnModifyDone();
56 UpdateProgressNode();
57 RegisterVisibleChange();
58 }
59
UpdateProgressNode()60 void LinearIndicatorPattern::UpdateProgressNode()
61 {
62 auto host = GetHost();
63 CHECK_NULL_VOID(host);
64 RefPtr<LinearIndicatorLayoutProperty> layoutProperty = GetLayoutProperty<LinearIndicatorLayoutProperty>();
65 CHECK_NULL_VOID(layoutProperty);
66 CHECK_NULL_VOID(theme_);
67 std::size_t oldCount = GetProgressSize();
68 std::size_t newCount = layoutProperty->GetProgressCountValue(theme_->GetDefaultProgressCount());
69 if (oldCount > newCount) {
70 for (std::size_t i = oldCount; i > newCount; --i) {
71 host->RemoveChildAtIndex(i - 1);
72 }
73 oldCount = newCount;
74 }
75 if (IsChangeLayoutPropertyAndUpdate(layoutProperty)) {
76 for (std::size_t i = 0; i < oldCount; ++i) {
77 UpdateProgressNodeAtIndex(i);
78 }
79 }
80 for (std::size_t i = oldCount; i < newCount; ++i) {
81 AddProgressNode();
82 }
83 controller_->UpdateProgressSize(newCount);
84 controller_->Loop(layoutProperty->GetLoopValue(theme_->GetDefaultLoop()));
85 }
86
IsChangeLayoutPropertyAndUpdate(RefPtr<LinearIndicatorLayoutProperty> layoutProperty)87 bool LinearIndicatorPattern::IsChangeLayoutPropertyAndUpdate(RefPtr<LinearIndicatorLayoutProperty> layoutProperty)
88 {
89 bool ret = false;
90 CHECK_NULL_RETURN(layoutProperty, ret);
91 CHECK_NULL_RETURN(theme_, ret);
92
93 Dimension strokeWidth = layoutProperty->GetStrokeWidthValue(theme_->GetDefaultStrokeWidth());
94 Dimension strokeRadius = layoutProperty->GetStrokeRadiusValue(theme_->GetDefaultStrokeRadius());
95 Color trackBackgroundColor = layoutProperty->GetTrackBackgroundColorValue(theme_->GetTrackBackgroundColor());
96 Color trackColor = layoutProperty->GetTrackColorValue(theme_->GetTrackColor());
97 TextDirection direction = layoutProperty->GetLayoutDirection();
98
99 float progressWidth = .0f;
100 if (CalcProgressWidth(progressWidth) && GreatNotEqual(strokeWidth.ConvertToPx(), progressWidth)) {
101 strokeWidth = Dimension(progressWidth, DimensionUnit::PX);
102 }
103 if (strokeWidth != strokeWidth_) {
104 strokeWidth_ = strokeWidth;
105 ret = true;
106 }
107 if (strokeRadius != strokeRadius_) {
108 strokeRadius_ = strokeRadius;
109 ret = true;
110 }
111 if (trackBackgroundColor != trackBackgroundColor_) {
112 trackBackgroundColor_ = trackBackgroundColor;
113 ret = true;
114 }
115 if (trackColor != trackColor_) {
116 trackColor_ = trackColor;
117 ret = true;
118 }
119 if (direction != direction_) {
120 direction_ = direction;
121 ret = true;
122 }
123 return ret;
124 }
125
UpdateProgressNodeAtIndex(std::size_t index)126 void LinearIndicatorPattern::UpdateProgressNodeAtIndex(std::size_t index)
127 {
128 auto progressNode = GetProgressNode(index);
129 CHECK_NULL_VOID(progressNode);
130 auto progressPaintProperty = progressNode->GetPaintProperty<NG::ProgressPaintProperty>();
131 CHECK_NULL_VOID(progressPaintProperty);
132 auto progressLayoutProperty = progressNode->GetLayoutProperty<ProgressLayoutProperty>();
133 CHECK_NULL_VOID(progressLayoutProperty);
134 progressPaintProperty->UpdateColor(trackColor_);
135 progressPaintProperty->UpdateBackgroundColor(trackBackgroundColor_);
136 progressLayoutProperty->UpdateStrokeWidth(strokeWidth_);
137 progressPaintProperty->UpdateStrokeRadius(strokeRadius_);
138 progressLayoutProperty->UpdateLayoutDirection(direction_);
139 progressNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
140 }
141
AddProgressNode()142 void LinearIndicatorPattern::AddProgressNode()
143 {
144 auto host = GetHost();
145 CHECK_NULL_VOID(host);
146 auto progressNodeId = ElementRegister::GetInstance()->MakeUniqueId();
147 auto progressNode = FrameNode::GetOrCreateFrameNode(
148 V2::PROGRESS_ETS_TAG, progressNodeId, []() { return AceType::MakeRefPtr<ProgressPattern>(); });
149 auto progressPaintProperty = progressNode->GetPaintProperty<NG::ProgressPaintProperty>();
150 auto progressLayoutProperty = progressNode->GetLayoutProperty<ProgressLayoutProperty>();
151 progressPaintProperty->UpdateColor(trackColor_);
152 progressPaintProperty->UpdateBackgroundColor(trackBackgroundColor_);
153 progressPaintProperty->UpdateEnableSmoothEffect(false);
154 progressLayoutProperty->UpdateLayoutWeight(1);
155 progressLayoutProperty->UpdateStrokeWidth(strokeWidth_);
156 progressPaintProperty->UpdateStrokeRadius(strokeRadius_);
157 progressLayoutProperty->UpdateLayoutDirection(direction_);
158 host->AddChild(progressNode);
159 }
160
GetProgressSize()161 std::size_t LinearIndicatorPattern::GetProgressSize()
162 {
163 auto host = GetHost();
164 CHECK_NULL_RETURN(host, 0);
165 return host->GetChildren().size();
166 }
167
GetProgressNode(int32_t index)168 RefPtr<FrameNode> LinearIndicatorPattern::GetProgressNode(int32_t index)
169 {
170 auto host = GetHost();
171 CHECK_NULL_RETURN(host, nullptr);
172 return AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(index));
173 }
174
RegisterVisibleChange()175 void LinearIndicatorPattern::RegisterVisibleChange()
176 {
177 if (hasVisibleChangeRegistered_) {
178 return;
179 }
180 auto pipeline = PipelineContext::GetCurrentContext();
181 CHECK_NULL_VOID(pipeline);
182 auto host = GetHost();
183 CHECK_NULL_VOID(host);
184
185 auto callback = [weak = WeakClaim(this)](bool visible, double ratio) {
186 auto pattern = weak.Upgrade();
187 CHECK_NULL_VOID(pattern);
188 pattern->VisibleChange(visible);
189 };
190 std::vector<double> ratioList = { 0.0 };
191 pipeline->AddVisibleAreaChangeNode(host, ratioList, std::move(callback), false);
192 hasVisibleChangeRegistered_ = true;
193 }
194
VisibleChange(bool visible)195 void LinearIndicatorPattern::VisibleChange(bool visible)
196 {
197 if (visible) {
198 if (isVisibleChangePause_) {
199 isVisibleChangePause_ = false;
200 controller_->Start(controller_->TotalAnimationTime(), controller_->TotalIntervalTime());
201 }
202 } else {
203 if (controller_->IsRuning()) {
204 isVisibleChangePause_ = true;
205 controller_->Pause();
206 }
207 }
208 }
209
CalcProgressWidth(float & progressWidth)210 bool LinearIndicatorPattern::CalcProgressWidth(float& progressWidth)
211 {
212 CHECK_NULL_RETURN(theme_, false);
213 auto layoutProperty = GetLayoutProperty<LinearIndicatorLayoutProperty>();
214 CHECK_NULL_RETURN(layoutProperty, false);
215
216 auto contentSize = GetHostFrameSize();
217 CHECK_NULL_RETURN(contentSize, false);
218
219 float width = contentSize->Width();
220 if (NearZero(width)) {
221 return false;
222 }
223 std::size_t progressCount = layoutProperty->GetProgressCount().value_or(theme_->GetDefaultProgressCount());
224 if (progressCount == 0) {
225 return false;
226 }
227
228 PaddingPropertyF padding = layoutProperty->CreatePaddingAndBorder();
229 float leftPadding = padding.left.value_or(theme_->GetPaddingLeft().ConvertToPx());
230 float rightPadding = padding.right.value_or(theme_->GetPaddingRight().ConvertToPx());
231 float space = layoutProperty->GetSpace().value_or(theme_->GetDefaultSpace()).ConvertToPx();
232
233 float ret = (width - leftPadding - rightPadding - (space * (progressCount - 1))) / progressCount;
234 progressWidth = std::clamp(ret, .0f, width);
235 return true;
236 }
237
DumpInfo()238 void LinearIndicatorPattern::DumpInfo()
239 {
240 auto layoutProperty = GetLayoutProperty<LinearIndicatorLayoutProperty>();
241 CHECK_NULL_VOID(layoutProperty);
242 auto pipeline = PipelineBase::GetCurrentContext();
243 CHECK_NULL_VOID(pipeline);
244 auto theme = pipeline->GetThemeManager()->GetTheme<NG::LinearIndicatorTheme>();
245 CHECK_NULL_VOID(theme);
246
247 DumpLog::GetInstance().AddDesc(std::string("indicatorStyle.space"),
248 layoutProperty->GetSpaceValue(theme->GetDefaultSpace()).ToString().c_str());
249 DumpLog::GetInstance().AddDesc(std::string("indicatorStyle.strokeWidth"),
250 layoutProperty->GetStrokeWidthValue(theme->GetDefaultStrokeWidth()).ToString().c_str());
251 DumpLog::GetInstance().AddDesc(std::string("indicatorStyle.strokeRadius"),
252 layoutProperty->GetStrokeRadiusValue(theme->GetDefaultStrokeRadius()).ToString().c_str());
253 DumpLog::GetInstance().AddDesc(std::string("indicatorStyle.trackBackgroundColor"),
254 layoutProperty->GetTrackBackgroundColorValue(theme->GetTrackBackgroundColor()).ColorToString().c_str());
255 DumpLog::GetInstance().AddDesc(std::string("indicatorStyle.trackColor"),
256 layoutProperty->GetTrackColorValue(theme->GetTrackColor()).ColorToString().c_str());
257
258 DumpLog::GetInstance().AddDesc(
259 std::string("indicatorLoop"), layoutProperty->GetLoopValue(theme->GetDefaultLoop()) ? "True" : "False");
260 DumpLog::GetInstance().AddDesc(
261 std::string("count"), layoutProperty->GetProgressCountValue(theme->GetDefaultProgressCount()));
262 }
263
DumpInfo(std::unique_ptr<JsonValue> & json)264 void LinearIndicatorPattern::DumpInfo(std::unique_ptr<JsonValue>& json)
265 {
266 auto layoutProperty = GetLayoutProperty<LinearIndicatorLayoutProperty>();
267 CHECK_NULL_VOID(layoutProperty);
268 auto pipeline = PipelineBase::GetCurrentContext();
269 CHECK_NULL_VOID(pipeline);
270 auto theme = pipeline->GetThemeManager()->GetTheme<NG::LinearIndicatorTheme>();
271 CHECK_NULL_VOID(theme);
272 json->Put("indicatorStyle.space", layoutProperty->GetSpaceValue(theme->GetDefaultSpace()).ToString().c_str());
273 json->Put("indicatorStyle.strokeWidth",
274 layoutProperty->GetStrokeWidthValue(theme->GetDefaultStrokeWidth()).ToString().c_str());
275 json->Put("indicatorStyle.strokeRadius",
276 layoutProperty->GetStrokeRadiusValue(theme->GetDefaultStrokeRadius()).ToString().c_str());
277 json->Put("indicatorStyle.trackBackgroundColor",
278 layoutProperty->GetTrackBackgroundColorValue(theme->GetTrackBackgroundColor()).ColorToString().c_str());
279 json->Put("indicatorStyle.trackColor",
280 layoutProperty->GetTrackColorValue(theme->GetTrackColor()).ColorToString().c_str());
281
282 json->Put("indicatorLoop", layoutProperty->GetLoopValue(theme->GetDefaultLoop()) ? "True" : "False");
283 json->Put("count", layoutProperty->GetProgressCountValue(theme->GetDefaultProgressCount()));
284 }
285
CreateAccessibilityProperty()286 RefPtr<AccessibilityProperty> LinearIndicatorPattern::CreateAccessibilityProperty()
287 {
288 return MakeRefPtr<LinearIndicatorAccessibilityProperty>();
289 }
290 } // namespace OHOS::Ace::NG
291