PatchworkOS  19e446b
A non-POSIX operating system.
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#include <sys/defs.h>
7
8typedef struct button
9{
14} button_t;
15
16static void button_draw(element_t* elem, button_t* button)
17{
19
20 drawable_t draw;
21 element_draw_begin(elem, &draw);
22
23 const theme_t* theme = element_get_theme(elem);
24
25 if (elem->flags & ELEMENT_FLAT)
26 {
27 if (button->isPressed || button->isHovered)
28 {
30 }
31 else
32 {
33 draw_rect(&draw, &rect, theme->button.backgroundNormal);
34 }
35 }
36 else
37 {
38 if (!(elem->flags & ELEMENT_NO_BEZEL))
39 {
40 draw_bezel(&draw, &rect, theme->bezelSize, theme->button.bezel);
42 }
43
44 if (button->isPressed)
45 {
47 }
48 else
49 {
51 }
53
54 draw_rect(&draw, &rect, theme->button.backgroundNormal);
55 }
56
57 if (!(elem->flags & ELEMENT_NO_OUTLINE))
58 {
60 if (button->isFocused)
61 {
62 draw_dashed_outline(&draw, &rect, theme->button.bezel, 2, 2);
63 }
64 RECT_SHRINK(&rect, 2);
65 }
66
67 if (elem->image != NULL)
68 {
69 rect_t imageDestRect;
70 int32_t imageWidth = image_width(elem->image);
71 int32_t imageHeight = image_height(elem->image);
72
73 switch (elem->imageProps.xAlign)
74 {
75 case ALIGN_MIN:
76 {
77 imageDestRect.left = rect.left;
78 }
79 break;
80 case ALIGN_CENTER:
81 {
82 imageDestRect.left = rect.left + (RECT_WIDTH(&rect) - imageWidth) / 2;
83 }
84 break;
85 case ALIGN_MAX:
86 {
87 imageDestRect.left = rect.left + RECT_WIDTH(&rect) - imageWidth;
88 }
89 break;
90 default:
91 {
92 imageDestRect.left = rect.left + (RECT_WIDTH(&rect) - imageWidth) / 2;
93 }
94 break;
95 }
96
97 switch (elem->imageProps.yAlign)
98 {
99 case ALIGN_MIN:
100 {
101 imageDestRect.top = rect.top;
102 }
103 break;
104 case ALIGN_CENTER:
105 {
106 imageDestRect.top = rect.top + (RECT_HEIGHT(&rect) - imageHeight) / 2;
107 }
108 break;
109 case ALIGN_MAX:
110 {
111 imageDestRect.top = rect.top + RECT_HEIGHT(&rect) - imageHeight;
112 }
113 break;
114 default:
115 {
116 imageDestRect.top = rect.top + (RECT_HEIGHT(&rect) - imageHeight) / 2;
117 }
118 break;
119 }
120
121 imageDestRect.right = imageDestRect.left + imageWidth;
122 imageDestRect.bottom = imageDestRect.top + imageHeight;
123
124 draw_image_blend(&draw, elem->image, &imageDestRect, &elem->imageProps.srcOffset);
125 }
126
127 if ((elem->flags & ELEMENT_FLAT) && (button->isHovered || button->isPressed))
128 {
130 elem->text);
131 }
132 else
133 {
135 elem->text);
136 }
137
138 element_draw_end(elem, &draw);
139}
140
142{
143 event_lib_action_t event = {.source = elem->id, .type = type};
144 display_push(elem->win->disp, elem->win->surface, EVENT_LIB_ACTION, &event, sizeof(event_lib_action_t));
145}
146
147static uint64_t button_procedure(window_t* win, element_t* elem, const event_t* event)
148{
149 UNUSED(win);
150
151 switch (event->type)
152 {
153 case EVENT_LIB_INIT:
154 {
155 button_t* button = malloc(sizeof(button_t));
156 if (button == NULL)
157 {
158 errno = ENOMEM;
159 return ERR;
160 }
161 button->mouseButtons = 0;
162 button->isPressed = false;
163 button->isHovered = false;
164 button->isFocused = false;
165
166 element_set_private(elem, button);
167 }
168 break;
169 case EVENT_LIB_DEINIT:
170 {
171 button_t* button = element_get_private(elem);
172 free(button);
173 }
174 break;
175 case EVENT_LIB_REDRAW:
176 {
177 button_t* button = element_get_private(elem);
178 button_draw(elem, button);
179 }
180 break;
181 case EVENT_MOUSE:
182 {
183 button_t* button = element_get_private(elem);
184 bool prevIsPressed = button->isPressed;
185 bool prevIsHovered = button->isHovered;
186 bool prevIsFocused = button->isFocused;
187
188 rect_t rect = element_get_content_rect(elem);
189
190 bool mouseInBounds = RECT_CONTAINS_POINT(&rect, &event->mouse.pos);
191 bool leftPressed = (event->mouse.pressed & MOUSE_LEFT) != 0;
192 bool leftReleased = (event->mouse.released & MOUSE_LEFT) != 0;
193
194 if (elem->flags & ELEMENT_TOGGLE)
195 {
196 if (mouseInBounds)
197 {
198 button->isHovered = true;
199
200 if (leftPressed)
201 {
202 button->isPressed = !button->isPressed;
203 button->isFocused = true;
204
206 }
207 }
208 else
209 {
210 button->isHovered = false;
211
212 if (leftPressed)
213 {
214 button->isFocused = false;
215 }
216 }
217 }
218 else
219 {
220 if (mouseInBounds)
221 {
222 button->isHovered = true;
223
224 if (leftPressed && !button->isPressed)
225 {
226 button->isPressed = true;
227 button->isFocused = true;
229 }
230 else if (leftReleased && button->isPressed)
231 {
232 button->isPressed = false;
234 }
235 }
236 else
237 {
238 button->isHovered = false;
239
240 if (button->isPressed)
241 {
242 button->isPressed = false;
244 }
245
246 if (leftPressed)
247 {
248 button->isFocused = false;
249 }
250 }
251 }
252
253 if (button->isPressed != prevIsPressed || button->isHovered != prevIsHovered ||
254 button->isFocused != prevIsFocused)
255 {
256 button_draw(elem, button);
257 }
258 }
259 break;
261 {
262 button_t* button = element_get_private(elem);
263 if (button->isHovered)
264 {
265 button->isHovered = false;
266 button_draw(elem, button);
267 }
268 }
269 break;
270 case EVENT_REPORT:
271 {
272 button_t* button = element_get_private(elem);
273 if (!(event->report.info.flags & SURFACE_FOCUSED) && button->isFocused)
274 {
275 button->isFocused = false;
276 button_draw(elem, button);
277 }
278 }
279 break;
281 {
282 button_t* button = element_get_private(elem);
283 switch (event->libForceAction.action)
284 {
285 case ACTION_PRESS:
286 {
287 button->isPressed = true;
288 button->isFocused = true;
289 }
290 break;
291 case ACTION_RELEASE:
292 {
293 button->isPressed = false;
294 button->isFocused = false;
295 }
296 break;
297 default:
298 {
299 }
300 }
301 button_draw(elem, button);
302 }
303 break;
304 }
305
306 return 0;
307}
308
309element_t* button_new(element_t* parent, element_id_t id, const rect_t* rect, const char* text, element_flags_t flags)
310{
311 return element_new(parent, id, rect, text, flags, button_procedure, NULL);
312}
static uint64_t button_procedure(window_t *win, element_t *elem, const event_t *event)
Definition button.c:147
static void button_draw(element_t *elem, button_t *button)
Definition button.c:16
static void button_send_action(element_t *elem, action_type_t type)
Definition button.c:141
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:321
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:667
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
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
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 *data)
Allocate and initialize a new element.
Definition element.c:48
#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
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_set_private(element_t *elem, void *data)
Set private data for an element.
Definition element.c:163
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 EVENT_LIB_FORCE_ACTION
Definition event.h:103
#define EVENT_CURSOR_LEAVE
Definition event.h:87
#define EVENT_MOUSE
Definition event.h:84
#define EVENT_LIB_DEINIT
Definition event.h:99
#define EVENT_LIB_INIT
Definition event.h:98
#define EVENT_LIB_REDRAW
Definition event.h:100
action_type_t
Action type.
Definition event.h:47
#define EVENT_REPORT
Definition event.h:88
mouse_buttons_t
Mouse buttons enum.
Definition event.h:173
#define EVENT_LIB_ACTION
Definition event.h:101
@ ACTION_PRESS
Definition event.h:50
@ ACTION_RELEASE
Definition event.h:49
@ ACTION_CANCEL
Definition event.h:51
@ MOUSE_LEFT
Left mouse button.
Definition event.h:175
@ 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:309
#define ENOMEM
Out of memory.
Definition errno.h:92
#define errno
Error number variable.
Definition errno.h:27
#define UNUSED(x)
Mark a variable as unused.
Definition defs.h:96
#define NULL
Pointer error value.
Definition NULL.h:25
#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
static const path_flag_t flags[]
Definition path.c:47
#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:12
bool isPressed
Definition button.c:11
mouse_buttons_t mouseButtons
Definition button.c:10
bool isFocused
Definition button.c:13
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
Library Action event.
Definition event.h:279
element_id_t source
Definition event.h:280
action_type_t action
Definition event.h:292
point_t pos
Definition event.h:190
surface_info_t info
Definition event.h:217
Event structure.
Definition event.h:306
event_report_t report
Definition event.h:316
event_type_t type
Definition event.h:307
event_mouse_t mouse
Definition event.h:313
event_lib_force_action_t libForceAction
Definition event.h:324
point_t srcOffset
Definition element.h:80
align_t xAlign
Definition element.h:78
align_t yAlign
Definition element.h:79
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