1/*
2 * Copyright (c) 2020-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/**
17 * @addtogroup UI_Components
18 * @{
19 *
20 * @brief Defines UI components such as buttons, texts, images, lists, and progress bars.
21 *
22 * @since 1.0
23 * @version 1.0
24 */
25
26/**
27 * @file ui_button.h
28 *
29 * @brief Defines the attributes and common functions of a button.
30 *
31 * @since 1.0
32 * @version 1.0
33 */
34
35#ifndef GRAPHIC_LITE_UI_BUTTON_H
36#define GRAPHIC_LITE_UI_BUTTON_H
37
38#include "animator/animator.h"
39#include "common/image.h"
40#include "components/ui_view.h"
41
42namespace OHOS {
43/**
44 * @brief Represents a button.
45 *
46 * This component responds to the press and release events.
47 *
48 * @since 1.0
49 * @version 1.0
50 */
51class UIButton : public UIView {
52public:
53    /**
54     * @brief A constructor used to create a <b>UIButton</b> instance.
55     *
56     * @since 1.0
57     * @version 1.0
58     */
59    UIButton();
60
61    /**
62     * @brief A constructor used to create a <b>UIButton</b> instance based on the button ID.
63     *
64     * Buttons sharing the same ID are in the same batch.
65     *
66     * @param id Indicates the button ID.
67     * @since 1.0
68     * @version 1.0
69     */
70    explicit UIButton(const char* id) : UIButton()
71    {
72        id_ = id;
73    }
74
75    /**
76     * @brief A destructor used to delete the <b>UIButton</b> instance.
77     *
78     * @since 1.0
79     * @version 1.0
80     */
81    virtual ~UIButton();
82
83    /**
84     * @brief Obtains the component type.
85     *
86     * @return Returns the component type, as defined in {@link UIViewType}.
87     * @since 1.0
88     * @version 1.0
89     */
90    UIViewType GetViewType() const override
91    {
92        return UI_BUTTON;
93    }
94
95    /**
96     * @fn virtual bool UIButton::OnPreDraw(Rect& invalidatedArea) override
97     *
98     * @brief Do something before draw, this function will be invoked mainly to check if this view need
99     *        to cover invalidate area so render manager can decide which layer to draw firstly.
100     * @param [in] invalidate area.
101     * @returns True if need cover.
102     */
103    bool OnPreDraw(Rect& invalidatedArea) const override;
104
105#if DEFAULT_ANIMATION
106    /**
107     * @fn virtual bool UIButton::OnPostDraw(BufferInfo& gfxDstBuffer, Rect& invalidatedArea) override
108     *
109     * @brief Do something after draw.
110     * @param [in] invalidate area.
111     */
112    void OnPostDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea) override;
113#endif
114    /**
115     * @fn  virtual void UIButton::OnDraw(const Rect& invalidatedArea) override;
116     *
117     * @brief   Executes the draw action
118     *
119     * @param   [in] invalidatedArea The rectangle to draw, with coordinates relative to this drawable..
120     */
121    void OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea) override;
122
123    /**
124     * @fn  virtual void UIButton::OnPressEvent(const PressEvent& event) override;
125     *
126     * @brief   Executes the press event action
127     *
128     * @param   [in] event   The press event, contain press position.
129     *
130     * @return Returns <b>true</b> if the event is consumed; returns <b>false</b> otherwise.
131     */
132    bool OnPressEvent(const PressEvent& event) override;
133
134    /**
135     * @fn  virtual void UIButton::OnReleaseEvent(const ReleaseEvent& event) override;
136     *
137     * @brief   Executes the press release event action
138     *
139     * @param   [in] event   The press release event.
140     */
141    bool OnReleaseEvent(const ReleaseEvent& event) override;
142
143    /**
144     * @fn  virtual void UIButton::OnCancelEvent(const CancelEvent& event) override;
145     *
146     * @brief   Executes the cancel event action
147     *
148     * @param   [in] event   The cancel event.
149     */
150    bool OnCancelEvent(const CancelEvent& event) override;
151
152    /**
153     * @brief Enumerates the images for different button states.
154     *
155     * You can define a different image for each button state.
156     *
157     * @since 1.0
158     * @version 1.0
159     */
160    enum ButtonImageSrc : uint8_t {
161        /* An enum constant representing the Button image default option */
162        BTN_IMAGE_DEFAULT,
163        /* An enum constant representing the Button image triggered option */
164        BTN_IMAGE_TRIGGERED,
165        /* An enum constant representing the Button Image Number option */
166        BTN_IMG_NUM,
167    };
168
169    /**
170     * @brief Sets the image for this button.
171     *
172     * @param defaultImgSrc Indicates the default image.
173     * @param triggeredImgSrc Indicates the image for a button when it is triggered.
174     * @since 1.0
175     * @version 1.0
176     */
177    void SetImageSrc(const char* defaultImgSrc, const char* triggeredImgSrc);
178
179    /**
180     * @brief Sets the image for this button.
181     *
182     * @param defaultImgSrc Indicates the default image.
183     * @param triggeredImgSrc Indicates the image for a button when it is triggered.
184     * @since 1.0
185     * @version 1.0
186     */
187    void SetImageSrc(const ImageInfo* defaultImgSrc, const ImageInfo* triggeredImgSrc);
188
189    /**
190     * @brief Sets the position for this image.
191     *
192     * @param x Indicates the x-coordinate to set.
193     * @param y Indicates the y-coordinate to set.
194     * @since 1.0
195     * @version 1.0
196     */
197    void SetImagePosition(const int16_t x, const int16_t y)
198    {
199        imgX_ = x;
200        imgY_ = y;
201    }
202
203    /**
204     * @brief Obtains the x-coordinate of this image.
205     *
206     * @return Returns the x-coordinate of this image.
207     * @since 1.0
208     * @version 1.0
209     */
210    int16_t GetImageX() const
211    {
212        return imgX_;
213    }
214
215    /**
216     * @brief Obtains the y-coordinate of this image.
217     *
218     * @return Returns the y-coordinate of this image.
219     * @since 1.0
220     * @version 1.0
221     */
222    int16_t GetImageY() const
223    {
224        return imgY_;
225    }
226
227    /**
228     * @brief Obtains the image for the current button state.
229     *
230     * @return Returns the image for the current button state.
231     * @since 1.0
232     * @version 1.0
233     */
234    const Image* GetCurImageSrc() const;
235
236    /**
237     * @brief Enumerates the states of this button.
238     *
239     * The button has three states.
240     *
241     * @since 1.0
242     * @version 1.0
243     */
244    enum ButtonState : uint8_t {
245        /* An enum constant representing the Button state released option */
246        RELEASED = 0,
247        /* An enum constant representing the Button state pressed option */
248        PRESSED,
249        /* An enum constant representing the Button state inactive option */
250        INACTIVE,
251        /* An enum constant representing the Button state Number option */
252        BTN_STATE_NUM,
253    };
254
255    /**
256     * @brief Obtains the width of this image.
257     *
258     * @return Returns the image width.
259     * @since 1.0
260     * @version 1.0
261     */
262    int16_t GetWidth() override
263    {
264        Style* style = buttonStyles_[state_];
265        return GetRelativeRect().GetWidth() - (style->paddingLeft_ + style->paddingRight_) -
266               (style->borderWidth_ * 2); /* 2: left and right border */
267    }
268
269    /**
270     * @brief Obtains the height of this button.
271     *
272     * @return Returns the image height.
273     * @since 1.0
274     * @version 1.0
275     */
276    int16_t GetHeight() override
277    {
278        Style* style = buttonStyles_[state_];
279        return GetRelativeRect().GetHeight() - (style->paddingTop_ + style->paddingBottom_) -
280               (style->borderWidth_ * 2); /* 2: top and bottom border */
281    }
282
283    /**
284     * @brief Sets the width for this button.
285     *
286     * @param width Indicates the width to set.
287     * @since 1.0
288     * @version 1.0
289     */
290    void SetWidth(int16_t width) override
291    {
292        contentWidth_ = width;
293        UIView::SetWidth(width); /* 2: left and right border */
294    }
295
296    /**
297     * @brief Sets the height for this image.
298     *
299     * @param height Indicates the height to set.
300     * @since 1.0
301     * @version 1.0
302     */
303    void SetHeight(int16_t height) override
304    {
305        contentHeight_ = height;
306        UIView::SetHeight(height); /* 2: top and bottom border */
307    }
308
309    /**
310     * @brief Obtains a rectangular area that contains coordinate information.
311     *
312     * @return Returns the rectangle area.
313     * @since 1.0
314     * @version 1.0
315     */
316    Rect GetContentRect() override
317    {
318        Rect contentRect;
319        Style* style = buttonStyles_[state_];
320        contentRect.SetX(GetRect().GetX() + style->paddingLeft_ + style->borderWidth_);
321        contentRect.SetY(GetRect().GetY() + style->paddingTop_ + style->borderWidth_);
322        contentRect.SetWidth(GetWidth());
323        contentRect.SetHeight(GetHeight());
324        return contentRect;
325    }
326
327    Rect GetOrigContentRect() override
328    {
329        Rect contentRect;
330        Style* style = buttonStyles_[state_];
331        contentRect.SetX(GetOrigRect().GetX() + style->paddingLeft_ + style->borderWidth_);
332        contentRect.SetY(GetOrigRect().GetY() + style->paddingTop_ + style->borderWidth_);
333        contentRect.SetWidth(GetWidth());
334        contentRect.SetHeight(GetHeight());
335        return contentRect;
336    }
337
338    /**
339     * @brief Obtains the value of a style.
340     *
341     * @param key Indicates the key of the style.
342     * @return Returns the value of the style.
343     * @since 1.0
344     * @version 1.0
345     */
346    int64_t GetStyle(uint8_t key) const override;
347
348    /**
349     * @brief Sets the view style.
350     * @param style Indicates the view style.
351     * @since 1.0
352     * @version 1.0
353     */
354    void SetStyle(Style& style) override
355    {
356        UIView::SetStyle(style);
357    }
358
359    /**
360     * @brief Sets a style.
361     *
362     * @param key Indicates the key of the style to set.
363     * @param value Indicates the value matching the key.
364     * @since 1.0
365     * @version 1.0
366     */
367    void SetStyle(uint8_t key, int64_t value) override;
368
369    /**
370     * @brief Obtains the style of a button in a specific state.
371     *
372     * @param key Indicates the key of the style.
373     * @param state Indicates the button state, as enumerated in {@link ButtonState}.
374     * @return Returns the style of the button in the specific state.
375     * @since 1.0
376     * @version 1.0
377     */
378    int64_t GetStyleForState(uint8_t key, ButtonState state) const;
379
380    /**
381     * @brief Sets the style for a button in a specific state.
382     *
383     * @param key Indicates the key of the style to set.
384     * @param value Indicates the value matching the key.
385     * @param state Indicates the button state, as enumerated in {@link ButtonState}.
386     * @since 1.0
387     * @version 1.0
388     */
389    void SetStyleForState(uint8_t key, int64_t value, ButtonState state);
390
391    /**
392     * @brief Disables this button.
393     *
394     * @since 1.0
395     * @version 1.0
396     */
397    void Disable();
398
399    /**
400     * @brief Enables this button.
401     *
402     * @since 1.0
403     * @version 1.0
404     */
405    void Enable();
406
407    /**
408     * @brief Sets the state for a button. After the setting, calling {@link SetStyle}
409     *        will change the style of this button, but not its state.
410     *
411     * @param state Indicates the button state, as enumerated in {@link ButtonState}.
412     * @since 1.0
413     * @version 1.0
414     */
415    void SetStateForStyle(ButtonState state)
416    {
417        styleState_ = state;
418    }
419
420#if DEFAULT_ANIMATION
421    void EnableButtonAnimation(bool enable)
422    {
423        enableAnimation_ = enable;
424    }
425
426    /**
427     * @brief Obtains the value of a style.
428     *
429     * @param enableAnimation.
430     * @return Returns enableAnimation_.
431     */
432    bool GetEnableButtonAnimation() const
433    {
434        return enableAnimation_;
435    }
436#endif
437
438protected:
439    Image* defaultImgSrc_;
440    Image* triggeredImgSrc_;
441    ButtonImageSrc currentImgSrc_;
442    int16_t imgX_;
443    int16_t imgY_;
444    int16_t contentWidth_;
445    int16_t contentHeight_;
446    void SetState(ButtonState state);
447    bool InitImage();
448
449    ButtonState state_;
450    ButtonState styleState_;
451    Style* buttonStyles_[BTN_STATE_NUM];
452#if DEFAULT_ANIMATION
453    bool enableAnimation_;
454    friend class ButtonAnimator;
455    class ButtonAnimator final : public AnimatorCallback {
456    public:
457        ButtonAnimator() = delete;
458        ButtonAnimator(const ButtonAnimator&) = delete;
459        ButtonAnimator& operator=(const ButtonAnimator&) = delete;
460        ButtonAnimator(ButtonAnimator&&) = delete;
461        ButtonAnimator& operator=(ButtonAnimator&&) = delete;
462        ButtonAnimator(UIButton& button) : animator_(this, nullptr, 0, false), button_(button) {}
463        ~ButtonAnimator() {}
464
465        void Start();
466        void DrawMask(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea);
467        void Callback(UIView* view) override;
468        void OnStop(UIView& view) override;
469
470    private:
471        Animator animator_;
472        bool isReverseAnimation_ = false;
473        float scale_ = 1.0f;
474        UIButton& button_;
475    } animator_;
476#endif
477    bool buttonStyleAllocFlag_;
478
479private:
480    /** Sets up the theme styles */
481    void SetupThemeStyles();
482
483    void DrawImg(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea, OpacityType opaScale);
484};
485} // namespace OHOS
486#endif // GRAPHIC_LITE_UI_BUTTON_H
487