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