diff options
| -rw-r--r-- | include/saffron_api.h | 6 | ||||
| -rw-r--r-- | include/saffron_event_hooks.h | 13 | ||||
| -rw-r--r-- | include/saffron_window.h | 3 | ||||
| -rw-r--r-- | meson.build | 4 | ||||
| -rw-r--r-- | src/saffron_button.c | 37 | ||||
| -rw-r--r-- | src/saffron_event_hooks.c | 19 | ||||
| -rw-r--r-- | src/saffron_window.c | 6 | ||||
| -rw-r--r-- | tests/test_hooks.c | 36 | ||||
| -rw-r--r-- | tests/test_main.c | 9 |
9 files changed, 123 insertions, 10 deletions
diff --git a/include/saffron_api.h b/include/saffron_api.h index 8ad340c..964eaa9 100644 --- a/include/saffron_api.h +++ b/include/saffron_api.h @@ -36,4 +36,10 @@ SaffronButton* saffron_button_new_with_text(SaffronText* text, bool enabled, voi void saffron_widget_set_theme(SaffronWidget* widget, SaffronTheme* theme); +/* very special function for special things + * also because i need an event hook that somewhat works + * for kiwihacks hackathon (wpewebkit bindings thing) +*/ +void saffron_hook_sdl_all_events(SaffronWindow* window, bool (*callback)(SDL_Event* event), int priority); + #endif diff --git a/include/saffron_event_hooks.h b/include/saffron_event_hooks.h new file mode 100644 index 0000000..92e689e --- /dev/null +++ b/include/saffron_event_hooks.h @@ -0,0 +1,13 @@ +#ifndef SAFFRON_EVENT_HOOKS_H +#define SAFFRON_EVENT_HOOKS_H + +#include <SDL3/SDL.h> + +/* this file will not be included in saffron.h. this is an internal file for internal hooking in the event loop. */ + +typedef struct { + bool (*callback)(SDL_Event* event); + int priority; // higher num = higher priority +} SfInternalEventHook; + +#endif diff --git a/include/saffron_window.h b/include/saffron_window.h index 80aaa39..89bf684 100644 --- a/include/saffron_window.h +++ b/include/saffron_window.h @@ -2,6 +2,7 @@ #define SAFFRON_WINDOW_H #include <SDL3/SDL.h> +#include "saffron_event_hooks.h" #include "saffron_widget.h" typedef struct { @@ -10,6 +11,8 @@ typedef struct { SDL_Renderer *renderer; int w, h; const char* title; + SfInternalEventHook hooks[32]; + int hook_count; } SaffronWindow; #endif diff --git a/meson.build b/meson.build index 27420ee..14aa2f0 100644 --- a/meson.build +++ b/meson.build @@ -12,7 +12,8 @@ sources = [ 'src/saffron_widget.c', 'src/saffron_layout.c', 'src/saffron_text.c', - 'src/saffron_button.c' + 'src/saffron_button.c', + 'src/saffron_event_hooks.c', ] saffron_lib = static_library('saffron', sources, include_directories: inc, dependencies: deps) @@ -26,3 +27,4 @@ saffron_dep = declare_dependency(link_with: saffron_lib, include_directories: in test_deps += saffron_dep executable('saffron_test', 'tests/test_main.c', dependencies: test_deps) +executable('saffron_hooks_test', 'tests/test_hooks.c', dependencies: test_deps) diff --git a/src/saffron_button.c b/src/saffron_button.c index bef0018..b7db204 100644 --- a/src/saffron_button.c +++ b/src/saffron_button.c @@ -7,9 +7,9 @@ static void saffron_button_draw(SaffronWidget* widget, SDL_Renderer* renderer) { SaffronTheme* theme = widget->theme; if (!theme) return; - SaffronColor secondary = theme->secondary; + SaffronColor bg = theme->bg; SaffronColor tertiary = theme->tertiary; - SDL_SetRenderDrawColor(renderer, secondary.r, secondary.g, secondary.b, secondary.a); + SDL_SetRenderDrawColor(renderer, bg.r, bg.g, bg.b, bg.a); SDL_FRect rect = {widget->x, widget->y, widget->w, widget->h}; SDL_RenderFillRect(renderer, &rect); @@ -17,16 +17,41 @@ static void saffron_button_draw(SaffronWidget* widget, SDL_Renderer* renderer) { SDL_RenderRect(renderer, &rect); } +static void saffron_button_onclick(SaffronWidget* self) { + SaffronButton* btn = (SaffronButton*)self; + btn->callback(btn); +} + SaffronButton* saffron_button_new(bool enabled, void (*callback)(SaffronButton* self), int width, int height) { SaffronButton* button = malloc(sizeof(SaffronButton)); - saffron_widget_init((SaffronWidget*)button); + if (!button) return NULL; + + SaffronBox* box = saffron_box_new(SAFFRON_ORIENTATION_HORIZONTAL, SAFFRON_HALIGN_CENTER, SAFFRON_VALIGN_CENTER, 5, 5, 0, width, height); + if (!box) { + free(button); + return NULL; + } + + memcpy(&button->base, box, sizeof(SaffronBox)); + free(box); - ((SaffronWidget*)button)->type = SAFFRON_WIDGET_BUTTON; - ((SaffronWidget*)button)->draw = saffron_button_draw; + SaffronWidget* widget = (SaffronWidget*)button; + // We set it to type BOX because the layout engine needs to treat it as one: I'll remove the BUTTON enum later or make the layout engine check for both + widget->type = SAFFRON_WIDGET_BOX; + widget->draw = saffron_button_draw; + widget->on_click = saffron_button_onclick; + widget->children = NULL; + widget->child_count = 0; button->callback = callback; button->enabled = enabled; - button->base = *saffron_box_new(SAFFRON_ORIENTATION_HORIZONTAL, SAFFRON_HALIGN_CENTER, SAFFRON_VALIGN_CENTER, 5, 5, 0, width, height); + + return button; +} + +SaffronButton* saffron_button_new_with_text(SaffronText* text, bool enabled, void (*callback)(SaffronButton* self), int width, int height) { + SaffronButton* button = saffron_button_new(enabled, callback, width, height); + saffron_widget_add_child((SaffronWidget*)button, (SaffronWidget*)text); return button; } diff --git a/src/saffron_event_hooks.c b/src/saffron_event_hooks.c new file mode 100644 index 0000000..d3a2c43 --- /dev/null +++ b/src/saffron_event_hooks.c @@ -0,0 +1,19 @@ +#include "saffron_api.h" +#include <SDL3/SDL.h> +#include <saffron.h> +#include <saffron_event_hooks.h> + +void saffron_hook_sdl_all_events(SaffronWindow* window, bool (*callback)(SDL_Event* event), int priority) { + window->hooks[window->hook_count].callback = callback; + window->hooks[window->hook_count].priority = priority; + window->hook_count++; + for (int i = 0; i < window->hook_count; i++) { + for (int j = i + 1; j < window->hook_count; j++) { + if (window->hooks[j].priority > window->hooks[i].priority) { + SfInternalEventHook tmp = window->hooks[i]; + window->hooks[i] = window->hooks[j]; + window->hooks[j] = tmp; + } + } + } +} diff --git a/src/saffron_window.c b/src/saffron_window.c index 41bc050..34da341 100644 --- a/src/saffron_window.c +++ b/src/saffron_window.c @@ -14,6 +14,8 @@ SaffronWindow* saffron_window_new(const char* title, int w, int h) { window->title = title; window->w = w; window->h = h; + memset(window->hooks, 0, sizeof(window->hooks)); + window->hook_count = 0; Uint32 flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY; window->sdl_window = SDL_CreateWindow(title, w, h, flags); @@ -81,6 +83,10 @@ void saffron_window_main(SaffronWindow *window) { if (event.type == SDL_EVENT_WINDOW_RESIZED) { handle_window_resized(&event, window); } + for (int i = 0; i < window->hook_count; i++) { + bool consumed = window->hooks[i].callback(&event); + if (consumed) break; + } } SDL_SetRenderDrawColor(window->renderer, 0, 0, 0, 255); diff --git a/tests/test_hooks.c b/tests/test_hooks.c new file mode 100644 index 0000000..ad56aa9 --- /dev/null +++ b/tests/test_hooks.c @@ -0,0 +1,36 @@ +#include "saffron_api.h" +#include <saffron.h> +#include <SDL3/SDL.h> +#include <stdio.h> + +bool hook_callback(SDL_Event* event) { + printf("got an event!\n"); + return false; // we didnt consume the event +} + +bool hook_callback_2(SDL_Event* event) { + printf("second hook got an event!\n"); + return true; // we consumed the event +} + +bool hook_callback_3(SDL_Event* event) { + printf("you should never see this, a hook with higher priority (hook_callback_2) should have consumed this event\n"); + return false; +} + +int main() { + saffron_init(); + + SaffronWindow* window = saffron_window_new("Saffron hooks test", 800, 600); + + saffron_hook_sdl_all_events(window, hook_callback, 999); + saffron_hook_sdl_all_events(window, hook_callback_2, 2); + saffron_hook_sdl_all_events(window, hook_callback_3, 1); + + saffron_window_main(window); + + saffron_window_free(window); + saffron_quit(); + + return 0; +} diff --git a/tests/test_main.c b/tests/test_main.c index cb92189..087b32a 100644 --- a/tests/test_main.c +++ b/tests/test_main.c @@ -31,6 +31,10 @@ void my_test_onclick(SaffronWidget* self) { printf("clicked!\n"); } +static void button_click_handler(SaffronButton* self) { + printf("button clicked!\n"); +} + int main(void) { saffron_init(); @@ -61,13 +65,12 @@ int main(void) { TTF_Font* font = TTF_OpenFont("/usr/share/fonts/fantasque-sans-mono/FantasqueSansMono-Regular.otf", 24); SaffronText* test3 = saffron_text_new("Mangoes", font); - /* become lunatic, add custom clickhandler to.. text????????????? */ - ((SaffronWidget*)test3)->on_click = my_test_onclick; + SaffronButton* btn = saffron_button_new_with_text(test3, true, &button_click_handler, 200, 150); saffron_widget_add_child(window->root, test); saffron_widget_add_child(window->root, box); saffron_widget_add_child(box, test2); - saffron_widget_add_child(box, (SaffronWidget*)test3); + saffron_widget_add_child(window->root, (SaffronWidget*)btn); saffron_window_main(window); |
