1 /*
2  * Copyright (c) 2021 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_PROPERTIES_ANIMATABLE_COLOR_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_PROPERTIES_ANIMATABLE_COLOR_H
18 
19 #include "core/animation/animator.h"
20 #include "core/animation/curve_animation.h"
21 #include "core/components/common/properties/animation_option.h"
22 #include "core/components/common/properties/color.h"
23 #include "core/event/ace_event_helper.h"
24 
25 namespace OHOS::Ace {
26 
27 using RenderNodeAnimationCallback = std::function<void()>;
28 
29 /*
30  * AnimatableColor is a Color with AnimationOption and Animator.
31  */
32 class AnimatableColor final : public Color {
33 public:
34     AnimatableColor() = default;
35     explicit AnimatableColor(uint32_t value, const AnimationOption& option = AnimationOption()) : Color(value)
36     {
37         animationOption_ = option;
38     }
39 
40     explicit AnimatableColor(const Color& color, const AnimationOption& option = AnimationOption())
41         : Color(color.GetValue())
42     {
43         animationOption_ = option;
44     }
45 
46     ~AnimatableColor() = default;
47 
SetContextAndCallback(const WeakPtr<PipelineContext> & context,const RenderNodeAnimationCallback & callback)48     void SetContextAndCallback(const WeakPtr<PipelineContext>& context, const RenderNodeAnimationCallback& callback)
49     {
50         context_ = context;
51         animationCallback_ = callback;
52     }
53 
GetAnimationOption()54     const AnimationOption& GetAnimationOption() const
55     {
56         return animationOption_;
57     }
58 
SetAnimationOption(const AnimationOption & option)59     void SetAnimationOption(const AnimationOption& option)
60     {
61         animationOption_ = option;
62     }
63 
64     AnimatableColor& operator=(const AnimatableColor& newColor)
65     {
66         SetAnimationOption(newColor.GetAnimationOption());
67         auto pipelineContext = context_.Upgrade();
68         if (!pipelineContext || !animationCallback_) {
69             SetValue(newColor.GetValue());
70             return *this;
71         }
72         AnimationOption explicitAnim = pipelineContext->GetExplicitAnimationOption();
73         if (explicitAnim.IsValid()) {
74             SetAnimationOption(explicitAnim);
75             AnimateTo(newColor.GetValue());
76         } else if (animationOption_.IsValid()) {
77             AnimateTo(newColor.GetValue());
78         } else {
79             ResetController();
80             SetValue(newColor.GetValue());
81         }
82         isFirstAssign_ = false;
83         return *this;
84     }
85 
86 private:
AnimateTo(uint32_t endValue)87     void AnimateTo(uint32_t endValue)
88     {
89         if (isFirstAssign_) {
90             isFirstAssign_ = false;
91             SetValue(endValue);
92             return;
93         }
94         if (GetValue() == endValue) {
95             return;
96         }
97         ResetController();
98         if (!animationController_) {
99             animationController_ = CREATE_ANIMATOR(context_);
100         }
101 
102         RefPtr<CurveAnimation<Color>> colorAnimation =
103             AceType::MakeRefPtr<CurveAnimation<Color>>(Color(GetValue()), Color(endValue), animationOption_.GetCurve());
104         colorAnimation->AddListener(std::bind(&AnimatableColor::OnAnimationCallback, this, std::placeholders::_1));
105 
106         animationController_->AddInterpolator(colorAnimation);
107         auto onFinishEvent = animationOption_.GetOnFinishEvent();
108         if (onFinishEvent) {
109             animationController_->AddStopListener([onFinishEvent, weakContext = context_] {
110                 auto context = weakContext.Upgrade();
111                 if (context) {
112                     context->PostAsyncEvent(onFinishEvent, "ArkUIAnimatableColorFinishEvent");
113                 } else {
114                     LOGE("the context is null");
115                 }
116             });
117         }
118         animationController_->SetDuration(animationOption_.GetDuration());
119         animationController_->SetStartDelay(animationOption_.GetDelay());
120         animationController_->SetIteration(animationOption_.GetIteration());
121         animationController_->SetTempo(animationOption_.GetTempo());
122         animationController_->SetAnimationDirection(animationOption_.GetAnimationDirection());
123         animationController_->SetFillMode(FillMode::FORWARDS);
124         animationController_->SetAllowRunningAsynchronously(animationOption_.GetAllowRunningAsynchronously());
125         animationController_->Play();
126     }
127 
ResetController()128     void ResetController()
129     {
130         if (animationController_) {
131             if (!animationController_->IsStopped()) {
132                 animationController_->Stop();
133             }
134             animationController_->ClearInterpolators();
135             animationController_->ClearAllListeners();
136             animationController_.Reset();
137         }
138     }
139 
OnAnimationCallback(const Color & color)140     void OnAnimationCallback(const Color& color)
141     {
142         SetValue(color.GetValue());
143         if (animationCallback_) {
144             animationCallback_();
145         }
146     }
147 
148 private:
149     bool isFirstAssign_ = true;
150     AnimationOption animationOption_;
151     RefPtr<Animator> animationController_;
152     WeakPtr<PipelineContext> context_;
153     RenderNodeAnimationCallback animationCallback_;
154 };
155 
156 } // namespace OHOS::Ace
157 
158 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_PROPERTIES_ANIMATABLE_COLOR_H
159