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