From a7284d1250b3605a471daddb9a214c2fa5978f82 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Tue, 29 Apr 2025 13:22:06 -0400 Subject: image widget --- main.c | 12 +++--------- renderer.c | 30 ++++++++++++++++++++---------- renderer.h | 4 ++-- ui.c | 5 ++++- ui.h | 2 ++ widget.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ widget.h | 10 ++++++++++ 7 files changed, 87 insertions(+), 22 deletions(-) diff --git a/main.c b/main.c index 60781a9..1edaeda 100644 --- a/main.c +++ b/main.c @@ -396,24 +396,18 @@ comp_select(mu_Context *ctx, UI *ui) { static void comp_img(mu_Context *ctx, UI *ui) { + int w, h; mu_Rect r; - const char *data; - int id, w, h; + /* Row that covers the rest of the window. */ r_get_window_size(&w, &h); mu_layout_row(ctx, 1, &w, h); - - data = ui->comps[ui->comp_select.idx].imgfile; - id = mu_get_id(ctx, &data, sizeof(data)); - r = mu_layout_next(ctx); r.w = w - r.x - ctx->style->spacing; r.h = h - r.y - ctx->style->spacing; mu_layout_set_next(ctx, r, 0); - mu_update_control(ctx, id, r, 0); - - mu_draw_icon(ctx, 0, r, (mu_Color) {0, 0, 0, 0}); + w_image(ctx, &ui->comp_img); } static void diff --git a/renderer.c b/renderer.c index 158f7e2..900a6c9 100644 --- a/renderer.c +++ b/renderer.c @@ -298,8 +298,9 @@ r_get_window_size(int *w, int*h) { } } +/* Load an image and add it to the list of icons. Returns the id of the icon, or -1 on error. */ int -r_push_icon(const char *path) { +r_add_icon(const char *path) { SDL_Surface *surface; expect(icon_list.idx < ICONLIST_SIZE); @@ -307,23 +308,32 @@ r_push_icon(const char *path) { surface = IMG_Load(path); if (!surface) { fprintf(stderr, "failed to load %s: %s\n", path, SDL_GetError()); - return 1; + return -1; } icon_list.items[icon_list.idx] = SDL_CreateTextureFromSurface(renderer, surface); if (!icon_list.items[icon_list.idx]) { fprintf(stderr, "%s\n", SDL_GetError()); SDL_FreeSurface(surface); - return 1; + return -1; } - icon_list.idx++; SDL_FreeSurface(surface); - return 0; + return icon_list.idx++; } +/* Remove the icon with the specified id from the icons list. */ void -r_pop_icon(void) { - if (icon_list.idx <= 0) { - return; - } - SDL_DestroyTexture(icon_list.items[--icon_list.idx]); +r_remove_icon(int id) { + SDL_Texture **dst, **src; + size_t size; + + expect(id >= 0 && id < icon_list.idx); + + SDL_DestroyTexture(icon_list.items[id]); + + dst = icon_list.items + id; + src = icon_list.items + id + 1; + size = (icon_list.idx - id - 1) * sizeof(*icon_list.items); + memmove(dst, src, size); + + icon_list.idx--; } diff --git a/renderer.h b/renderer.h index 23d9123..0a31578 100644 --- a/renderer.h +++ b/renderer.h @@ -3,5 +3,5 @@ void r_free(void); void r_input(mu_Context *ctx); void r_render(mu_Context *ctx); void r_get_window_size(int *w, int *h); -int r_push_icon(const char *path); -void r_pop_icon(void); +int r_add_icon(const char *path); +void r_remove_icon(int); diff --git a/ui.c b/ui.c index 3393d65..882206b 100644 --- a/ui.c +++ b/ui.c @@ -92,6 +92,7 @@ void free_ui(UI *ui) { w_free_select_compressor(&ui->comp_select); free(ui->comps); + w_free_image(&ui->comp_img); } static void @@ -254,8 +255,10 @@ init_comps(UI *ui) { static int init_comp_img(UI *ui) { const Compressor *comp; + + w_init_image(&ui->comp_img); comp = &ui->comps[ui->comp_select.idx]; - return r_push_icon(comp->imgfile); + return w_set_image(&ui->comp_img, comp->imgfile); } void diff --git a/ui.h b/ui.h index b5c2635..fe3d783 100644 --- a/ui.h +++ b/ui.h @@ -47,6 +47,8 @@ typedef struct { Compressor *comps; int ncomps; w_Select_Compressor comp_select; + + w_Image comp_img; } UI; int init_ui(UI *ui); diff --git a/widget.c b/widget.c index 79e6028..2b0476e 100644 --- a/widget.c +++ b/widget.c @@ -6,15 +6,18 @@ #include #include "microui.h" +#include "renderer.h" #include "unit.h" #include "compressor.h" #include "widget.h" #include "util.h" +#include "eprintf.h" #define FORMAT "%.5g" static const mu_Color RED = {255, 0, 0, 255}; +static const mu_Color WHITE = {255, 255, 255, 255}; static const char *sc_selected_name(w_Select_Compressor *select); static int select_compressor_active(mu_Context *ctx, w_Select_Compressor *select); @@ -280,6 +283,49 @@ w_number(mu_Context *ctx, const w_Number num) { mu_label(ctx, num); } +void +w_init_image(w_Image *img) { + img->id = -1; +} + +void +w_free_image(w_Image *img) { + if (img->id >= 0) { + r_remove_icon(img->id); + img->id = -1; + } +} + +/* Load an image from a file. Returns non-zero on error. */ +int +w_set_image(w_Image *img, const char *path) { + int id; + + /* Remove old image. */ + w_free_image(img); + + /* Load new image. */ + id = r_add_icon(path); + if (id < 0) { + weprintf("failed to load image %s", path); + return 1; + } + img->id = id; + + return 0; +} + +void +w_image(mu_Context *ctx, w_Image *img) { + int id; + mu_Rect r; + + id = mu_get_id(ctx, &img, sizeof(img)); + r = mu_layout_next(ctx); + mu_update_control(ctx, id, r, 0); + mu_draw_icon(ctx, 0, r, WHITE); +} + /* Update the active/selected status of a widget. id is the microui ID of the widget. * *active is the active flag of the widget that will be toggled if anywhere in r is clicked. */ static void diff --git a/widget.h b/widget.h index 1351ba1..ab30f7a 100644 --- a/widget.h +++ b/widget.h @@ -64,3 +64,13 @@ typedef char w_Number[NUMBER_SIZE]; void w_init_number(w_Number num); void w_set_number(w_Number num, double val); void w_number(mu_Context *ctx, const w_Number num); + + +typedef struct { + int id; /* icon id. */ +} w_Image; + +void w_init_image(w_Image *img); +void w_free_image(w_Image *img); +int w_set_image(w_Image *img, const char *path); +void w_image(mu_Context *ctx, w_Image *img); -- cgit v1.2.3