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 "base/geometry/animatable_dimension.h"
17
18 #include "core/animation/animator.h"
19 #include "core/event/ace_event_helper.h"
20
21 namespace OHOS::Ace {
operator =(const Dimension & newDimension)22 AnimatableDimension& AnimatableDimension::operator=(const Dimension& newDimension)
23 {
24 ResetAnimatableDimension();
25 Dimension& dimension = *this;
26 dimension = newDimension;
27 return *this;
28 }
29
operator =(const CalcDimension & newDimension)30 AnimatableDimension& AnimatableDimension::operator=(const CalcDimension& newDimension)
31 {
32 ResetAnimatableDimension();
33 CalcDimension& dimension = *this;
34 dimension = newDimension;
35 return *this;
36 }
37
operator =(const AnimatableDimension & newDimension)38 AnimatableDimension& AnimatableDimension::operator=(const AnimatableDimension& newDimension)
39 {
40 SetUnit(newDimension.Unit());
41 SetAnimationOption(newDimension.GetAnimationOption());
42 auto pipelineContext = context_.Upgrade();
43 if (!animationCallback_ || !pipelineContext) {
44 if (newDimension.Unit() == DimensionUnit::CALC) {
45 SetCalcValue(newDimension.CalcValue());
46 } else {
47 SetValue(newDimension.Value());
48 }
49 return *this;
50 }
51 AnimationOption explicitAnim = pipelineContext->GetExplicitAnimationOption();
52 if (explicitAnim.IsValid()) {
53 SetAnimationOption(explicitAnim);
54 AnimateTo(newDimension.Value());
55 } else if (animationOption_.IsValid()) {
56 AnimateTo(newDimension.Value());
57 } else {
58 ResetController();
59 if (newDimension.Unit() == DimensionUnit::CALC) {
60 SetCalcValue(newDimension.CalcValue());
61 } else {
62 SetValue(newDimension.Value());
63 }
64 }
65 isFirstAssign_ = false;
66 return *this;
67 }
68
AnimateTo(double endValue)69 void AnimatableDimension::AnimateTo(double endValue)
70 {
71 if (isFirstAssign_) {
72 LOGD("AnimateTo with first assign. endValue: %{public}.2f", endValue);
73 isFirstAssign_ = false;
74 SetValue(endValue);
75 return;
76 }
77 if (NearEqual(Value(), endValue) && !evaluator_) {
78 return;
79 }
80 ResetController();
81 if (!animationController_) {
82 animationController_ = CREATE_ANIMATOR(context_);
83 }
84 RefPtr<CurveAnimation<double>> animation =
85 AceType::MakeRefPtr<CurveAnimation<double>>(Value(), endValue, animationOption_.GetCurve());
86 if (evaluator_) {
87 animation->SetEvaluator(evaluator_);
88 }
89 animation->AddListener(std::bind(&AnimatableDimension::OnAnimationCallback, this, std::placeholders::_1));
90
91 animationController_->AddInterpolator(animation);
92 auto onFinishEvent = animationOption_.GetOnFinishEvent();
93 if (onFinishEvent) {
94 animationController_->AddStopListener([onFinishEvent, weakContext = context_] {
95 auto context = weakContext.Upgrade();
96 if (context) {
97 context->PostAsyncEvent(onFinishEvent);
98 } else {
99 LOGE("the context is null");
100 }
101 });
102 }
103 if (stopCallback_) {
104 animationController_->AddStopListener(stopCallback_);
105 }
106 animationController_->SetDuration(animationOption_.GetDuration());
107 animationController_->SetStartDelay(animationOption_.GetDelay());
108 animationController_->SetIteration(animationOption_.GetIteration());
109 animationController_->SetTempo(animationOption_.GetTempo());
110 animationController_->SetAnimationDirection(animationOption_.GetAnimationDirection());
111 animationController_->SetFillMode(FillMode::FORWARDS);
112 animationController_->SetAllowRunningAsynchronously(animationOption_.GetAllowRunningAsynchronously());
113 animationController_->Play();
114 }
115
ResetController()116 void AnimatableDimension::ResetController()
117 {
118 if (animationController_) {
119 if (!animationController_->IsStopped()) {
120 animationController_->Stop();
121 }
122 animationController_->ClearInterpolators();
123 animationController_->ClearAllListeners();
124 animationController_.Reset();
125 }
126 }
127
OnAnimationCallback(double value)128 void AnimatableDimension::OnAnimationCallback(double value)
129 {
130 SetValue(value);
131 if (animationCallback_) {
132 animationCallback_();
133 }
134 }
135
MoveTo(double target)136 void AnimatableDimension::MoveTo(double target)
137 {
138 SetValue(target);
139 isFirstAssign_ = false;
140 }
141
ResetAnimatableDimension()142 void AnimatableDimension::ResetAnimatableDimension()
143 {
144 isFirstAssign_ = true;
145 animationOption_ = AnimationOption();
146 animationController_ = nullptr;
147 context_ = nullptr;
148 animationCallback_ = nullptr;
149 }
150 } // namespace OHOS::Ace
151