PatchworkOS
Loading...
Searching...
No Matches
button.c
Go to the documentation of this file.
1#include "internal.h"
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7typedef struct button
8{
13} button_t;
14
15static void button_draw(element_t* elem, button_t* button)
16{
18
19 drawable_t draw;
20 element_draw_begin(elem, &draw);
21
22 const theme_t* theme = element_get_theme(elem);
23
24 if (elem->flags & ELEMENT_FLAT)
25 {
26 if (button->isPressed || button->isHovered)
27 {
29 }
30 else
31 {
32 draw_rect(&draw, &rect, theme->button.backgroundNormal);
33 }
34 }
35 else
36 {
37 if (!(elem->flags & ELEMENT_NO_BEZEL))
38 {
39 draw_bezel(&draw, &rect, theme->bezelSize, theme->button.bezel);
41 }
42
43 if (button->isPressed)
44 {
46 }
47 else
48 {
50 }
52
53 draw_rect(&draw, &rect, theme->button.backgroundNormal);
54 }
55
56 if (!(elem->flags & ELEMENT_NO_OUTLINE))
57 {
59 if (button->isFocused)
60 {
61 draw_dashed_outline(&draw, &rect, theme->button.bezel, 2, 2);
62 }
63 RECT_SHRINK(&rect, 2);
64 }
65
66 if (elem->image != NULL)
67 {
68 rect_t imageDestRect;
69 int32_t imageWidth = image_width(elem->image);
70 int32_t imageHeight = image_height(elem->image);
71
72 switch (elem->imageProps.xAlign)
73 {
74 case ALIGN_MIN:
75 {
76 imageDestRect.left = rect.left;
77 }
78 break;
79 case ALIGN_CENTER:
80 {
81 imageDestRect.left = rect.left + (RECT_WIDTH(&rect) - imageWidth) / 2;
82 }
83 break;
84 case ALIGN_MAX:
85 {
86 imageDestRect.left = rect.left + RECT_WIDTH(&rect) - imageWidth;
87 }
88 break;
89 default:
90 {
91 imageDestRect.left = rect.left + (RECT_WIDTH(&rect) - imageWidth) / 2;
92 }
93 break;
94 }
95
96 switch (elem->imageProps.yAlign)
97 {
98 case ALIGN_MIN:
99 {
100 imageDestRect.top = rect.top;
101 }
102 break;
103 case ALIGN_CENTER:
104 {
105 imageDestRect.top = rect.top + (RECT_HEIGHT(&rect) - imageHeight) / 2;
106 }
107 break;
108 case ALIGN_MAX:
109 {
110 imageDestRect.top = rect.top + RECT_HEIGHT(&rect) - imageHeight;
111 }
112 break;
113 default:
114 {
115 imageDestRect.top = rect.top + (RECT_HEIGHT(&rect) - imageHeight) / 2;
116 }
117 break;
118 }
119
120 imageDestRect.right = imageDestRect.left + imageWidth;
121 imageDestRect.bottom = imageDestRect.top + imageHeight;
122
123 draw_image_blend(&draw, elem->image, &imageDestRect, &elem->imageProps.srcOffset);
124 }
125
126 if ((elem->flags & ELEMENT_FLAT) && (button->isHovered || button->isPressed))
127 {
129 elem->text);
130 }
131 else
132 {
134 elem->text);
135 }
136
137 element_draw_end(elem, &draw);
138}
139
141{
142 levent_action_t event = {.source = elem->id, .type = type};
143 display_push(elem->win->disp, elem->win->surface, LEVENT_ACTION, &event, sizeof(levent_action_t));
144}
145
146static uint64_t button_procedure(window_t* win, element_t* elem, const event_t* event)
147{
148 (void)win; // Unused
149
150 switch (event->type)
151 {
152 case LEVENT_INIT:
153 {
154 button_t* button = malloc(sizeof(button_t));
155 if (button == NULL)
156 {
157 errno = ENOMEM;
158 return ERR;
159 }
160 button->mouseButtons = 0;
161 button->isPressed = false;
162 button->isHovered = false;
163 button->isFocused = false;
164
165 element_set_private(elem, button);
166 }
167 break;
168 case LEVENT_DEINIT:
169 {
170 button_t* button = element_get_private(elem);
171 free(button);
172 }
173 break;
174 case LEVENT_REDRAW:
175 {
176 button_t* button = element_get_private(elem);
177 button_draw(elem, button);
178 }
179 break;
180 case EVENT_MOUSE:
181 {
182 button_t* button = element_get_private(elem);
183 bool prevIsPressed = button->isPressed;
184 bool prevIsHovered = button->isHovered;
185 bool prevIsFocused = button->isFocused;
186
187 rect_t rect = element_get_content_rect(elem);
188
189 bool mouseInBounds = RECT_CONTAINS_POINT(&rect, &event->mouse.pos);
190 bool leftPressed = (event->mouse.pressed & MOUSE_LEFT) != 0;
191 bool leftReleased = (event->mouse.released & MOUSE_LEFT) != 0;
192
193 if (elem->flags & ELEMENT_TOGGLE)
194 {
195 if (mouseInBounds)
196 {
197 button->isHovered = true;
198
199 if (leftPressed)
200 {
201 button->isPressed = !button->isPressed;
202 button->isFocused = true;
203
205 }
206 }
207 else
208 {
209 button->isHovered = false;
210
211 if (leftPressed)
212 {
213 button->isFocused = false;
214 }
215 }
216 }
217 else
218 {
219 if (mouseInBounds)
220 {
221 button->isHovered = true;
222
223 if (leftPressed && !button->isPressed)
224 {
225 button->isPressed = true;
226 button->isFocused = true;
228 }
229 else if (leftReleased && button->isPressed)
230 {
231 button->isPressed = false;
233 }
234 }
235 else
236 {
237 button->isHovered = false;
238
239 if (button->isPressed)
240 {
241 button->isPressed = false;
243 }
244
245 if (leftPressed)
246 {
247 button->isFocused = false;
248 }
249 }
250 }
251
252 if (button->isPressed != prevIsPressed || button->isHovered != prevIsHovered ||
253 button->isFocused != prevIsFocused)
254 {
255 button_draw(elem, button);
256 }
257 }
258 break;
260 {
261 button_t* button = element_get_private(elem);
262 if (button->isHovered)
263 {
264 button->isHovered = false;
265 button_draw(elem, button);
266 }
267 }
268 break;
269 case EVENT_REPORT:
270 {
271 button_t* button = element_get_private(elem);
272 if (!(event->report.info.flags & SURFACE_FOCUSED) && button->isFocused)
273 {
274 button->isFocused = false;
275 button_draw(elem, button);
276 }
277 }
278 break;
280 {
281 button_t* button = element_get_private(elem);
282 switch (event->lForceAction.action)
283 {
284 case ACTION_PRESS:
285 {
286 button->isPressed = true;
287 button->isFocused = true;
288 }
289 break;
290 case ACTION_RELEASE:
291 {
292 button->isPressed = false;
293 button->isFocused = false;
294 }
295 break;
296 default:
297 {
298 }
299 }
300 button_draw(elem, button);
301 }
302 break;
303 }
304
305 return 0;
306}
307
308element_t* button_new(element_t* parent, element_id_t id, const rect_t* rect, const char* text, element_flags_t flags)
309{
310 return element_new(parent, id, rect, text, flags, button_procedure, NULL);
311}
static uint64_t button_procedure(window_t *win, element_t *elem, const event_t *event)
Definition button.c:146
static void button_draw(element_t *elem, button_t *button)
Definition button.c:15
static void button_send_action(element_t *elem, action_type_t type)
Definition button.c:140
void display_push(display_t *disp, surface_id_t target, event_type_t type, void *data, uint64_t size)
Push an event to the display's internal event queue.
Definition display.c:349
void draw_image_blend(drawable_t *draw, image_t *image, const rect_t *destRect, const point_t *srcPoint)
Draw an image with alpha blending.
Definition drawable.c:550
void draw_rect(drawable_t *draw, const rect_t *rect, pixel_t pixel)
Draw a filled rectangle.
Definition drawable.c:7
void draw_text(drawable_t *draw, const rect_t *rect, const font_t *font, align_t xAlign, align_t yAlign, pixel_t pixel, const char *text)
Draw text to a drawable.
Definition drawable.c:669
void draw_dashed_outline(drawable_t *draw, const rect_t *rect, pixel_t pixel, uint32_t length, int32_t width)
Draw a dashed outline just inside the given rectangle.
Definition drawable.c:259
void draw_bezel(drawable_t *draw, const rect_t *rect, uint64_t width, pixel_t pixel)
Draw a filled border bezel just inside the given rectangle.
Definition drawable.c:339
void draw_frame(drawable_t *draw, const rect_t *rect, uint64_t width, pixel_t foreground, pixel_t background)
Draw a skeuomorphic frame.
Definition drawable.c:204
@ ALIGN_MIN
Definition drawable.h:51
@ ALIGN_CENTER
Definition drawable.h:49
@ ALIGN_MAX
Definition drawable.h:50
void element_set_private(element_t *elem, void *private)
Set private data for an element.
Definition element.c:163
theme_t * element_get_theme(element_t *elem)
Get the theme of an element.
Definition element.c:401
#define ELEMENT_NO_BEZEL
Definition element.h:46
#define ELEMENT_TOGGLE
Definition element.h:44
#define ELEMENT_NO_OUTLINE
Definition element.h:47
void element_draw_end(element_t *elem, drawable_t *draw)
End drawing to an element.
Definition element.c:427
element_t * element_new(element_t *parent, element_id_t id, const rect_t *rect, const char *text, element_flags_t flags, procedure_t procedure, void *private)
Allocate and initialize a new element.
Definition element.c:48
rect_t element_get_content_rect(element_t *elem)
Get the element's rectangle in local coordinates.
Definition element.c:213
uint64_t element_flags_t
Element flags type.
Definition element.h:41
void element_draw_begin(element_t *elem, drawable_t *draw)
Begin drawing to an element.
Definition element.c:411
uint64_t element_id_t
Element identifier type.
Definition element_id.h:23
void * element_get_private(element_t *elem)
Get private data for an element.
Definition element.c:173
#define ELEMENT_FLAT
Definition element.h:45
#define LEVENT_FORCE_ACTION
Definition event.h:104
#define EVENT_CURSOR_LEAVE
Definition event.h:88
#define EVENT_MOUSE
Definition event.h:85
#define LEVENT_DEINIT
Definition event.h:100
#define LEVENT_REDRAW
Definition event.h:101
#define LEVENT_INIT
Definition event.h:99
#define LEVENT_ACTION
Definition event.h:102
action_type_t
Action type.
Definition event.h:48
#define EVENT_REPORT
Definition event.h:89
@ ACTION_PRESS
Definition event.h:51
@ ACTION_RELEASE
Definition event.h:50
@ ACTION_CANCEL
Definition event.h:52
@ SURFACE_FOCUSED
Definition surface.h:50
element_t * button_new(element_t *parent, element_id_t id, const rect_t *rect, const char *text, element_flags_t flags)
Create a new button element.
Definition button.c:308
#define ENOMEM
Out of memory.
Definition errno.h:92
#define errno
Error number variable.
Definition errno.h:27
mouse_buttons_t
Mouse buttons enum.
Definition mouse.h:31
@ MOUSE_LEFT
Left mouse button.
Definition mouse.h:35
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
uint64_t image_height(image_t *image)
Definition image.c:99
uint64_t image_width(image_t *image)
Definition image.c:94
#define RECT_SHRINK(rect, margin)
Definition rect.h:81
#define RECT_HEIGHT(rect)
Definition rect.h:39
#define RECT_WIDTH(rect)
Definition rect.h:38
#define RECT_CONTAINS_POINT(rect, point)
Definition rect.h:61
__INT32_TYPE__ int32_t
Definition stdint.h:14
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC void free(void *ptr)
Definition free.c:11
bool isHovered
Definition button.c:11
bool isPressed
Definition button.c:10
mouse_buttons_t mouseButtons
Definition button.c:9
bool isFocused
Definition button.c:12
Drawable structure.
Definition drawable.h:35
Opaque element structure.
Definition internal.h:23
element_id_t id
Definition internal.h:27
image_props_t imageProps
Definition internal.h:36
image_t * image
Definition internal.h:35
element_flags_t flags
Definition internal.h:32
window_t * win
Definition internal.h:29
char * text
Definition internal.h:33
text_props_t textProps
Definition internal.h:34
point_t pos
Definition event.h:155
surface_info_t info
Definition event.h:182
Event structure.
Definition event.h:271
event_report_t report
Definition event.h:281
levent_force_action_t lForceAction
Definition event.h:289
event_type_t type
Definition event.h:272
event_mouse_t mouse
Definition event.h:278
point_t srcOffset
Definition element.h:80
align_t xAlign
Definition element.h:78
align_t yAlign
Definition element.h:79
Library Action event.
Definition event.h:244
element_id_t source
Definition event.h:245
action_type_t action
Definition event.h:257
Definition rect.h:13
int32_t bottom
Definition rect.h:17
int32_t top
Definition rect.h:15
int32_t right
Definition rect.h:16
int32_t left
Definition rect.h:14
surface_flags_t flags
Definition surface.h:61
font_t * font
Definition element.h:66
pixel_t backgroundNormal
Definition theme.h:35
pixel_t backgroundSelectedEnd
Definition theme.h:37
pixel_t highlight
Definition theme.h:45
pixel_t foregroundSelected
Definition theme.h:43
pixel_t foregroundNormal
Definition theme.h:40
pixel_t bezel
Definition theme.h:44
pixel_t shadow
Definition theme.h:46
Theme structure.
Definition theme.h:71
int64_t bezelSize
Definition theme.h:84
int64_t smallPadding
Definition theme.h:88
theme_color_set_t button
Definition theme.h:72
int64_t frameSize
Definition theme.h:83
Opaque window structure.
Definition internal.h:44
surface_id_t surface
Definition internal.h:52
display_t * disp
Definition internal.h:46
static theme_t theme
Definition theme.c:12