commit 3f0e6475dd2dd06e821de038bab8ce7d0edd409b
parent cb22e8c5355b5677d096ffc9e089e2b738a4ecb6
Author: hhvn <dev@hhvn.uk>
Date: Sat, 17 Sep 2022 05:19:55 +0100
Move gui elements and handlers to separate file
Diffstat:
6 files changed, 269 insertions(+), 242 deletions(-)
diff --git a/src/main.h b/src/main.h
@@ -63,6 +63,7 @@ extern View_sys view_sys;
extern int charpx;
void ui_init(void);
void ui_update_screen(void);
+void ui_update_focus(enum UiElements type, void *p);
int ui_loop(void);
void ui_deinit(void);
void ui_print(int x, int y, Color col, char *format, ...);
@@ -75,7 +76,6 @@ int ui_onscreen(Vector2 point);
int ui_onscreen_ring(Vector2 centre, float r);
int ui_onscreen_circle(Vector2 centre, float r);
void ui_clickable_register(Geom geom, enum UiElements type, void *elem);
-void ui_clickable_handle(Vector2 mouse, MouseButton button, Clickable *clickable);
int ui_clickable_update(void);
void ui_clickable_clear(void);
void ui_keyboard_handle(void);
@@ -88,11 +88,7 @@ void ui_draw_texture(Texture2D texture, int x, int y);
void ui_draw_circle(int x, int y, float r, Color col);
void ui_draw_line(int sx, int sy, int ex, int ey, float thick, Color col);
void ui_draw_line_v(Vector2 start, Vector2 end, float thick, Color col);
-void ui_draw_tabs(int x, int y, int w, int h, Tabs *tabs);
void ui_draw_tabbed_window(int x, int y, int w, int h, Tabs *tabs);
-int ui_draw_checkbox(int x, int y, Checkbox *checkbox); /* returns width */
-void ui_draw_dropdown(int x, int y, int w, Dropdown *d);
-void ui_draw_input(int x, int y, int w, Input *in);
Vector2 ui_vectordiff(Vector2 a, Vector2 b);
float ui_vectordist(Vector2 a, Vector2 b);
void ui_handle_view_colonies(int nowsel);
@@ -106,6 +102,14 @@ void ui_draw_view_design(void);
void ui_draw_view_sys(void);
void ui_draw_view_settings(void);
+/* uielem.c */
+extern void (*ui_elem_handlers[UI_ELEMS])(Vector2 mouse,
+ MouseButton button, Geom *geom, void *elem);
+void ui_tabs(int x, int y, int w, int h, Tabs *tabs);
+int ui_checkbox(int x, int y, Checkbox *checkbox); /* returns width */
+void ui_dropdown(int x, int y, int w, Dropdown *d);
+void ui_input(int x, int y, int w, Input *in);
+
/* ui/main.c */
extern View_main view_main;
void ui_handle_view_main(int nowsel);
diff --git a/src/struct.h b/src/struct.h
@@ -167,10 +167,10 @@ typedef struct {
enum UiElements {
UI_TAB,
UI_CHECKBOX,
- UI_BODY,
UI_BUTTON,
UI_INPUT,
UI_DROPDOWN,
+ UI_ELEMS,
};
typedef struct {
diff --git a/src/ui.c b/src/ui.c
@@ -204,96 +204,31 @@ ui_clickable_register(Geom geom, enum UiElements type, void *elem) {
/* welp, we ran out */
}
-void
-ui_clickable_handle(Vector2 mouse, MouseButton button, Clickable *clickable) {
- Tabs *tabs;
- Checkbox *checkbox;
- Dropdown *drop;
- Input *input;
- Geom *geom = &clickable->geom;
- int ftabw, fw, fn, tabw, x;
- int i;
-
- switch (clickable->type) {
- case UI_TAB:
- if (button != MOUSE_BUTTON_LEFT)
- return;
- tabs = clickable->elem;
- for (fw = geom->w, fn = i = 0; i < tabs->n; i++) {
- if (!tabs->tabs[i].w)
- fn++;
- else
- fw -= tabs->tabs[i].w;
- }
- ftabw = fw / fn;
- for (i = 0, x = geom->x; i < tabs->n; x += tabw, i++) {
- if (i == tabs->n - 1)
- tabw = geom->x + geom->w - x;
- else if (!tabs->tabs[i].w)
- tabw = ftabw;
- else
- tabw = tabs->tabs[i].w;
- if (mouse.x >= x && mouse.x <= x + tabw) {
- tabs->sel = i;
- return;
- }
- }
- break;
- case UI_CHECKBOX:
- if (button != MOUSE_BUTTON_LEFT)
- return;
- checkbox = clickable->elem;
- checkbox->val = !checkbox->val;
- break;
- case UI_INPUT:
- /* TODO: display hover over text */
- if (button != MOUSE_BUTTON_LEFT)
- return;
- input = clickable->elem;
- if (focus.p != input) {
- ui_update_focus(UI_INPUT, input);
- } else {
- i = (mouse.x - TPX - geom->x + charpx / 2) / charpx;
- if (i < input->len)
- input->cur = i;
- else if (i > 0)
- input->cur = input->len;
- }
- break;
- case UI_DROPDOWN:
- if (button != MOUSE_BUTTON_LEFT)
- return;
- drop = clickable->elem;
- if (focus.p != drop) {
- ui_update_focus(UI_DROPDOWN, drop);
- } else {
- i = (mouse.y - geom->y) / FONT_SIZE;
- if (i != 0 && i <= drop->n)
- drop->sel = i - 1;
- ui_update_focus(0, NULL);
- }
- break;
- }
-}
-
int
ui_clickable_update(void) {
Vector2 mouse;
MouseButton button;
+ Geom *geom;
int i;
int ret = 0;
int keepfocus = 0;
mouse = GetMousePosition();
/* I wish there was a: int GetMouseButton(void) */
- if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) button = MOUSE_BUTTON_LEFT;
- else if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE)) button = MOUSE_BUTTON_MIDDLE;
- else if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) button = MOUSE_BUTTON_RIGHT;
- else button = -1;
+ if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
+ button = MOUSE_BUTTON_LEFT;
+ else if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
+ button = MOUSE_BUTTON_MIDDLE;
+ else if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
+ button = MOUSE_BUTTON_RIGHT;
+ else
+ button = -1;
for (i = 0; i < CLICKABLE_MAX; i++) {
if (clickable[i].elem && ui_collides(clickable[i].geom, mouse)) {
- ui_clickable_handle(mouse, button, &clickable[i]);
+ geom = &clickable[i].geom;
+ ui_elem_handlers[clickable[i].type](mouse,
+ button, geom, clickable[i].elem);
if (clickable[i].elem == focus.p)
keepfocus = 1;
ret = 1;
@@ -375,7 +310,7 @@ void
ui_draw_views(void) {
int sw = GetScreenWidth();
if (sw > VIEWS_MAX_WIDTH) sw = VIEWS_MAX_WIDTH;
- ui_draw_tabs(0, 0, sw, VIEWS_HEIGHT, &view_tabs);
+ ui_tabs(0, 0, sw, VIEWS_HEIGHT, &view_tabs);
}
void
@@ -450,67 +385,6 @@ ui_draw_line_v(Vector2 start, Vector2 end, float thick, Color col) {
}
void
-ui_draw_tabs(int x, int y, int w, int h, Tabs *tabs) {
- int fw, fn, ftabw;
- int tabw;
- int padx, pady;
- int iw;
- int cx, selx = -1;
- int i;
-
- ui_draw_rectangle(x, y, w, h, col_bg);
-
- for (fw = w, fn = i = 0; i < tabs->n; i++) {
- if (!tabs->tabs[i].w)
- fn++;
- else
- fw -= tabs->tabs[i].w;
- }
-
- ftabw = fw / fn;
- pady = (h - FONT_SIZE) / 2;
-
- for (i = 0, cx = x; i < tabs->n; i++, cx += tabw) {
- if (i == tabs->n - 1)
- tabw = x + w - cx;
- else if (!tabs->tabs[i].w)
- tabw = ftabw;
- else
- tabw = tabs->tabs[i].w;
-
- if (tabs->tabs[i].icon)
- iw = tabs->tabs[i].icon->width;
- else
- iw = 0;
-
- padx = (tabw - ui_textsize(tabs->tabs[i].name) - iw) / 2;
- if (i == tabs->sel)
- selx = cx;
- else
- ui_draw_rectangle(cx, y, tabw, h, col_unselbg);
- ui_print(cx + padx + iw, y + pady, col_fg, "%s", tabs->tabs[i].name);
- if (tabs->tabs[i].icon)
- ui_draw_texture(*tabs->tabs[i].icon, cx + padx / 2,
- y + (h - tabs->tabs[i].icon->width) / 2);
- ui_draw_rectangle(cx + tabw - 1, y, 1, h, col_border);
- }
-
- if (tabs->sel != tabs->n - 1) {
- if (!tabs->tabs[i].w)
- tabw = ftabw;
- else
- tabw = w / tabs->n;
- }
-
- ui_draw_border(x, y, w, h, 1);
- if (selx != -1) ui_draw_rectangle(selx - 1, y + h - 1, tabw + 1, 1, col_bg); /* undraw bottom border */
- if (tabs->sel == 0) ui_draw_rectangle(x, y + 1, 1, h - 1, col_bg); /* undraw left border */
- if (tabs->sel == tabs->n - 1) ui_draw_rectangle(x + w - 1, y + 1, 1, h - 1, col_bg); /* undraw right border */
-
- ui_clickable_register(RECT(x, y, w, h), UI_TAB, tabs);
-}
-
-void
ui_draw_border(int x, int y, int w, int h, int px) {
if (!pane_visible(y, y + h))
return;
@@ -522,83 +396,6 @@ ui_draw_border_around(int x, int y, int w, int h, int px) {
ui_draw_border(x - px, y - px, w + px * 2, h + px * 2, px);
}
-int
-ui_draw_checkbox(int x, int y, Checkbox *box) {
- int w, h;
- int rw;
-
- w = h = FONT_SIZE;
- ui_draw_border(x, y, w, h, 1);
- ui_draw_rectangle(x + 1, y + 1, w - 2, h - 2,
- box->enabled ? (box->val ? col_fg : col_bg) : col_border);
- ui_print(x + w + (w / 2), y + (h / 6), col_fg, "%s", box->label);
- rw = w + (w / 2) + ui_textsize(box->label);
- if (box->enabled)
- ui_clickable_register(RECT(x, y, rw, h),
- UI_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;
-
- 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 + TPY);
- d->pane.geom = &d->rect;
- pane_begin(&d->pane);
-
- if (d->sel != -1)
- ui_print(x + TPX, y + TPY, col_fg, "%s", d->val[d->sel]);
- else if (d->placeholder)
- ui_print(x + TPX, y + TPY, 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 + TPX, y + TPY + (i+1) * h, col_fg, "%s", d->val[i]);
- }
- }
-
- ui_clickable_register(d->rect, UI_DROPDOWN, d);
- pane_end();
-}
-
-void
-ui_draw_input(int x, int y, int w, Input *in) {
- int h = FONT_SIZE;
- int focused = focus.p == in;
- int cw;
-
- /* Dirty hack: truncate str to length that fits */
- cw = w / charpx - 1;
- if (in->len > cw) {
- in->len = cw;
- in->wstr[cw] = '\0';
- }
- if (in->cur > in->len)
- in->cur = in->len;
-
- ui_draw_border_around(x, y, w, h, 1);
- ui_draw_rectangle(x, y, w, h, focused ? col_bg : col_unselbg);
- if (in->len)
- ui_print(x + TPX, y + TPY, col_fg, "%S", in->wstr);
- else if (!focused && in->placeholder)
- ui_print(x + TPX, y + TPY, col_info, "%s", in->placeholder);
- if (focused) {
- ui_draw_rectangle(x + TPX + charpx * in->cur, y + TPY, 1, FONT_SIZE, col_fg);
- }
- ui_clickable_register(RECT(x, y, w, h), UI_INPUT, in);
-}
-
Vector2
ui_vectordiff(Vector2 a, Vector2 b) {
float x = a.x - b.x;
@@ -619,7 +416,7 @@ ui_vectordist(Vector2 a, Vector2 b) {
void
ui_draw_tabbed_window(int x, int y, int w, int h, Tabs *tabs) {
ui_draw_rectangle(x, y, w, h, col_bg);
- ui_draw_tabs(x, y, w, WINDOW_TAB_HEIGHT, tabs);
+ ui_tabs(x, y, w, WINDOW_TAB_HEIGHT, tabs);
ui_draw_border(x, y, w, h, WINDOW_BORDER);
}
diff --git a/src/ui/bodies.c b/src/ui/bodies.c
@@ -130,12 +130,12 @@ ui_draw_view_bodies(void) {
x = v->disp.x + PAD/2;
y = v->disp.y + PAD/2;
- x += ui_draw_checkbox(x, y, &v->show.planet) + PAD * 2;
- x += ui_draw_checkbox(x, y, &v->show.moon) + PAD * 2;
- x += ui_draw_checkbox(x, y, &v->show.dwarf) + PAD * 2;
- x += ui_draw_checkbox(x, y, &v->show.asteroid) + PAD * 2;
- x += ui_draw_checkbox(x, y, &v->show.comet) + PAD * 2;
- x += ui_draw_checkbox(x, y, &v->show.nomineral);
+ x += ui_checkbox(x, y, &v->show.planet) + PAD * 2;
+ x += ui_checkbox(x, y, &v->show.moon) + PAD * 2;
+ x += ui_checkbox(x, y, &v->show.dwarf) + PAD * 2;
+ x += ui_checkbox(x, y, &v->show.asteroid) + PAD * 2;
+ x += ui_checkbox(x, y, &v->show.comet) + PAD * 2;
+ x += ui_checkbox(x, y, &v->show.nomineral);
ui_draw_border_around(v->disp.x, v->disp.y, x, v->disp.h, 1);
ui_draw_border_around(EXPLODE_RECT(v->bodies), 1);
diff --git a/src/ui/main.c b/src/ui/main.c
@@ -51,8 +51,6 @@ View_main view_main = {
.sys = NULL,
};
-Input test = { 0 };
-
Vector2
kmtopx(Vector2 km) {
return (Vector2) {
@@ -282,16 +280,14 @@ ui_draw_view_main(void) {
view_main.infobox.pane.geom = &geom;
pane_begin(&view_main.infobox.pane);
- ui_draw_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.names.dwarf);
- ui_draw_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.names.dwarfn);
- ui_draw_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.names.asteroid);
- ui_draw_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.names.asteroidn);
- ui_draw_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.names.comet);
- ui_draw_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.orbit.dwarf);
- ui_draw_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.orbit.asteroid);
- ui_draw_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.orbit.comet);
- ui_draw_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.comettail);
+ ui_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.names.dwarf);
+ ui_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.names.dwarfn);
+ ui_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.names.asteroid);
+ ui_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.names.asteroidn);
+ ui_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.names.comet);
+ ui_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.orbit.dwarf);
+ ui_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.orbit.asteroid);
+ ui_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.orbit.comet);
+ ui_checkbox(x, y += FONT_SIZE*1.5, &view_main.infobox.comettail);
pane_end();
-
- ui_draw_input(500, 500, 150, &test);
}
diff --git a/src/uielem.c b/src/uielem.c
@@ -0,0 +1,230 @@
+#include "main.h"
+
+static void ui_handle_tabs(Vector2 mouse,
+ MouseButton button, Geom *geom, void *elem);
+static void ui_handle_checkbox(Vector2 mouse,
+ MouseButton button, Geom *geom, void *elem);
+static void ui_handle_dropdown(Vector2 mouse,
+ MouseButton button, Geom *geom, void *elem);
+static void ui_handle_input(Vector2 mouse,
+ MouseButton button, Geom *geom, void *elem);
+
+void (*ui_elem_handlers[UI_ELEMS])(Vector2 mouse,
+ MouseButton button,
+ Geom *geom, void *elem) = {
+ [UI_TAB] = ui_handle_tabs,
+ [UI_CHECKBOX] = ui_handle_checkbox,
+ [UI_DROPDOWN] = ui_handle_dropdown,
+ [UI_INPUT] = ui_handle_input,
+};
+
+void
+ui_tabs(int x, int y, int w, int h, Tabs *tabs) {
+ int fw, fn, ftabw;
+ int tabw;
+ int padx, pady;
+ int iw;
+ int cx, selx = -1;
+ int i;
+
+ ui_draw_rectangle(x, y, w, h, col_bg);
+
+ for (fw = w, fn = i = 0; i < tabs->n; i++) {
+ if (!tabs->tabs[i].w)
+ fn++;
+ else
+ fw -= tabs->tabs[i].w;
+ }
+
+ ftabw = fw / fn;
+ pady = (h - FONT_SIZE) / 2;
+
+ for (i = 0, cx = x; i < tabs->n; i++, cx += tabw) {
+ if (i == tabs->n - 1)
+ tabw = x + w - cx;
+ else if (!tabs->tabs[i].w)
+ tabw = ftabw;
+ else
+ tabw = tabs->tabs[i].w;
+
+ if (tabs->tabs[i].icon)
+ iw = tabs->tabs[i].icon->width;
+ else
+ iw = 0;
+
+ padx = (tabw - ui_textsize(tabs->tabs[i].name) - iw) / 2;
+ if (i == tabs->sel)
+ selx = cx;
+ else
+ ui_draw_rectangle(cx, y, tabw, h, col_unselbg);
+ ui_print(cx + padx + iw, y + pady, col_fg, "%s", tabs->tabs[i].name);
+ if (tabs->tabs[i].icon)
+ ui_draw_texture(*tabs->tabs[i].icon, cx + padx / 2,
+ y + (h - tabs->tabs[i].icon->width) / 2);
+ ui_draw_rectangle(cx + tabw - 1, y, 1, h, col_border);
+ }
+
+ if (tabs->sel != tabs->n - 1) {
+ if (!tabs->tabs[i].w)
+ tabw = ftabw;
+ else
+ tabw = w / tabs->n;
+ }
+
+ ui_draw_border(x, y, w, h, 1);
+ if (selx != -1) ui_draw_rectangle(selx - 1, y + h - 1, tabw + 1, 1, col_bg); /* undraw bottom border */
+ if (tabs->sel == 0) ui_draw_rectangle(x, y + 1, 1, h - 1, col_bg); /* undraw left border */
+ if (tabs->sel == tabs->n - 1) ui_draw_rectangle(x + w - 1, y + 1, 1, h - 1, col_bg); /* undraw right border */
+
+ ui_clickable_register(RECT(x, y, w, h), UI_TAB, tabs);
+}
+
+static void
+ui_handle_tabs(Vector2 mouse, MouseButton button, Geom *geom, void *elem) {
+ int ftabw, fw, fn;
+ int tabw, x, i;
+ Tabs *tabs = elem;
+
+ if (button != MOUSE_BUTTON_LEFT)
+ return;
+ for (fw = geom->w, fn = i = 0; i < tabs->n; i++) {
+ if (!tabs->tabs[i].w)
+ fn++;
+ else
+ fw -= tabs->tabs[i].w;
+ }
+ ftabw = fw / fn;
+ for (i = 0, x = geom->x; i < tabs->n; x += tabw, i++) {
+ if (i == tabs->n - 1)
+ tabw = geom->x + geom->w - x;
+ else if (!tabs->tabs[i].w)
+ tabw = ftabw;
+ else
+ tabw = tabs->tabs[i].w;
+ if (mouse.x >= x && mouse.x <= x + tabw) {
+ tabs->sel = i;
+ return;
+ }
+ }
+}
+
+int
+ui_checkbox(int x, int y, Checkbox *box) {
+ int w, h;
+ int rw;
+
+ w = h = FONT_SIZE;
+ ui_draw_border(x, y, w, h, 1);
+ ui_draw_rectangle(x + 1, y + 1, w - 2, h - 2,
+ box->enabled ? (box->val ? col_fg : col_bg) : col_border);
+ ui_print(x + w + (w / 2), y + (h / 6), col_fg, "%s", box->label);
+ rw = w + (w / 2) + ui_textsize(box->label);
+ if (box->enabled)
+ ui_clickable_register(RECT(x, y, rw, h),
+ UI_CHECKBOX, box);
+ return rw;
+}
+
+static void
+ui_handle_checkbox(Vector2 mouse, MouseButton button, Geom *geom, void *elem) {
+ Checkbox *checkbox = elem;
+
+ if (button != MOUSE_BUTTON_LEFT)
+ return;
+ checkbox->val = !checkbox->val;
+}
+
+void
+ui_dropdown(int x, int y, int w, Dropdown *d) {
+ int h = FONT_SIZE;
+ int fh, ph;
+ int focused;
+ int i;
+
+ 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 + TPY);
+ d->pane.geom = &d->rect;
+ pane_begin(&d->pane);
+
+ if (d->sel != -1)
+ ui_print(x + TPX, y + TPY, col_fg, "%s", d->val[d->sel]);
+ else if (d->placeholder)
+ ui_print(x + TPX, y + TPY, 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 + TPX, y + TPY + (i+1) * h, col_fg, "%s", d->val[i]);
+ }
+ }
+
+ ui_clickable_register(d->rect, UI_DROPDOWN, d);
+ pane_end();
+}
+
+static void
+ui_handle_dropdown(Vector2 mouse, MouseButton button, Geom *geom, void *elem) {
+ Dropdown *drop = elem;
+ int i;
+
+ if (button != MOUSE_BUTTON_LEFT)
+ return;
+ if (focus.p != drop) {
+ ui_update_focus(UI_DROPDOWN, drop);
+ } else {
+ i = (mouse.y - geom->y) / FONT_SIZE;
+ if (i != 0 && i <= drop->n)
+ drop->sel = i - 1;
+ ui_update_focus(0, NULL);
+ }
+}
+
+void
+ui_input(int x, int y, int w, Input *in) {
+ int h = FONT_SIZE;
+ int focused = focus.p == in;
+ int cw;
+
+ /* Dirty hack: truncate str to length that fits */
+ cw = w / charpx - 1;
+ if (in->len > cw) {
+ in->len = cw;
+ in->wstr[cw] = '\0';
+ }
+ if (in->cur > in->len)
+ in->cur = in->len;
+
+ ui_draw_border_around(x, y, w, h, 1);
+ ui_draw_rectangle(x, y, w, h, focused ? col_bg : col_unselbg);
+ if (in->len)
+ ui_print(x + TPX, y + TPY, col_fg, "%S", in->wstr);
+ else if (!focused && in->placeholder)
+ ui_print(x + TPX, y + TPY, col_info, "%s", in->placeholder);
+ if (focused) {
+ ui_draw_rectangle(x + TPX + charpx * in->cur, y + TPY, 1, FONT_SIZE, col_fg);
+ }
+ ui_clickable_register(RECT(x, y, w, h), UI_INPUT, in);
+}
+
+static void
+ui_handle_input(Vector2 mouse, MouseButton button, Geom *geom, void *elem) {
+ Input *input = elem;
+ int i;
+
+ if (button != MOUSE_BUTTON_LEFT)
+ return;
+ if (focus.p != input) {
+ ui_update_focus(UI_INPUT, input);
+ } else {
+ i = (mouse.x - TPX - geom->x + charpx / 2) / charpx;
+ if (i < input->len)
+ input->cur = i;
+ else if (i > 0)
+ input->cur = input->len;
+ }
+}