• 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 
16 #include "core/components_ng/pattern/linear_indicator/linear_indicator_controller.h"
17 
18 #include "core/components_ng/pattern/linear_indicator/linear_indicator_pattern.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 {
LinearIndicatorControllerData()23 LinearIndicatorControllerData::LinearIndicatorControllerData()
24     : progressAnimation_(nullptr), animationTag_(0), progressInterval_(),
25       totalAnimationTime_(LinearIndicatorController::ANIMATION_TIME_MIN), totalIntervalTime_(0), isLoop_(true)
26 {
27     InitData();
28 }
29 
InitData()30 void LinearIndicatorControllerData::InitData()
31 {
32     state_ = LinearIndicatorControllerDataState::STOP;
33     index_ = 0;
34     value_ = .0f;
35     intervalConsumeTime_ = 0;
36     intervalStart_ = std::chrono::system_clock::time_point();
37 }
38 
GetProgressSize() const39 int32_t LinearIndicatorController::GetProgressSize() const
40 {
41     auto host = GetHost();
42     CHECK_NULL_RETURN(host, 0);
43     return host->GetChildren().size();
44 }
45 
GetProgressNode(int32_t index) const46 RefPtr<FrameNode> LinearIndicatorController::GetProgressNode(int32_t index) const
47 {
48     auto host = GetHost();
49     CHECK_NULL_RETURN(host, nullptr);
50     return AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(index));
51 }
52 
InitProgressValue()53 void LinearIndicatorController::InitProgressValue()
54 {
55     int32_t size = GetProgressSize();
56     int32_t index = animationData_.Index();
57     for (int32_t i = 0; i < size; ++i) {
58         float value = .0f;
59         if (i < index) {
60             value = END_VALUE;
61         } else if (i == index) {
62             value = animationData_.Value();
63         }
64         SetProgressComponentValue(i, value);
65     }
66 }
67 
SetProgressComponentValue(int32_t index,float value)68 bool LinearIndicatorController::SetProgressComponentValue(int32_t index, float value)
69 {
70     RefPtr<FrameNode> progressNode = GetProgressNode(index);
71     CHECK_NULL_RETURN(progressNode, false);
72     RefPtr<ProgressPaintProperty> paintProperty = progressNode->GetPaintProperty<ProgressPaintProperty>();
73     CHECK_NULL_RETURN(paintProperty, false);
74     paintProperty->UpdateValue(value);
75     progressNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
76     return true;
77 }
78 
SetProgressValue(float value)79 void LinearIndicatorController::SetProgressValue(float value)
80 {
81     if (!animationData_.IsRuning()) {
82         return;
83     }
84     if (SetProgressComponentValue(animationData_.Index(), value)) {
85         SetValueAndCallback(value, false);
86         return;
87     }
88     StopAnimation(LinearIndicatorControllerDataState::ANIMATION_PAUSE);
89     animationData_.SetIndexAndValue(0, .0f);
90     StartProgressAnimation();
91 }
92 
ProgreAnimationStart()93 void LinearIndicatorController::ProgreAnimationStart()
94 {
95     if (animationData_.Index() == 0) {
96         InitProgressValue();
97     }
98 }
99 
StartProgressInterval(int32_t intervalTime)100 void LinearIndicatorController::StartProgressInterval(int32_t intervalTime)
101 {
102     auto host = GetHost();
103     CHECK_NULL_VOID(host);
104     auto context = host->GetContext();
105     CHECK_NULL_VOID(context);
106     auto taskExecutor = context->GetTaskExecutor();
107     CHECK_NULL_VOID(taskExecutor);
108     animationData_.ProgressIntervalCancel();
109     auto weak = AceType::WeakClaim(this);
110     animationData_.ProgressIntervalReset([weak] {
111         auto control = weak.Upgrade();
112         CHECK_NULL_VOID(control);
113         control->StartProgressAnimation();
114     });
115     taskExecutor->PostDelayedTask(
116         animationData_.ProgressInterval(), TaskExecutor::TaskType::UI, intervalTime, LINEAR_INDICATOR_INTERVAL_NAME);
117     animationData_.SetState(LinearIndicatorControllerDataState::INTERVAL);
118     animationData_.UpdateIntervalStart(animationData_.TotalIntervalTime() - intervalTime);
119 }
120 
ProgreAnimationEnd()121 void LinearIndicatorController::ProgreAnimationEnd()
122 {
123     if (animationData_.IsPause()) {
124         return;
125     }
126     animationData_.ProgressAnimationAndClear();
127     if (!animationData_.IsRuning()) {
128         return;
129     }
130     int32_t index = animationData_.UpdateIndex();
131     int32_t progressSize = GetProgressSize();
132     if (progressSize == 0) {
133         animationData_.SetIndex(0);
134         animationData_.SetState(LinearIndicatorControllerDataState::STOP);
135         return;
136     }
137     if (index >= progressSize) {
138         animationData_.SetIndex(0);
139         if (!animationData_.IsLoop()) {
140             animationData_.SetState(LinearIndicatorControllerDataState::STOP);
141             return;
142         }
143     }
144     StartProgressInterval(animationData_.TotalIntervalTime());
145 }
146 
StartProgressAnimation()147 void LinearIndicatorController::StartProgressAnimation()
148 {
149     if (animationData_.IsProgressAnimation()) {
150         return;
151     }
152     auto host = GetHost();
153     CHECK_NULL_VOID(host);
154     auto weak = AceType::WeakClaim(this);
155     host->CreateAnimatablePropertyFloat(LINEAR_INDICATOR_ANIMATION_NAME, 0, [weak](float value) {
156         auto control = weak.Upgrade();
157         CHECK_NULL_VOID(control);
158         control->SetProgressValue(value);
159     });
160 
161     host->UpdateAnimatablePropertyFloat(LINEAR_INDICATOR_ANIMATION_NAME, animationData_.Value());
162 
163     int32_t animationTime = animationData_.TotalAnimationTime() * (END_VALUE - animationData_.Value()) / END_VALUE;
164     AnimationOption option;
165     option.SetDuration(animationTime);
166     option.SetCurve(Curves::LINEAR);
167 
168     int32_t animationTag = animationData_.UpdateAnimationTag();
169     animationData_.SetProgressAnimation(AnimationUtils::StartAnimation(
170         option,
171         [weak]() {
172             auto control = weak.Upgrade();
173             CHECK_NULL_VOID(control);
174             auto host = control->GetHost();
175             CHECK_NULL_VOID(host);
176             host->UpdateAnimatablePropertyFloat(LINEAR_INDICATOR_ANIMATION_NAME, END_VALUE);
177             control->ProgreAnimationStart();
178         },
179         [weak, animationTag]() {
180             auto control = weak.Upgrade();
181             CHECK_NULL_VOID(control);
182             if (control->animationData_.AnimationTag() != animationTag) {
183                 return;
184             }
185             control->ProgreAnimationEnd();
186         }));
187     animationData_.SetState(LinearIndicatorControllerDataState::ANIMATION);
188 }
189 
PlayingUpdateTime(int32_t animationTime,int32_t intervalTime)190 void LinearIndicatorController::PlayingUpdateTime(int32_t animationTime, int32_t intervalTime)
191 {
192     if (!animationData_.IsRuning()) {
193         return;
194     }
195     if (animationData_.IsTimeEqually(animationTime, intervalTime)) {
196         return;
197     }
198     if (animationData_.State() == LinearIndicatorControllerDataState::INTERVAL) {
199         if (animationData_.IsIntervalTimeEqually(intervalTime)) {
200             animationData_.SetTotalAnimationTime(animationTime);
201         } else {
202             animationData_.ProgressIntervalCancel();
203             animationData_.SetTime(animationTime, intervalTime);
204             int32_t consumeTime = animationData_.IntervalCurrentConsumeTime();
205             if (consumeTime >= intervalTime) {
206                 StartProgressAnimation();
207             } else {
208                 StartProgressInterval(intervalTime - consumeTime);
209             }
210         }
211     } else {
212         if (animationData_.IsAnimationTimeEqually(animationTime)) {
213             animationData_.SetTotalIntervalTime(intervalTime);
214         } else {
215             StopAnimation(LinearIndicatorControllerDataState::ANIMATION_PAUSE);
216             SetValueAndCallback(RecalcProgressValue(animationTime), true);
217             animationData_.SetTime(animationTime, intervalTime);
218             StartProgressAnimation();
219         }
220     }
221 }
222 
Start(int32_t animationTime,int32_t intervalTime)223 void LinearIndicatorController::Start(int32_t animationTime, int32_t intervalTime)
224 {
225     animationTime = std::max(animationTime, ANIMATION_TIME_MIN);
226     intervalTime = std::max(intervalTime, 0);
227     if (animationData_.IsRuning()) {
228         PlayingUpdateTime(animationTime, intervalTime);
229     } else if (animationData_.IsPause()) {
230         if (animationData_.State() == LinearIndicatorControllerDataState::INTERVAL_PAUSE) {
231             animationData_.SetTime(animationTime, intervalTime);
232             int32_t consumeTime = animationData_.IntervalConsumeTime();
233             if (consumeTime >= intervalTime) {
234                 StartProgressAnimation();
235             } else {
236                 StartProgressInterval(intervalTime - consumeTime);
237             }
238         } else {
239             SetValueAndCallback(RecalcProgressValue(animationTime), true);
240             animationData_.SetTime(animationTime, intervalTime);
241             StartProgressAnimation();
242         }
243     } else {
244         animationData_.SetTime(animationTime, intervalTime);
245         StartProgressAnimation();
246     }
247 }
248 
Pause()249 void LinearIndicatorController::Pause()
250 {
251     if (!animationData_.IsRuning()) {
252         return;
253     }
254     if (animationData_.State() == LinearIndicatorControllerDataState::INTERVAL) {
255         animationData_.SetState(LinearIndicatorControllerDataState::INTERVAL_PAUSE);
256         animationData_.ProgressIntervalCancel();
257         return;
258     }
259     StopAnimation(LinearIndicatorControllerDataState::ANIMATION_PAUSE);
260 }
261 
Stop()262 void LinearIndicatorController::Stop()
263 {
264     if (animationData_.IsRuning()) {
265         if (animationData_.State() == LinearIndicatorControllerDataState::INTERVAL) {
266             animationData_.ProgressIntervalCancel();
267         } else {
268             StopAnimation(LinearIndicatorControllerDataState::STOP);
269         }
270     }
271     if ((animationData_.Index() != 0) || (!NearZero(animationData_.Value()))) {
272         if (changeCallback_) {
273             changeCallback_(0, .0f);
274         }
275     }
276     animationData_.InitData();
277     InitProgressValue();
278 }
279 
SetProgress(int32_t index,float value)280 void LinearIndicatorController::SetProgress(int32_t index, float value)
281 {
282     if (animationData_.Index() == index && animationData_.Value() == value) {
283         return;
284     }
285     int32_t progressSize = GetProgressSize();
286     if (progressSize == 0) {
287         animationData_.InitData();
288         return;
289     }
290     if (index < 0 || index >= progressSize) {
291         return;
292     }
293     if (value < 0 || value > END_VALUE) {
294         return;
295     }
296     if (changeCallback_) {
297         changeCallback_(index, value);
298     }
299     bool isRuning = animationData_.IsRuning();
300     bool isPause = animationData_.IsPause();
301     if (isRuning) {
302         if (animationData_.State() == LinearIndicatorControllerDataState::INTERVAL) {
303             animationData_.ProgressIntervalCancel();
304         } else {
305             StopAnimation(LinearIndicatorControllerDataState::ANIMATION_PAUSE);
306         }
307     }
308     animationData_.SetIndexAndValue(index, value);
309     InitProgressValue();
310     if (isRuning) {
311         StartProgressAnimation();
312     } else if (isPause) {
313         animationData_.SetState(LinearIndicatorControllerDataState::ANIMATION_PAUSE);
314     }
315 }
316 
GetHost() const317 RefPtr<FrameNode> LinearIndicatorController::GetHost() const
318 {
319     auto pattern = pattern_.Upgrade();
320     CHECK_NULL_RETURN(pattern, nullptr);
321     return pattern->GetHost();
322 }
323 
StopAnimation(LinearIndicatorControllerDataState state)324 void LinearIndicatorController::StopAnimation(LinearIndicatorControllerDataState state)
325 {
326     animationData_.SetState(state);
327     AnimationUtils::StopAnimation(animationData_.ProgressAnimationAndClear());
328 }
329 
UpdateProgressSize(int32_t size)330 void LinearIndicatorController::UpdateProgressSize(int32_t size)
331 {
332     if (animationData_.Index() >= size) {
333         SetProgress(size - 1, END_VALUE);
334     }
335 }
336 
RecalcProgressValue(int32_t newAnimationTime)337 float LinearIndicatorController::RecalcProgressValue(int32_t newAnimationTime)
338 {
339     if (newAnimationTime == 0) {
340         return END_VALUE;
341     }
342     int32_t oldAnimationTime = animationData_.TotalAnimationTime();
343     float oldValue = animationData_.Value();
344     return std::clamp(oldAnimationTime * oldValue / newAnimationTime, .0f, END_VALUE);
345 }
346 
SetValueAndCallback(float value,bool isDraw)347 void LinearIndicatorController::SetValueAndCallback(float value, bool isDraw)
348 {
349     animationData_.SetValue(value);
350     if (isDraw) {
351         InitProgressValue();
352     }
353     if (changeCallback_) {
354         changeCallback_(animationData_.Index(), value);
355     }
356 }
357 } // namespace OHOS::Ace::NG
358