1 #include "button.h"
2 
3 #include "draw.h"
4 #include "tooltip.h"
5 
6 #include "../macros.h"
7 #include "../theme.h"
8 #include "../ui.h"
9 
calculate_pos_and_width(BUTTON * b,int * x,int * w)10 static void calculate_pos_and_width(BUTTON *b, int *x, int *w) {
11     int real_w = *w;
12 
13     // Increase width if needed, so that button text fits.
14     if (maybe_i18nal_string_is_valid(&b->button_text)) {
15         STRING *str = maybe_i18nal_string_get(&b->button_text);
16 
17         int min_w = textwidth(str->str, str->length);
18 
19         if (*w < min_w) {
20             *w = min_w + SCALE(12); // 12 seems like a perfectly fine number,
21                                     // eventually we should use logic here.
22         }
23     }
24 
25     // Push away from the right border to fit,
26     // if our panel is right-adjusted.
27     if (b->panel.x < 0) {
28         *x -= *w - real_w;
29     }
30 }
31 
button_draw(BUTTON * b,int x,int y,int width,int height)32 void button_draw(BUTTON *b, int x, int y, int width, int height) {
33     // If `update` function is defined, call it on each draw
34     if (b->update) {
35         b->update(b);
36     }
37 
38     // Button is hidden
39     if (b->nodraw) {
40         return;
41     }
42 
43     // Ensure that font is set before calculating position and width.
44     setfont(FONT_SELF_NAME);
45 
46     // Button contents color
47     uint32_t color_text = b->mousedown ? b->ct2 : (b->mouseover ? b->ct2 : b->ct1);
48     setcolor(color_text);
49 
50     int real_w = width;
51     calculate_pos_and_width(b, &x, &width);
52 
53     // Button background color
54     uint32_t color_bg = b->mousedown ? b->c3 : (b->mouseover ? b->c2 : b->c1);
55 
56     if (b->bm_fill) {
57         drawalpha(b->bm_fill, x, y, real_w, height, color_bg);
58     } else {
59         draw_rect_fill(x, y, real_w, height, b->disabled ? b->cd : color_bg);
60     }
61 
62     if (b->bm_icon) {
63         const int icon_x = real_w / 2 - SCALE(b->icon_w) / 2;
64         const int icon_y = height / 2 - SCALE(b->icon_h) / 2;
65         drawalpha(b->bm_icon, x + icon_x, y + icon_y, SCALE(b->icon_w), SCALE(b->icon_h), color_text);
66     }
67 
68     if (maybe_i18nal_string_is_valid(&b->button_text)) {
69         if (b->bm_fill) {
70             while (width > real_w) {
71                 // The text didn't fit into the original width.
72                 // Fill the rest of the new width with the image
73                 // and hope for the best.
74                 drawalpha(b->bm_fill, x + width - real_w, y, real_w, height, color_bg);
75                 width -= real_w / 2 + 1;
76             }
77         }
78         STRING *s = maybe_i18nal_string_get(&b->button_text);
79         drawtext(x + SCALE(6), y + SCALE(2), s->str, s->length);
80     }
81 }
82 
button_mmove(BUTTON * b,int UNUSED (x),int UNUSED (y),int width,int height,int mx,int my,int UNUSED (dx),int UNUSED (dy))83 bool button_mmove(BUTTON *b, int UNUSED(x), int UNUSED(y), int width, int height, int mx, int my, int UNUSED(dx),
84                   int UNUSED(dy)) {
85     // Ensure that font is set before calculating position and width.
86     setfont(FONT_SELF_NAME);
87 
88     int real_x = 0, real_w = width;
89     calculate_pos_and_width(b, &real_x, &real_w);
90 
91     bool mouseover = inrect(mx, my, real_x, 0, real_w, height);
92     if (mouseover) {
93         if (!b->disabled) {
94             cursor = CURSOR_HAND;
95         }
96 
97         if (maybe_i18nal_string_is_valid(&b->tooltip_text)) {
98             tooltip_new(&b->tooltip_text);
99         }
100     }
101     if (mouseover != b->mouseover) {
102         b->mouseover = mouseover;
103         return 1;
104     }
105 
106     return 0;
107 }
108 
button_mdown(BUTTON * b)109 bool button_mdown(BUTTON *b) {
110     if (b->mouseover) {
111         if (!b->mousedown && b->on_mdn) {
112             b->on_mdn();
113         }
114 
115         b->mousedown = true;
116         return 1;
117     }
118 
119     return 0;
120 }
121 
button_mup(BUTTON * b)122 bool button_mup(BUTTON *b) {
123     if (b->mousedown) {
124         if (b->mouseover && b->on_mup) {
125             b->on_mup();
126         }
127 
128         b->mousedown = 0;
129         return 1;
130     }
131 
132     return 0;
133 }
134 
button_mright(BUTTON * b)135 bool button_mright(BUTTON *b) {
136     if (b->mouseover && b->onright) {
137         b->onright();
138         return 1;
139     }
140 
141     return 0;
142 }
143 
button_mwheel(BUTTON * UNUSED (b),int UNUSED (height),double UNUSED (d),bool UNUSED (smooth))144 bool button_mwheel(BUTTON *UNUSED(b), int UNUSED(height), double UNUSED(d), bool UNUSED(smooth)) { return 0; }
145 
button_mleave(BUTTON * b)146 bool button_mleave(BUTTON *b) {
147     if (b->mouseover) {
148         b->mouseover = 0;
149         return 1;
150     }
151 
152     return 0;
153 }
154 
155 
156 // Logic update functions
157 // TODO should these live here?
158 // TODO delete button_setcolor_* and move this setting and logic to the struct
159 /* Quick color change functions */
button_setcolors_success(BUTTON * b)160 void button_setcolors_success(BUTTON *b) {
161     b->c1  = COLOR_BTN_SUCCESS_BKGRND;
162     b->c2  = COLOR_BTN_SUCCESS_BKGRND_HOVER;
163     b->c3  = COLOR_BTN_SUCCESS_BKGRND_HOVER;
164     b->ct1 = COLOR_BTN_SUCCESS_TEXT;
165     b->ct2 = COLOR_BTN_SUCCESS_TEXT_HOVER;
166 }
167 
button_setcolors_danger(BUTTON * b)168 void button_setcolors_danger(BUTTON *b) {
169     b->c1  = COLOR_BTN_DANGER_BACKGROUND;
170     b->c2  = COLOR_BTN_DANGER_BKGRND_HOVER;
171     b->c3  = COLOR_BTN_DANGER_BKGRND_HOVER;
172     b->ct1 = COLOR_BTN_DANGER_TEXT;
173     b->ct2 = COLOR_BTN_DANGER_TEXT_HOVER;
174 }
175 
button_setcolors_warning(BUTTON * b)176 void button_setcolors_warning(BUTTON *b) {
177     b->c1  = COLOR_BTN_WARNING_BKGRND;
178     b->c2  = COLOR_BTN_WARNING_BKGRND_HOVER;
179     b->c3  = COLOR_BTN_WARNING_BKGRND_HOVER;
180     b->ct1 = COLOR_BTN_WARNING_TEXT;
181     b->ct2 = COLOR_BTN_WARNING_TEXT_HOVER;
182 }
183 
button_setcolors_disabled(BUTTON * b)184 void button_setcolors_disabled(BUTTON *b) {
185     b->c1  = COLOR_BTN_DISABLED_BKGRND;
186     b->c2  = COLOR_BTN_DISABLED_BKGRND;
187     b->c3  = COLOR_BTN_DISABLED_BKGRND;
188     b->ct1 = COLOR_BTN_DISABLED_TEXT;
189     b->ct2 = COLOR_BTN_DISABLED_TEXT;
190 }
191