• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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