cepheid

An Aurora 4X clone
Log | Files | Refs | README

commit eaf31cc5096be1db264a3066cf213fd18a1d6fb3
parent 071239df07ee045485a73c2b6e9c204893c2c2af
Author: hhvn <dev@hhvn.uk>
Date:   Mon,  5 Sep 2022 13:57:52 +0100

Dropdowns

Diffstat:
Msrc/main.h | 1+
Msrc/pane.c | 4++--
Msrc/struct.h | 34+++++++++++++++++++++++-----------
Msrc/ui.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 84 insertions(+), 13 deletions(-)

diff --git a/src/main.h b/src/main.h @@ -53,6 +53,7 @@ extern Tabs view_tabs; extern void (*view_handlers[UI_VIEW_LAST])(int); extern void (*view_drawers[UI_VIEW_LAST])(void); extern Screen screen; +extern Focus focus; extern View_sys view_sys; void ui_init(void); void ui_update_screen(void); diff --git a/src/pane.c b/src/pane.c @@ -58,8 +58,8 @@ pane_visible(float miny, float maxy) { float pane_max(float y) { - if (pane && y > pane->max) - pane->max = y; + if (pane && y - pane->geom->y > pane->max) + pane->max = y - pane->geom->y; return y; } diff --git a/src/struct.h b/src/struct.h @@ -89,6 +89,17 @@ typedef struct { int w, h; } Rect; +/* pane.c */ +#define PANESCROLL {NULL, 1, 0, 0} +#define PANENOSCROLL {NULL, 0, 0, 0} +typedef struct { + Rect *geom; + int scroll; + int max; + int off; +} Pane; + +/* ui.c again */ typedef struct { Vector2 centre; int r; @@ -141,14 +152,18 @@ typedef struct { typedef struct { char str[INPUT_MAX]; void (*onenter)(char *, int); - int arg; + int arg; /* differentiates buttons with common onenter() */ } Input; #define DROPDOWN_MAX 64 typedef struct { int n; int sel; /* -1 for none */ + char *placeholder; char *val[DROPDOWN_MAX]; + /* internal */ + Rect rect; + Pane pane; } Dropdown; enum UiElements { @@ -157,8 +172,14 @@ enum UiElements { UI_BODY, UI_BUTTON, UI_INPUT, + UI_DROPDOWN, }; +typedef struct { + enum UiElements type; + void *p; +} Focus; + enum UiViews { UI_VIEW_MAIN, UI_VIEW_COLONIES, @@ -177,6 +198,7 @@ typedef struct { void *elem; } Clickable; +/* loading.c */ #define LOAD_STR_MAX 512 typedef struct { char path[64]; @@ -184,13 +206,3 @@ typedef struct { int *step; char *data; } Loader; - -/* pane.c */ -#define PANESCROLL {NULL, 1, 0, 0} -#define PANENOSCROLL {NULL, 0, 0, 0} -typedef struct { - Rect *geom; - int scroll; - int max; - int off; -} Pane; diff --git a/src/ui.c b/src/ui.c @@ -29,6 +29,7 @@ void (*view_drawers[UI_VIEW_LAST])(void) = { }; Screen screen = { 0 }; +Focus focus = { 0 }; Tabs view_tabs = { /* Tactical is the terminology used in Aurora, so I decided to use it @@ -214,6 +215,7 @@ void ui_clickable_handle(Vector2 mouse, MouseButton button, Clickable *clickable) { Tabs *tabs; Checkbox *checkbox; + Dropdown *drop; Rect *rect; /* Circle *circle; */ int ftabw, fw, fn, tabw, x; @@ -253,6 +255,19 @@ ui_clickable_handle(Vector2 mouse, MouseButton button, Clickable *clickable) { checkbox = clickable->elem; checkbox->val = !checkbox->val; break; + case UI_DROPDOWN: + if (button != MOUSE_BUTTON_LEFT) + return; + drop = clickable->elem; + if (focus.p != drop) { + focus.p = drop; + } else { + i = (mouse.y - rect->y) / FONT_SIZE; + if (i != 0 && i <= drop->n) + drop->sel = i - 1; + focus.p = NULL; + } + break; } } @@ -262,6 +277,7 @@ ui_clickable_update(void) { MouseButton button; int i; int ret = 0; + int keepfocus = 0; mouse = GetMousePosition(); /* I wish there was a: int GetMouseButton(void) */ @@ -273,10 +289,16 @@ ui_clickable_update(void) { for (i = 0; i < CLICKABLE_MAX; i++) { if (clickable[i].elem && ui_collides(clickable[i].geom, mouse)) { ui_clickable_handle(mouse, button, &clickable[i]); + if (clickable[i].elem == focus.p) + keepfocus = 1; ret = 1; } } + /* clicking outside the focused elememnt unfocuses */ + if (button != -1 && !keepfocus) + focus.p = NULL; + /* Handle bodies seperately for efficiency: * - body->pxloc can be used instead of a geometry passed to * ui_clickable_register() @@ -464,6 +486,42 @@ ui_draw_checkbox(int x, int y, Checkbox *box) { return rw; } +void +ui_draw_dropdown(int x, int y, int w, Dropdown *d) { + int h = FONT_SIZE; + int fh, ph; + int focused; + int i; + int px = 2, py = 1; + Geom geom = {UI_RECT}; + + focused = focus.p == d; + fh = h + (focused ? h * d->n : 0); + ph = MIN(fh, (screen.h - x) * 0.75); + + ui_draw_border_around(x, y, w, ph, 1); + + d->rect = (Rect){x, y, w, fh + py}; + d->pane.geom = &d->rect; + pane_begin(&d->pane); + + if (d->sel != -1) + ui_print(x + px, y + py, col_fg, "%s", d->val[d->sel]); + else if (d->placeholder) + ui_print(x + px, y + py, col_info, "%s", d->placeholder); + + if (focused) { + ui_draw_rectangle(x, y + h, w, fh - h, col_unselbg); + for (i = 0; i < d->n; i++) { + ui_print(x + px, y + py + (i+1) * h, col_fg, "%s", d->val[i]); + } + } + + geom.rect = (Rect){x, y, w, ph}; + ui_clickable_register(geom, UI_DROPDOWN, d); + pane_end(); +} + Vector2 ui_vectordiff(Vector2 a, Vector2 b) { float x = a.x - b.x;