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/event/ace_event_helper.h"
19
20 namespace OHOS::Ace {
operator =(const Dimension & newDimension)21 AnimatableDimension& AnimatableDimension::operator=(const Dimension& newDimension)
22 {
23 ResetAnimatableDimension();
24 Dimension& dimension = *this;
25 dimension = newDimension;
26 return *this;
27 }
28
operator =(const CalcDimension & newDimension)29 AnimatableDimension& AnimatableDimension::operator=(const CalcDimension& newDimension)
30 {
31 ResetAnimatableDimension();
32 CalcDimension& dimension = *this;
33 dimension = newDimension;
34 return *this;
35 }
36
operator =(const AnimatableDimension & newDimension)37 AnimatableDimension& AnimatableDimension::operator=(const AnimatableDimension& newDimension)
38 {
39 SetUnit(newDimension.Unit());
40 SetAnimationOption(newDimension.GetAnimationOption());
41 auto pipelineContext = context_.Upgrade();
42 if (!animationCallback_ || !pipelineContext) {
43 if (newDimension.Unit() == DimensionUnit::CALC) {
44 SetCalcValue(newDimension.CalcValue());
45 } else {
46 SetValue(newDimension.Value());
47 }
48 return *this;
49 }
50 AnimationOption explicitAnim = pipelineContext->GetExplicitAnimationOption();
51 if (explicitAnim.IsValid()) {
52 SetAnimationOption(explicitAnim);
53 AnimateTo(newDimension.Value());
54 } else if (animationOption_.IsValid()) {
55 AnimateTo(newDimension.Value());
56 } else {
57 ResetController();
58 if (newDimension.Unit() == DimensionUnit::CALC) {
59 SetCalcValue(newDimension.CalcValue());
60 } else {
61 SetValue(newDimension.Value());
62 }
63 }
64 isFirstAssign_ = false;
65 return *this;
66 }
67
AnimateTo(double endValue)68 void AnimatableDimension::AnimateTo(double endValue)
69 {
70 if (isFirstAssign_) {
71 LOGD("AnimateTo with first assign. endValue: %{public}.2f", endValue);
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_ = AceType::MakeRefPtr<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 } else {
98 LOGE("the context is null");
99 }
100 });
101 }
102 if (stopCallback_) {
103 animationController_->AddStopListener(stopCallback_);
104 }
105 animationController_->SetDuration(animationOption_.GetDuration());
106 animationController_->SetStartDelay(animationOption_.GetDelay());
107 animationController_->SetIteration(animationOption_.GetIteration());
108 animationController_->SetTempo(animationOption_.GetTempo());
109 animationController_->SetAnimationDirection(animationOption_.GetAnimationDirection());
110 animationController_->SetFillMode(FillMode::FORWARDS);
111 animationController_->SetAllowRunningAsynchronously(animationOption_.GetAllowRunningAsynchronously());
112 animationController_->Play();
113 }
114
ResetController()115 void AnimatableDimension::ResetController()
116 {
117 if (animationController_) {
118 if (!animationController_->IsStopped()) {
119 animationController_->Stop();
120 }
121 animationController_->ClearInterpolators();
122 animationController_->ClearAllListeners();
123 animationController_.Reset();
124 }
125 }
126
OnAnimationCallback(double value)127 void AnimatableDimension::OnAnimationCallback(double value)
128 {
129 SetValue(value);
130 if (animationCallback_) {
131 animationCallback_();
132 }
133 }
134
MoveTo(double target)135 void AnimatableDimension::MoveTo(double target)
136 {
137 SetValue(target);
138 isFirstAssign_ = false;
139 }
140
ResetAnimatableDimension()141 void AnimatableDimension::ResetAnimatableDimension()
142 {
143 isFirstAssign_ = true;
144 animationOption_ = AnimationOption();
145 animationController_ = nullptr;
146 context_ = nullptr;
147 animationCallback_ = nullptr;
148 }
149 } // namespace OHOS::Ace