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