From 23771a9e599700aa9c80139abb122a0f6c97976a Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Fri, 5 Mar 2021 14:38:19 -0500 Subject: fix rendering if border-thickness is big --- README.md | 5 +++-- buffer.c | 20 +++++++++++++++----- find.c | 38 ++++++++++++++++++++++---------------- gl.c | 13 ++++++------- main.c | 1 - math.c | 9 +++++++++ menu.c | 15 ++++++--------- node.c | 16 ++++++++++++++-- ted.c | 7 +++++++ ted.png | Bin 81487 -> 75840 bytes ui.c | 17 ++++++++++------- 11 files changed, 92 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index a3c421e..9b457c5 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A text editor. -**ted is still very new, and there are almost certainly bugs. There are also definitely important features missing. I don't recommend using this as your main text editor yet.** +**ted is still very new, and there are almost certainly bugs. I don't recommend using this as your main text editor yet.** @@ -71,7 +71,8 @@ at any time to generate tags for all files in the current directory. Once you ha to go to its definition. You can also press Ctrl+D to get a searchable list of all functions/types where you can select one to go to its definition. Press Ctrl+space to autocomplete. If there is only one possible completion from the tags file, it will be selected automatically. Otherwise, you'll get a popup showing all possible completions. You can press tab to select a completion (or click on it), and press -Ctrl+space/Ctrl+shift+space to cycle between suggestions. +Ctrl+space/Ctrl+shift+space to cycle between suggestions. Note that autocomplete just completes to stuff in the tags file, so it won't complete local +variable names. Sorry. ## Building from source diff --git a/buffer.c b/buffer.c index 51bdfbe..06f2960 100644 --- a/buffer.c +++ b/buffer.c @@ -1099,6 +1099,8 @@ i64 buffer_cursor_move_right(TextBuffer *buffer, i64 by) { i64 buffer_cursor_move_up(TextBuffer *buffer, i64 by) { BufferPos cur_pos = buffer->cursor_pos; + if (buffer->selection && buffer_pos_cmp(buffer->selection_pos, buffer->cursor_pos) < 0) + cur_pos = buffer->selection_pos; // go to one line above the selection pos (instead of the cursor pos) if it's before the cursor i64 ret = buffer_pos_move_up(buffer, &cur_pos, by); buffer_cursor_move_to_pos(buffer, cur_pos); return ret; @@ -1106,6 +1108,8 @@ i64 buffer_cursor_move_up(TextBuffer *buffer, i64 by) { i64 buffer_cursor_move_down(TextBuffer *buffer, i64 by) { BufferPos cur_pos = buffer->cursor_pos; + if (buffer->selection && buffer_pos_cmp(buffer->selection_pos, buffer->cursor_pos) > 0) + cur_pos = buffer->selection_pos; i64 ret = buffer_pos_move_down(buffer, &cur_pos, by); buffer_cursor_move_to_pos(buffer, cur_pos); return ret; @@ -2226,7 +2230,17 @@ void buffer_render(TextBuffer *buffer, Rect r) { float const border_thickness = settings->border_thickness; u32 start_line = buffer_first_rendered_line(buffer); // line to start rendering from - Rect bounding_box = rect4(x1, y1, x2, y2); + + + u32 border_color = colors[COLOR_BORDER]; // color of border around buffer + // bounding box around buffer + gl_geometry_rect_border(rect4(x1, y1, x2, y2), border_thickness, border_color); + + x1 += border_thickness; + y1 += border_thickness; + x2 -= border_thickness; + y2 -= border_thickness; + float render_start_y = y1 - (float)(buffer->scroll_y - start_line) * char_height; // where the 1st line is rendered @@ -2304,10 +2318,6 @@ void buffer_render(TextBuffer *buffer, Rect r) { gl_geometry_rect(hl_rect, colors[COLOR_CURSOR_LINE_BG]); } - u32 border_color = colors[COLOR_BORDER]; // color of border around buffer - - // bounding box around buffer - gl_geometry_rect_border(bounding_box, border_thickness, border_color); // what x coordinate to start rendering the text from float render_start_x = x1 - (float)buffer->scroll_x * char_width; diff --git a/find.c b/find.c index 1e0b409..2878015 100644 --- a/find.c +++ b/find.c @@ -71,9 +71,11 @@ static float find_menu_height(Ted *ted) { Font *font = ted->font; float char_height = text_font_char_height(font); Settings const *settings = &ted->settings; - float padding = settings->padding; + float const padding = settings->padding; + float const border_thickness = settings->border_thickness; + float const line_buffer_height = ted_line_buffer_height(ted); - return 3 * char_height + (padding + char_height) * ted->replace + 6 * padding; + return 3 * char_height + 4 * border_thickness + (padding + line_buffer_height) * ted->replace + 6 * padding; } // finds the next match in the buffer, returning false if there is no match this line. @@ -311,13 +313,14 @@ static void find_replace_all(Ted *ted) { static void find_menu_frame(Ted *ted, Rect menu_bounds) { Font *font = ted->font, *font_bold = ted->font_bold; - float const char_height = text_font_char_height(font), - char_height_bold = text_font_char_height(font_bold); + float const char_height = text_font_char_height(font); Settings const *settings = &ted->settings; float const padding = settings->padding; + float const border_thickness = settings->border_thickness; u32 const *colors = settings->colors; bool const replace = ted->replace; + float const line_buffer_height = ted_line_buffer_height(ted); TextBuffer *buffer = find_search_buffer(ted), *find_buffer = &ted->find_buffer, *replace_buffer = &ted->replace_buffer; if (!buffer) return; @@ -326,6 +329,10 @@ static void find_menu_frame(Ted *ted, Rect menu_bounds) { u32 last_rendered_line = buffer_last_rendered_line(buffer); + gl_geometry_rect(menu_bounds, colors[COLOR_MENU_BG]); + gl_geometry_rect_border(menu_bounds, border_thickness, colors[COLOR_BORDER]); + menu_bounds = rect_shrink(menu_bounds, border_thickness); + float x1, y1, x2, y2; rect_coords(menu_bounds, &x1, &y1, &x2, &y2); @@ -336,13 +343,13 @@ static void find_menu_frame(Ted *ted, Rect menu_bounds) { char const *prev_text = "Previous", *next_text = "Next"; char const *replace_text = "Replace", *replace_find_text = "Replace+find", *replace_all_text = "Replace all"; - v2 prev_size = text_get_size_v2(font, prev_text); - v2 next_size = text_get_size_v2(font, next_text); - v2 replace_size = text_get_size_v2(font, replace_text); - v2 replace_find_size = text_get_size_v2(font, replace_find_text); - v2 replace_all_size = text_get_size_v2(font, replace_all_text); + v2 prev_size = button_get_size(ted, prev_text); + v2 next_size = button_get_size(ted, next_text); + v2 replace_size = button_get_size(ted, replace_text); + v2 replace_find_size = button_get_size(ted, replace_find_text); + v2 replace_all_size = button_get_size(ted, replace_all_text); - float x = x1, y = y2 - char_height; + float x = x1, y = y2 - prev_size.y; // compute positions of buttons Rect button_prev = rect(V2(x, y), prev_size); x += button_prev.size.x + padding; @@ -355,6 +362,7 @@ static void find_menu_frame(Ted *ted, Rect menu_bounds) { Rect button_replace_all = rect(V2(x, y), replace_all_size); x += button_replace_all.size.x + padding; + if (button_update(ted, button_prev)) find_next_in_direction(ted, -1); if (button_update(ted, button_next)) @@ -387,11 +395,9 @@ static void find_menu_frame(Ted *ted, Rect menu_bounds) { text_get_size(font_bold, replace ? replace_with_text : find_text, &text_width, NULL); - Rect find_buffer_bounds = rect4(x1 + text_width + padding, y1, x2 - padding, y1 + char_height); - Rect replace_buffer_bounds = rect_translate(find_buffer_bounds, V2(0, char_height + padding)); + Rect find_buffer_bounds = rect4(x1 + text_width + padding, y1, x2 - padding, y1 + line_buffer_height); + Rect replace_buffer_bounds = rect_translate(find_buffer_bounds, V2(0, line_buffer_height + padding)); - gl_geometry_rect(menu_bounds, colors[COLOR_MENU_BG]); - gl_geometry_rect_border(menu_bounds, 1, colors[COLOR_BORDER]); button_render(ted, button_prev, prev_text, colors[COLOR_TEXT]); button_render(ted, button_next, next_text, colors[COLOR_TEXT]); @@ -417,11 +423,11 @@ static void find_menu_frame(Ted *ted, Rect menu_bounds) { } text_utf8(font_bold, find_text, x1, y1, colors[COLOR_TEXT]); - y1 += char_height_bold + padding; + y1 += line_buffer_height + padding; if (replace) { text_utf8(font_bold, replace_with_text, x1, y1, colors[COLOR_TEXT]); - y1 += char_height_bold + padding; + y1 += line_buffer_height + padding; } gl_geometry_draw(); diff --git a/gl.c b/gl.c index a30eb59..a7f720f 100644 --- a/gl.c +++ b/gl.c @@ -210,17 +210,16 @@ static void gl_geometry_rect(Rect r, u32 color_rgba) { } static void gl_geometry_rect_border(Rect r, float border_thickness, u32 color) { - 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; // make sure rectangle isn't too small - x2 = maxf(x2, x1 + 2 * border_radius); - y2 = maxf(y2, y1 + 2 * border_radius); + x2 = maxf(x2, x1 + border_thickness); + y2 = maxf(y2, y1 + border_thickness); - gl_geometry_rect(rect4(x1+border_radius, y1-border_radius, x2+border_radius, y1+border_radius), color); - gl_geometry_rect(rect4(x1-border_radius, y2-border_radius, x2-border_radius, y2+border_radius), color); - gl_geometry_rect(rect4(x1-border_radius, y1-border_radius, x1+border_radius, y2-border_radius), color); - gl_geometry_rect(rect4(x2-border_radius, y1+border_radius, x2+border_radius, y2+border_radius), color); + gl_geometry_rect(rect4(x1+border_thickness, y1, x2, y1+border_thickness), color); + gl_geometry_rect(rect4(x1, y2-border_thickness, x2-border_thickness, y2), color); + gl_geometry_rect(rect4(x1, y1, x1+border_thickness, y2), color); + gl_geometry_rect(rect4(x2-border_thickness, y1+border_thickness, x2, y2), color); } static void gl_geometry_draw(void) { diff --git a/main.c b/main.c index 64a79a6..356a2fa 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,4 @@ // @TODO: -// - update screenshot in README // - test windows 7 #include "base.h" diff --git a/math.c b/math.c index 75ec497..42f6cb9 100644 --- a/math.c +++ b/math.c @@ -748,6 +748,15 @@ static Rect rect_shrink(Rect r, float amount) { return r; } +// adds `amount` to all sides of r +static Rect rect_grow(Rect r, float amount) { + r.pos.x -= amount; + r.pos.y -= amount; + r.size.x += 2 * amount; + r.size.y += 2 * amount; + return r; +} + static v4 color_rgba_to_hsva(v4 rgba) { float R = rgba.x, G = rgba.y, B = rgba.z, A = rgba.w; float M = maxf(R, maxf(G, B)); diff --git a/menu.c b/menu.c index 975ce15..aff805a 100644 --- a/menu.c +++ b/menu.c @@ -312,11 +312,12 @@ static void menu_render(Ted *ted) { assert(menu); Settings const *settings = &ted->settings; u32 const *colors = settings->colors; - float window_width = ted->window_width, window_height = ted->window_height; + float const window_width = ted->window_width, window_height = ted->window_height; Font *font_bold = ted->font_bold, *font = ted->font; - float char_height = text_font_char_height(font); - float char_height_bold = text_font_char_height(font_bold); - + float const char_height = text_font_char_height(font); + float const char_height_bold = text_font_char_height(font_bold); + float const line_buffer_height = ted_line_buffer_height(ted); + // render backdrop gl_geometry_rect(rect(V2(0, 0), V2(window_width, window_height)), colors[COLOR_MENU_BACKDROP]); gl_geometry_draw(); @@ -405,8 +406,6 @@ static void menu_render(Ted *ted) { buffer_render(&ted->line_buffer, rect4(x1, y1, x2, y2)); } break; case MENU_COMMAND_SELECTOR: { - float line_buffer_height = char_height; - // argument field char const *text = "Argument"; text_utf8(font_bold, text, x1, y1, colors[COLOR_TEXT]); @@ -421,9 +420,7 @@ static void menu_render(Ted *ted) { text_render(font_bold); } break; - case MENU_SHELL: { - float line_buffer_height = char_height; - + case MENU_SHELL: { bounds.size.y = line_buffer_height + 2 * padding; rect_coords(bounds, &x1, &y1, &x2, &y2); diff --git a/node.c b/node.c index be4e676..5ae0ea7 100644 --- a/node.c +++ b/node.c @@ -193,8 +193,8 @@ static void node_frame(Ted *ted, Node *node, Rect r) { u32 const *colors = settings->colors; Font *font = ted->font; float const border_thickness = settings->border_thickness; - - float tab_bar_height = 20; + float const char_height = text_font_char_height(font); + float tab_bar_height = char_height + 2 * border_thickness; Rect tab_bar_rect = r; tab_bar_rect.size.y = tab_bar_height; @@ -284,6 +284,12 @@ static void node_frame(Ted *ted, Node *node, Rect r) { char const *path = buffer_get_filename(buffer); char const *filename = path ? path_filename(path) : TED_UNTITLED; Rect tab_rect = rect(V2(r.pos.x + tab_width * i, r.pos.y), V2(tab_width, tab_bar_height)); + + if (i > 0) { + // make sure tab borders overlap (i.e. don't double the border thickness between tabs) + tab_rect.pos.x -= border_thickness; + tab_rect.size.x += border_thickness; + } if (node == ted->dragging_tab_node && i == ted->dragging_tab_idx) { // make tab follow mouse @@ -292,6 +298,7 @@ static void node_frame(Ted *ted, Node *node, Rect r) { // tab border gl_geometry_rect_border(tab_rect, border_thickness, colors[COLOR_BORDER]); + tab_rect = rect_shrink(tab_rect, border_thickness); // tab title { @@ -324,6 +331,11 @@ static void node_frame(Ted *ted, Node *node, Rect r) { TextBuffer *buffer = &ted->buffers[buffer_index]; assert(ted->buffers_used[buffer_index]); Rect buffer_rect = rect_translate(r, V2(0, tab_bar_height)); + + // make sure buffer border and tab border overlap + buffer_rect.pos.y -= border_thickness; + buffer_rect.size.y += border_thickness; + buffer_rect.size.y -= tab_bar_height; buffer_render(buffer, buffer_rect); } else { diff --git a/ted.c b/ted.c index cc9eb06..3150458 100644 --- a/ted.c +++ b/ted.c @@ -172,6 +172,13 @@ static i32 ted_new_node(Ted *ted) { } +// how tall is a line buffer? +static float ted_line_buffer_height(Ted const *ted) { + Settings const *settings = &ted->settings; + float const char_height = text_font_char_height(ted->font); + return char_height + 2 * settings->border_thickness; +} + // switch to this node static void ted_node_switch(Ted *ted, Node *node) { assert(node->tabs); diff --git a/ted.png b/ted.png index 1f70e83..3d64d1d 100644 Binary files a/ted.png and b/ted.png differ diff --git a/ui.c b/ui.c index be3b35c..4d825d1 100644 --- a/ui.c +++ b/ui.c @@ -3,12 +3,10 @@ #endif static float selector_entries_start_y(Ted const *ted, Selector const *s) { - Font *font = ted->font; - float char_height = text_font_char_height(font); float padding = ted->settings.padding; return s->bounds.pos.y - + char_height * 1.25f + padding; // make room for line buffer + + ted_line_buffer_height(ted) + padding; // make room for line buffer } // number of entries that can be displayed on the screen @@ -107,7 +105,6 @@ static void selector_render(Ted *ted, Selector *s) { Settings const *settings = &ted->settings; u32 const *colors = settings->colors; Font *font = ted->font; - float char_height = text_font_char_height(font); Rect bounds = s->bounds; @@ -127,7 +124,7 @@ static void selector_render(Ted *ted, Selector *s) { float x1, y1, x2, y2; rect_coords(bounds, &x1, &y1, &x2, &y2); // search buffer - float line_buffer_height = char_height; + float line_buffer_height = ted_line_buffer_height(ted); buffer_render(&ted->line_buffer, rect4(x1, y1, x2, y1 + line_buffer_height)); y1 += line_buffer_height; @@ -514,6 +511,11 @@ static void file_selector_render(Ted *ted, FileSelector *fs) { selector_render(ted, sel); } +static v2 button_get_size(Ted *ted, char const *text) { + float border_thickness = ted->settings.border_thickness; + return v2_add_const(text_get_size_v2(ted->font, text), 2 * border_thickness); +} + static void button_render(Ted *ted, Rect button, char const *text, u32 color) { u32 const *colors = ted->settings.colors; @@ -643,6 +645,7 @@ static v2 checkbox_frame(Ted *ted, bool *value, char const *label, v2 pos) { Settings const *settings = &ted->settings; u32 const *colors = settings->colors; float padding = settings->padding; + float border_thickness = settings->border_thickness; Rect checkbox_rect = rect(pos, V2(checkbox_size, checkbox_size)); @@ -653,9 +656,9 @@ static v2 checkbox_frame(Ted *ted, bool *value, char const *label, v2 pos) { } checkbox_rect.pos = v2_add(checkbox_rect.pos, V2(0.5f, 0.5f)); - gl_geometry_rect_border(checkbox_rect, 1, colors[COLOR_TEXT]); + gl_geometry_rect_border(checkbox_rect, border_thickness, colors[COLOR_TEXT]); if (*value) { - gl_geometry_rect(rect_shrink(checkbox_rect, checkbox_size * 0.2f), colors[COLOR_TEXT]); + gl_geometry_rect(rect_shrink(checkbox_rect, border_thickness + 2), colors[COLOR_TEXT]); } v2 text_pos = v2_add(pos, V2(checkbox_size + padding * 0.5f, 0)); -- cgit v1.2.3