diff options
-rw-r--r-- | colors.h | 9 | ||||
-rw-r--r-- | math.c | 9 | ||||
-rw-r--r-- | ted.cfg | 3 | ||||
-rw-r--r-- | text.c | 20 | ||||
-rw-r--r-- | text.h | 13 | ||||
-rw-r--r-- | ui.c | 29 |
6 files changed, 76 insertions, 7 deletions
@@ -16,6 +16,10 @@ ENUM_U16 { COLOR_ERROR_BG, COLOR_ERROR_BORDER, + COLOR_YES, + COLOR_NO, + COLOR_CANCEL, + COLOR_COUNT } ENUM_U16_END(ColorSetting); @@ -39,7 +43,10 @@ static ColorName const color_names[COLOR_COUNT] = { {COLOR_MENU_HL, "menu-hl"}, {COLOR_ERROR_TEXT, "error-text"}, {COLOR_ERROR_BG, "error-bg"}, - {COLOR_ERROR_BORDER, "error-border"} + {COLOR_ERROR_BORDER, "error-border"}, + {COLOR_YES, "yes"}, + {COLOR_NO, "no"}, + {COLOR_CANCEL, "cancel"} }; static ColorSetting color_setting_from_str(char const *str) { @@ -658,6 +658,10 @@ static bool rect_contains_point(Rect r, v2 point) { return rect_contains_point_v2(r.pos, r.size, point); } +static Rect rect_translate(Rect r, v2 by) { + return rect(v2_add(r.pos, by), r.size); +} + static float rect_x1(Rect r) { return r.pos.x; } static float rect_y1(Rect r) { return r.pos.y; } static float rect_x2(Rect r) { return r.pos.x + r.size.x; } @@ -688,27 +692,22 @@ static void rect_render(Rect r) { static void rect_render_border(Rect r, float border_thickness) { float border_radius = border_thickness * 0.5f; float x1 = r.pos.x, y1 = r.pos.y, x2 = x1 + r.size.x, y2 = y1 + r.size.y; - //float a = 0.3f; // for debugging - //glColor4f(1,0,0,a); glVertex2f(x1+border_radius, y1-border_radius); glVertex2f(x1+border_radius, y1+border_radius); glVertex2f(x2+border_radius, y1+border_radius); glVertex2f(x2+border_radius, y1-border_radius); - //glColor4f(0,1,0,a); glVertex2f(x1-border_radius, y2-border_radius); glVertex2f(x1-border_radius, y2+border_radius); glVertex2f(x2-border_radius, y2+border_radius); glVertex2f(x2-border_radius, y2-border_radius); - //glColor4f(0,0,1,a); glVertex2f(x1-border_radius, y1-border_radius); glVertex2f(x1+border_radius, y1-border_radius); glVertex2f(x1+border_radius, y2-border_radius); glVertex2f(x1-border_radius, y2-border_radius); - //glColor4f(1,1,0,a); glVertex2f(x2-border_radius, y1+border_radius); glVertex2f(x2+border_radius, y1+border_radius); glVertex2f(x2+border_radius, y2+border_radius); @@ -97,3 +97,6 @@ menu-hl = #afa2 error-border = #f00 error-bg = #800 error-text = #fdd +yes = #afa +no = #faa +cancel = #ffa @@ -280,11 +280,29 @@ void text_render(Font *font, char const *text, float x, float y) { text_render_internal(font, text, &x, &y, true); } +void text_render_anchored(Font *font, char const *text, float x, float y, Anchor anchor) { + float w = 0, h = 0; // width, height of text + text_get_size(font, text, &w, &h); + float hw = w * 0.5f, hh = h * 0.5f; // half-width, half-height + switch (anchor) { + case ANCHOR_TOP_LEFT: break; + case ANCHOR_TOP_MIDDLE: x -= hw; break; + case ANCHOR_TOP_RIGHT: x -= w; break; + case ANCHOR_MIDDLE_LEFT: y -= hh; break; + case ANCHOR_MIDDLE: x -= hw; y -= hh; break; + case ANCHOR_MIDDLE_RIGHT: x -= w; y -= hh; break; + case ANCHOR_BOTTOM_LEFT: y -= h; break; + case ANCHOR_BOTTOM_MIDDLE: x -= hw; y -= h; break; + case ANCHOR_BOTTOM_RIGHT: x -= w; y -= h; break; + } + text_render(font, text, x, y); +} + void text_get_size(Font *font, char const *text, float *width, float *height) { float x = 0, y = 0; text_render_internal(font, text, &x, &y, false); if (width) *width = x; - if (height) *height = y + font->char_height * (2/3.0f); + if (height) *height = y + font->char_height; } void text_get_size32(Font *font, char32_t const *text, u64 len, float *width, float *height) { @@ -20,6 +20,18 @@ typedef struct { float min_x, max_x, min_y, max_y; } TextRenderState; +typedef enum { + ANCHOR_TOP_LEFT, + ANCHOR_TOP_MIDDLE, + ANCHOR_TOP_RIGHT, + ANCHOR_MIDDLE_LEFT, + ANCHOR_MIDDLE, + ANCHOR_MIDDLE_RIGHT, + ANCHOR_BOTTOM_LEFT, + ANCHOR_BOTTOM_MIDDLE, + ANCHOR_BOTTOM_RIGHT, +} Anchor; + extern bool text_has_err(void); // Get the current error. Errors will NOT be overwritten with newer errors. extern char const *text_get_err(void); @@ -39,6 +51,7 @@ extern void text_get_size(Font *font, char const *text, float *width, float *hei extern void text_get_size32(Font *font, char32_t const *text, u64 len, float *width, float *height); // Write text, but using a state, starting at (x, y) -- state->x and state->y are ignored. This allows you to control min/max_x/y. extern void text_render_with_state(Font *font, TextRenderState *state, char const *text, float x, float y); +extern void text_render_anchored(Font *font, char const *text, float x, float y, Anchor anchor); // Begin writing characters. extern void text_chars_begin(Font *font); // Finish writing characters. @@ -461,6 +461,24 @@ static void file_selector_render(Ted *ted, FileSelector *fs) { } } +static void button_render(Ted *ted, Rect button, char const *text, u32 color) { + u32 const *colors = ted->settings.colors; + + glBegin(GL_QUADS); + if (rect_contains_point(button, ted->mouse_pos)) { + // highlight button when hovering over it + gl_color_rgba((color & 0xffffff00) | ((color & 0xff) / 3)); + rect_render(button); + } + gl_color_rgba(colors[COLOR_BORDER]); + rect_render_border(button, 1); + glEnd(); + + gl_color_rgba(color); + v2 pos = rect_center(button); + text_render_anchored(ted->font, text, pos.x, pos.y, ANCHOR_MIDDLE); +} + typedef enum { POPUP_NONE, POPUP_YES, @@ -519,4 +537,15 @@ static void popup_render(Ted *ted, char const *title, char const *body) { .min_y = -FLT_MAX, .max_y = +FLT_MAX }; text_render_with_state(font, &state, body, text_x1, y); + + float button_height = 30; + u16 nbuttons = 3; + float button_width = r.size.x / nbuttons; + Rect button_yes = rect(V2(r.pos.x, rect_y2(r) - button_height), V2(button_width, button_height)); + Rect button_no = rect_translate(button_yes, V2(button_width, 0)); + Rect button_cancel = rect_translate(button_no, V2(button_width, 0)); + + button_render(ted, button_yes, "Yes", colors[COLOR_YES]); + button_render(ted, button_no, "No", colors[COLOR_NO]); + button_render(ted, button_cancel, "Cancel", colors[COLOR_CANCEL]); } |