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 isFirstAssign_ = false;
73 SetValue(endValue);
74 return;
75 }
76 if (NearEqual(Value(), endValue) && !evaluator_) {
77 return;
78 }
79 ResetController();
80 if (!animationController_) {
81 animationController_ = CREATE_ANIMATOR(context_);
82 }
83 RefPtr<CurveAnimation<double>> animation =
84 AceType::MakeRefPtr<CurveAnimation<double>>(Value(), endValue, animationOption_.GetCurve());
85 if (evaluator_) {
86 animation->SetEvaluator(evaluator_);
87 }
88 animation->AddListener(std::bind(&AnimatableDimension::OnAnimationCallback, this, std::placeholders::_1));
89
90 animationController_->AddInterpolator(animation);
91 auto onFinishEvent = animationOption_.GetOnFinishEvent();
92 if (onFinishEvent) {
93 animationController_->AddStopListener([onFinishEvent, weakContext = context_] {
94 auto context = weakContext.Upgrade();
95 if (context) {
96 context->PostAsyncEvent(onFinishEvent);
97 }
98 });
99 }
100 if (stopCallback_) {
101 animationController_->AddStopListener(stopCallback_);
102 }
103 animationController_->SetDuration(animationOption_.GetDuration());
104 animationController_->SetStartDelay(animationOption_.GetDelay());
105 animationController_->SetIteration(animationOption_.GetIteration());
106 animationController_->SetTempo(animationOption_.GetTempo());
107 animationController_->SetAnimationDirection(animationOption_.GetAnimationDirection());
108 animationController_->SetFillMode(FillMode::FORWARDS);
109 animationController_->SetAllowRunningAsynchronously(animationOption_.GetAllowRunningAsynchronously());
110 animationController_->Play();
111 }
112
ResetController()113 void AnimatableDimension::ResetController()
114 {
115 if (animationController_) {
116 if (!animationController_->IsStopped()) {
117 animationController_->Stop();
118 }
119 animationController_->ClearInterpolators();
120 animationController_->ClearAllListeners();
121 animationController_.Reset();
122 }
123 }
124
OnAnimationCallback(double value)125 void AnimatableDimension::OnAnimationCallback(double value)
126 {
127 SetValue(value);
128 if (animationCallback_) {
129 animationCallback_();
130 }
131 }
132
MoveTo(double target)133 void AnimatableDimension::MoveTo(double target)
134 {
135 SetValue(target);
136 isFirstAssign_ = false;
137 }
138
ResetAnimatableDimension()139 void AnimatableDimension::ResetAnimatableDimension()
140 {
141 isFirstAssign_ = true;
142 animationOption_ = AnimationOption();
143 animationController_ = nullptr;
144 context_ = nullptr;
145 animationCallback_ = nullptr;
146 }
147 } // namespace OHOS::Ace
148