• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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