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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BUTTON_RENDER_BUTTON_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BUTTON_RENDER_BUTTON_H
18 
19 #include "base/utils/system_properties.h"
20 #include "core/animation/animator.h"
21 #include "core/animation/curve_animation.h"
22 #include "core/animation/keyframe_animation.h"
23 #include "core/components/button/button_component.h"
24 #include "core/components/common/properties/color.h"
25 #include "core/components/common/properties/edge.h"
26 #include "core/components/touch_listener/render_touch_listener.h"
27 #include "core/gestures/click_recognizer.h"
28 #include "core/gestures/raw_recognizer.h"
29 #include "core/pipeline/base/render_node.h"
30 
31 namespace OHOS::Ace {
32 
33 constexpr Dimension ARC_BUTTON_WIDTH = 169.0_vp;
34 constexpr Dimension ARC_BUTTON_HEIGHT = 48.0_vp;
35 
36 // Definition for animation
37 constexpr double INIT_SCALE = 1.0;
38 
39 class RenderButton : public RenderNode {
40     DECLARE_ACE_TYPE(RenderButton, RenderNode);
41 
42 public:
43     ~RenderButton() override = default;
44 
45     static RefPtr<RenderNode> Create();
46 
47     void Update(const RefPtr<Component>& component) override;
48     void PerformLayout() override;
49     void OnPaintFinish() override;
50     void OnStatusStyleChanged(const VisualState state) override;
51 
OnAttachContext()52     void OnAttachContext() override
53     {
54         width_.SetContextAndCallback(context_, [weak = WeakClaim(this)] {
55             auto renderButton = weak.Upgrade();
56             if (renderButton) {
57                 renderButton->MarkNeedLayout();
58             }
59         });
60         height_.SetContextAndCallback(context_, [weak = WeakClaim(this)] {
61             auto renderButton = weak.Upgrade();
62             if (renderButton) {
63                 renderButton->MarkNeedLayout();
64             }
65         });
66         backgroundColor_.SetContextAndCallback(context_, [weak = WeakClaim(this)] {
67             auto renderButton = weak.Upgrade();
68             if (renderButton) {
69                 renderButton->MarkNeedLayout();
70             }
71         });
72         clickedColor_.SetContextAndCallback(context_, [weak = WeakClaim(this)] {
73             auto renderButton = weak.Upgrade();
74             if (renderButton) {
75                 renderButton->MarkNeedLayout();
76             }
77         });
78     }
79 
80     void HandleFocusEvent(bool isFocus);
81     void HandleClickEvent(const ClickInfo& info);
82     void HandleClickEvent();
83     bool HandleKeyEnterEvent(const ClickInfo& info);
84     void HandleKeyEnterEvent();
85     void HandleRemoteMessageEvent(const ClickInfo& info);
86     void HandleRemoteMessageEvent();
87     void DisplayFocusAnimation();
88     void PlayFocusAnimation(bool isFocus);
89     void AnimateMouseHoverEnter() override;
90     void AnimateMouseHoverExit() override;
91 
IsDisabled()92     bool IsDisabled() const
93     {
94         return isDisabled_;
95     }
96 
SetClickedColor(const Color & clickColor)97     void SetClickedColor(const Color& clickColor)
98     {
99         // do not trigger animation
100         clickedColor_.SetValue(clickColor.GetValue());
101         setClickColor_ = true;
102     }
103 
GetButtonType()104     ButtonType GetButtonType() const
105     {
106         return type_;
107     }
108 
GetStateEffect()109     bool GetStateEffect() const
110     {
111         return stateEffect_;
112     }
GetComponent()113     RefPtr<Component> GetComponent() override
114     {
115         return buttonComponent_;
116     }
GetClickedColor()117     Color GetClickedColor()
118     {
119         return clickedColor_;
120     }
121 
GetBackgroundColor()122     Color GetBackgroundColor() const
123     {
124         return buttonComponent_->GetBackgroundColor();
125     }
126 
GetRadius()127     double GetRadius() const
128     {
129         return rrectRadius_;
130     }
131 
132     void SendAccessibilityEvent();
133 
134 protected:
135     RenderButton();
136     virtual Size Measure() = 0;
137     void OnTouchTestHit(
138         const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result) override;
139 
140     void Initialize();
141     void InitAccessibilityEventListener();
142     void HandleTouchEvent(bool isTouch);
143     void HandleMoveEvent(const TouchEventInfo& info);
144     void UpdateDownloadStyles(const RefPtr<ButtonComponent>& button);
145     void SetProgress(uint32_t progress);
146     void OnMouseHoverEnterTest() override;
147     void OnMouseHoverExitTest() override;
148     void OnMouseClickDownAnimation() override;
149     void OnMouseClickUpAnimation() override;
150 
NeedLayoutExtendToParant()151     bool NeedLayoutExtendToParant() const
152     {
153         return (layoutFlag_ & LAYOUT_FLAG_EXTEND_TO_PARENT) == LAYOUT_FLAG_EXTEND_TO_PARENT;
154     }
155 
156     RefPtr<ButtonComponent> buttonComponent_;
157     RefPtr<RawRecognizer> touchRecognizer_;
158     RefPtr<ClickRecognizer> clickRecognizer_;
159     RefPtr<Animator> progressController_;
160 
161     ButtonType type_ = ButtonType::NORMAL;
162     Size buttonSize_;
163     Offset offsetDelta_;
164     double rrectRadius_ = 0.0;
165     double widthDelta_ = 0.0;
166     double progressWidth_ = 0.0;
167     double progressPercent_ = 0.0;
168     double progressDiameter_ = 0.0;
169     double opacity_ = 1.0;
170     double maskingOpacity_ = 0.0;
171     double ratio_ = 0.0;
172     double previousValue_ = 0.0;
173     double percentChange_ = 0.0;
174     float scale_ = 1.0f;
175     bool stateEffect_ = true;
176     double aspectRatio_ = 0.0;
177 
178     bool needUpdateAnimation_ = false;
179     bool isInnerBorder_ = false;
180     bool isClicked_ = false;
181     bool isDisabled_ = false;
182     bool isFocus_ = false;
183     bool isWatch_ = false;
184     bool isTv_ = false;
185     bool isPhone_ = false;
186     bool isTablet_ = false;
187     bool widthDefined_ = false;
188     bool heightDefined_ = false;
189     bool progressDisplay_ = false;
190     bool animationRunning_ = false;
191     bool isLastFrame_ = false;
192     bool isOpacityAnimation_ = false;
193     bool isTouchAnimation_ = false;
194     bool isHover_ = false;
195     bool needFocusColor_ = false;
196     bool needHoverColor_ = false;
197     bool isMoveEventValid_ = false;
198     bool setClickColor_ = false;
199     uint32_t layoutFlag_ = 0;
200 
201     Color focusAnimationColor_;
202     Color progressColor_;
203     Color progressFocusColor_;
204     Color defaultClickedColor_;
205     AnimatableColor clickedColor_;
206     AnimatableColor backgroundColor_;
207     BorderEdge borderEdge_;
208     std::function<void(const ClickInfo&)> onClickWithInfo_;
209     std::function<void()> onClick_;
210     std::chrono::steady_clock::time_point previousUpdateTime_ = std::chrono::steady_clock::now();
211     std::chrono::duration<double> animationDuring_;
212 
213 private:
214     void UpdateAnimationParam(double value);
215     void UpdateFocusAnimation(double value);
216     void UpdateProgressAnimation();
217     void PlayAnimation(double start, double end, int32_t duration, const FillMode& fillMode = FillMode::FORWARDS);
218     void PlayTouchAnimation();
219     void PlayClickAnimation();
220     void PlayClickScaleAnimation(float keyTime, int32_t duration);
221     void UpdateAccessibility();
222     void SetChildrenLayoutSize();
223     void SetChildrenAlignment();
224     Size CalculateLayoutSize();
225     bool NeedAdaptiveChild();
226     bool NeedConstrain();
227     void ResetController(RefPtr<Animator>& controller);
228     void CreateFloatAnimation(RefPtr<KeyframeAnimation<float>>& floatAnimation, float beginValue, float endValue);
229 
230     AnimatableDimension width_;
231     AnimatableDimension height_;
232     Dimension minWidth_;
233     bool valueChanged_ = false;
234     bool isClickAnimation_ = false;
235     double startValue_ = 0.0;
236     double endValue_ = 0.0;
237     Edge arcInitEdge_;
238     Size layoutSize_;
239     Size childrenSize_;
240 
241     RefPtr<Animator> controller_;
242     RefPtr<Animator> hoverControllerEnter_;
243     RefPtr<Animator> hoverControllerExit_;
244     RefPtr<Animator> clickControllerDown_;
245     RefPtr<Animator> clickControllerUp_;
246     RefPtr<KeyframeAnimation<float>> scaleAnimationEnter_;
247     RefPtr<KeyframeAnimation<float>> scaleAnimationExit_;
248     RefPtr<KeyframeAnimation<float>> scaleAnimationUp_;
249     RefPtr<KeyframeAnimation<float>> scaleAnimationDown_;
250 };
251 
252 } // namespace OHOS::Ace
253 
254 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BUTTON_RENDER_BUTTON_H
255