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 
42 namespace 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  */
51 class UIButton : public UIView {
52 public:
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      */
UIButton(const char * id)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      */
GetViewType()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      */
SetImagePosition(const int16_t x,const int16_t y)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      */
GetImageX()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      */
GetImageY()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      */
GetWidth()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      */
GetHeight()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      */
SetWidth(int16_t width)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      */
SetHeight(int16_t height)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      */
GetContentRect()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 
GetOrigContentRect()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      */
SetStyle(Style & style)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      */
SetStateForStyle(ButtonState state)415     void SetStateForStyle(ButtonState state)
416     {
417         styleState_ = state;
418     }
419 
420 #if DEFAULT_ANIMATION
EnableButtonAnimation(bool enable)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      */
GetEnableButtonAnimation()432     bool GetEnableButtonAnimation() const
433     {
434         return enableAnimation_;
435     }
436 #endif
437 
438 protected:
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;
ButtonAnimator(UIButton & button)462         ButtonAnimator(UIButton& button) : animator_(this, nullptr, 0, false), button_(button) {}
~ButtonAnimator()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 
479 private:
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