From e7f53d2c077735971ba7b6bc7f7b84f164112408 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Thu, 4 Jul 2024 07:20:45 +0200 Subject: [PATCH] Line highlights --- src/text_editor/layout.cpp | 10 +++- src/text_editor/main.cpp | 87 +++++++++++++++++++++--------- src/text_editor/rect2.cpp | 107 ++++++++++++++++++++----------------- 3 files changed, 126 insertions(+), 78 deletions(-) diff --git a/src/text_editor/layout.cpp b/src/text_editor/layout.cpp index aebf940..47caa04 100644 --- a/src/text_editor/layout.cpp +++ b/src/text_editor/layout.cpp @@ -28,6 +28,11 @@ struct History { int debug_edit_phase; }; +struct ColoredString { + Range range; + Color color; +}; + struct Window { Font font; float font_size; @@ -46,8 +51,9 @@ struct Window { Buffer buffer; History history; - Arena layout_arena; - Layout layout; + Array colored_strings; + Arena layout_arena; + Layout layout; }; template diff --git a/src/text_editor/main.cpp b/src/text_editor/main.cpp index c8e7b94..eb72790 100644 --- a/src/text_editor/main.cpp +++ b/src/text_editor/main.cpp @@ -5,9 +5,11 @@ // @todo: highlight all occurences of selected word // @todo: systematic way of coloring words -// @todo: line wrapping +// @todo: search for word // @todo: context menu // @todo: toy around with acme ideas +// @todo: undo tree +// @todo: resize font, reload font // @todo: add clipboard history? #include "rect2.cpp" #include "buffer.cpp" @@ -85,6 +87,7 @@ int main() { window.font = font; window.font_size = font_size; window.font_spacing; + window.colored_strings.allocator = FrameArena; InitArena(&window.layout_arena); InitBuffer(GetSystemAllocator(), &window.buffer); @@ -294,6 +297,18 @@ int main() { it.range.min = it.range.max = line.max_without_new_line; } } + + if (IsKeyPressed(KEY_PAGE_UP) || IsKeyPressedRepeat(KEY_PAGE_UP)) { + if (IsKeyDown(KEY_LEFT_SHIFT)) { + } else { + } + } + + if (IsKeyPressed(KEY_PAGE_DOWN) || IsKeyPressedRepeat(KEY_PAGE_DOWN)) { + if (IsKeyDown(KEY_LEFT_SHIFT)) { + } else { + } + } } if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C)) { @@ -411,6 +426,16 @@ int main() { ApplyEdits(focused_window, edits); AfterEdit(focused_window, edits); } + + { + int64_t index = 0; + String buffer_string = GetString(focused_window->buffer); + if (Seek(buffer_string, "number", &index)) { + Range range = {index, index + 6}; + focused_window->colored_strings.add({range, RED}); + } + } + EventRecording_SimulateGetCharPressed(focused_window); } @@ -427,7 +452,9 @@ int main() { // Draw and layout window overlay Vec2 mouse = GetMousePosition(); { + // @todo: why are we drawing this here?? DrawRectangleRec(ToRectangle(window.rect), WHITE); + DrawRectangleRec(ToRectangle(line_number_rect), WHITE); Vec2 size = GetSize(window.rect); Vec2 min = window.scroll / (window.layout.buffer_world_pixel_size + size); @@ -613,34 +640,34 @@ int main() { Vec2 window_rect_size = GetSize(window.rect); BeginScissorMode((int)window.rect.min.x, (int)window.rect.min.y, (int)window_rect_size.x, (int)window_rect_size.y); - Range visible_line_range = CalculateVisibleLineRange(window); - for (int64_t line = visible_line_range.min; line < visible_line_range.max; line += 1) { - LayoutRow &row = window.layout.rows[line]; + Array visible_columns = CalculateVisibleColumns(&FrameArena, window); + Range visible_line_range = CalculateVisibleLineRange(window); - ForItem(col, row.columns) { - Rect2 rect = {col.rect.min + window.rect.min - window.scroll, col.rect.max + window.rect.min - window.scroll}; - - if (!CheckCollisionRecs(ToRectangle(rect), ToRectangle(window.rect))) { - continue; // Clip everything that is outside the window and screen - } - - if (col.codepoint == '\n') { - DrawTextEx(font, "\\n", rect.min, font_size, font_spacing, GRAY); - } else if (col.codepoint == '\0') { - DrawTextEx(font, "\\0", rect.min, font_size, font_spacing, {255, 0, 0, 150}); - } else if ((col.codepoint != ' ') && (col.codepoint != '\t')) { - DrawTextCodepoint(font, col.codepoint, rect.min, font_size, BLACK); - } + ForItem(col, visible_columns) { + Rect2 rect = {col.rect.min + window.rect.min - window.scroll, col.rect.max + window.rect.min - window.scroll}; + if (col.codepoint == '\n') { + DrawTextEx(font, "\\n", rect.min, font_size, font_spacing, GRAY); + } else if (col.codepoint == '\0') { + DrawTextEx(font, "\\0", rect.min, font_size, font_spacing, {255, 0, 0, 150}); + } else if ((col.codepoint != ' ') && (col.codepoint != '\t')) { + DrawTextCodepoint(font, col.codepoint, rect.min, font_size, BLACK); } } - Array visible_columns = CalculateVisibleColumns(&FrameArena, window); - // Draw cursor stuff + Array lines_to_highlight = {FrameArena}; ForItem(cursor, window.cursors) { - auto front = GetRowCol(window, GetFront(cursor)); - auto back = GetRowCol(window, GetBack(cursor)); + Tuple front = GetRowCol(window, GetFront(cursor)); + Tuple back = GetRowCol(window, GetBack(cursor)); + // Line highlight + lines_to_highlight.add(front.a); + if (GetRangeSize(cursor.range) == 0) { + Rect2 rect = front.a->rect + window.rect.min - window.scroll; + DrawRectangleRec(ToRectangle(rect), {0, 0, 0, 30}); + } + + // Selection For(visible_columns) { if (it.pos >= cursor.range.min && it.pos < cursor.range.max) { Rect2 rect = it.rect + window.rect.min - window.scroll; @@ -648,6 +675,7 @@ int main() { } } + // Cursor blocks if (front.b) { Rect2 rect = front.b->rect + window.rect.min - window.scroll; rect = CutLeft(&rect, 4); @@ -664,12 +692,19 @@ int main() { // Draw line numbers { - Rect2 rect = line_number_rect; - BeginScissorMode((int)rect.min.x, (int)rect.min.y, (int)(rect.max.x - rect.min.x), (int)(rect.max.y - rect.min.y)); + BeginScissorMode((int)line_number_rect.min.x, (int)line_number_rect.min.y, (int)(line_number_rect.max.x - line_number_rect.min.x), (int)(line_number_rect.max.y - line_number_rect.min.y)); for (int64_t line = visible_line_range.min; line < visible_line_range.max; line += 1) { LayoutRow &row = window.layout.rows[line]; - - Vec2 pos = {rect.min.x, row.rect.min.y + rect.min.y - window.scroll.y}; + Vec2 pos = {line_number_rect.min.x, row.rect.min.y + line_number_rect.min.y - window.scroll.y}; + For(lines_to_highlight) { + if (it == &row) { + Rect2 r = {pos, pos}; + r.max.x = line_number_rect.max.x; + r.max.y += GetSize(row.rect).y; + DrawRectangleRec(ToRectangle(r), {0, 0, 0, 30}); + break; + } + } String line_num_string = Format(FrameArena, "%lld", (long long)line); DrawTextEx(font, line_num_string.data, pos, font_size, font_spacing, LIGHTGRAY); diff --git a/src/text_editor/rect2.cpp b/src/text_editor/rect2.cpp index 4e18233..b21f828 100644 --- a/src/text_editor/rect2.cpp +++ b/src/text_editor/rect2.cpp @@ -14,6 +14,63 @@ Rectangle ToRectangle(Rect2 r) { return result; } +// clang-format off +Rect2 operator-(Rect2 r, Rect2 value) { return { r.min.x - value.min.x, r.min.y - value.min.y, r.max.x - value.max.x, r.max.y - value.max.y }; } +Rect2 operator+(Rect2 r, Rect2 value) { return { r.min.x + value.min.x, r.min.y + value.min.y, r.max.x + value.max.x, r.max.y + value.max.y }; } +Rect2 operator*(Rect2 r, Rect2 value) { return { r.min.x * value.min.x, r.min.y * value.min.y, r.max.x * value.max.x, r.max.y * value.max.y }; } +Rect2 operator/(Rect2 r, Rect2 value) { return { r.min.x / value.min.x, r.min.y / value.min.y, r.max.x / value.max.x, r.max.y / value.max.y }; } + +Rect2 operator-(Rect2 r, Vec2 value) { return { r.min.x - value.x, r.min.y - value.y, r.max.x - value.x, r.max.y - value.y }; } +Rect2 operator+(Rect2 r, Vec2 value) { return { r.min.x + value.x, r.min.y + value.y, r.max.x + value.x, r.max.y + value.y }; } +Rect2 operator*(Rect2 r, Vec2 value) { return { r.min.x * value.x, r.min.y * value.y, r.max.x * value.x, r.max.y * value.y }; } +Rect2 operator/(Rect2 r, Vec2 value) { return { r.min.x / value.x, r.min.y / value.y, r.max.x / value.x, r.max.y / value.y }; } + +Rect2 operator-(Rect2 r, float value) { return { r.min.x - value, r.min.y - value, r.max.x - value, r.max.y - value }; } +Rect2 operator+(Rect2 r, float value) { return { r.min.x + value, r.min.y + value, r.max.x + value, r.max.y + value }; } +Rect2 operator*(Rect2 r, float value) { return { r.min.x * value, r.min.y * value, r.max.x * value, r.max.y * value }; } +Rect2 operator/(Rect2 r, float value) { return { r.min.x / value, r.min.y / value, r.max.x / value, r.max.y / value }; } + +Rect2 operator-=(Rect2 &r, Rect2 value) { r = r - value; return r; } +Rect2 operator+=(Rect2 &r, Rect2 value) { r = r + value; return r; } +Rect2 operator*=(Rect2 &r, Rect2 value) { r = r * value; return r; } +Rect2 operator/=(Rect2 &r, Rect2 value) { r = r / value; return r; } +Rect2 operator-=(Rect2 &r, Vec2 value) { r = r - value; return r; } +Rect2 operator+=(Rect2 &r, Vec2 value) { r = r + value; return r; } +Rect2 operator*=(Rect2 &r, Vec2 value) { r = r * value; return r; } +Rect2 operator/=(Rect2 &r, Vec2 value) { r = r / value; return r; } +Rect2 operator-=(Rect2 &r, float value) { r = r - value; return r; } +Rect2 operator+=(Rect2 &r, float value) { r = r + value; return r; } +Rect2 operator*=(Rect2 &r, float value) { r = r * value; return r; } +Rect2 operator/=(Rect2 &r, float value) { r = r / value; return r; } + +Vec2 operator-(Vec2 a, Vec2 b) { return {a.x - b.x, a.y - b.y}; } +Vec2 operator+(Vec2 a, Vec2 b) { return {a.x + b.x, a.y + b.y}; } +Vec2 operator*(Vec2 a, Vec2 b) { return {a.x * b.x, a.y * b.y}; } +Vec2 operator/(Vec2 a, Vec2 b) { return {a.x / b.x, a.y / b.y}; } + +Vec2 operator-(Vec2 a, float b) { return {a.x - b, a.y - b}; } +Vec2 operator+(Vec2 a, float b) { return {a.x + b, a.y + b}; } +Vec2 operator*(Vec2 a, float b) { return {a.x * b, a.y * b}; } +Vec2 operator/(Vec2 a, float b) { return {a.x / b, a.y / b}; } + +Vec2 operator-=(Vec2 &a, Vec2 b) { a = a - b; return a; } +Vec2 operator+=(Vec2 &a, Vec2 b) { a = a + b; return a; } +Vec2 operator*=(Vec2 &a, Vec2 b) { a = a * b; return a; } +Vec2 operator/=(Vec2 &a, Vec2 b) { a = a / b; return a; } +Vec2 operator-=(Vec2 &a, float b) { a = a - b; return a; } +Vec2 operator+=(Vec2 &a, float b) { a = a + b; return a; } +Vec2 operator*=(Vec2 &a, float b) { a = a * b; return a; } +Vec2 operator/=(Vec2 &a, float b) { a = a / b; return a; } + +// clang-format on + +Rect2 Rect2FromSize(Vec2 pos, Vec2 size) { + Rect2 result = {}; + result.min = pos; + result.max = pos + size; + return result; +} + Rect2 Shrink(Rect2 result, float v) { result.min.x += v; result.max.x -= v; @@ -71,53 +128,3 @@ Rect2 CutTop(Rect2 *r, float value) { }; return result; } - -// clang-format off -Rect2 operator-(Rect2 r, Rect2 value) { return { r.min.x - value.min.x, r.min.y - value.min.y, r.max.x - value.max.x, r.max.y - value.max.y }; } -Rect2 operator+(Rect2 r, Rect2 value) { return { r.min.x + value.min.x, r.min.y + value.min.y, r.max.x + value.max.x, r.max.y + value.max.y }; } -Rect2 operator*(Rect2 r, Rect2 value) { return { r.min.x * value.min.x, r.min.y * value.min.y, r.max.x * value.max.x, r.max.y * value.max.y }; } -Rect2 operator/(Rect2 r, Rect2 value) { return { r.min.x / value.min.x, r.min.y / value.min.y, r.max.x / value.max.x, r.max.y / value.max.y }; } - -Rect2 operator-(Rect2 r, Vec2 value) { return { r.min.x - value.x, r.min.y - value.y, r.max.x - value.x, r.max.y - value.y }; } -Rect2 operator+(Rect2 r, Vec2 value) { return { r.min.x + value.x, r.min.y + value.y, r.max.x + value.x, r.max.y + value.y }; } -Rect2 operator*(Rect2 r, Vec2 value) { return { r.min.x * value.x, r.min.y * value.y, r.max.x * value.x, r.max.y * value.y }; } -Rect2 operator/(Rect2 r, Vec2 value) { return { r.min.x / value.x, r.min.y / value.y, r.max.x / value.x, r.max.y / value.y }; } - -Rect2 operator-(Rect2 r, float value) { return { r.min.x - value, r.min.y - value, r.max.x - value, r.max.y - value }; } -Rect2 operator+(Rect2 r, float value) { return { r.min.x + value, r.min.y + value, r.max.x + value, r.max.y + value }; } -Rect2 operator*(Rect2 r, float value) { return { r.min.x * value, r.min.y * value, r.max.x * value, r.max.y * value }; } -Rect2 operator/(Rect2 r, float value) { return { r.min.x / value, r.min.y / value, r.max.x / value, r.max.y / value }; } - -Rect2 operator-=(Rect2 &r, Rect2 value) { r = r - value; return r; } -Rect2 operator+=(Rect2 &r, Rect2 value) { r = r + value; return r; } -Rect2 operator*=(Rect2 &r, Rect2 value) { r = r * value; return r; } -Rect2 operator/=(Rect2 &r, Rect2 value) { r = r / value; return r; } -Rect2 operator-=(Rect2 &r, Vec2 value) { r = r - value; return r; } -Rect2 operator+=(Rect2 &r, Vec2 value) { r = r + value; return r; } -Rect2 operator*=(Rect2 &r, Vec2 value) { r = r * value; return r; } -Rect2 operator/=(Rect2 &r, Vec2 value) { r = r / value; return r; } -Rect2 operator-=(Rect2 &r, float value) { r = r - value; return r; } -Rect2 operator+=(Rect2 &r, float value) { r = r + value; return r; } -Rect2 operator*=(Rect2 &r, float value) { r = r * value; return r; } -Rect2 operator/=(Rect2 &r, float value) { r = r / value; return r; } - -Vec2 operator-(Vec2 a, Vec2 b) { return {a.x - b.x, a.y - b.y}; } -Vec2 operator+(Vec2 a, Vec2 b) { return {a.x + b.x, a.y + b.y}; } -Vec2 operator*(Vec2 a, Vec2 b) { return {a.x * b.x, a.y * b.y}; } -Vec2 operator/(Vec2 a, Vec2 b) { return {a.x / b.x, a.y / b.y}; } - -Vec2 operator-(Vec2 a, float b) { return {a.x - b, a.y - b}; } -Vec2 operator+(Vec2 a, float b) { return {a.x + b, a.y + b}; } -Vec2 operator*(Vec2 a, float b) { return {a.x * b, a.y * b}; } -Vec2 operator/(Vec2 a, float b) { return {a.x / b, a.y / b}; } - -Vec2 operator-=(Vec2 &a, Vec2 b) { a = a - b; return a; } -Vec2 operator+=(Vec2 &a, Vec2 b) { a = a + b; return a; } -Vec2 operator*=(Vec2 &a, Vec2 b) { a = a * b; return a; } -Vec2 operator/=(Vec2 &a, Vec2 b) { a = a / b; return a; } -Vec2 operator-=(Vec2 &a, float b) { a = a - b; return a; } -Vec2 operator+=(Vec2 &a, float b) { a = a + b; return a; } -Vec2 operator*=(Vec2 &a, float b) { a = a * b; return a; } -Vec2 operator/=(Vec2 &a, float b) { a = a / b; return a; } - -// clang-format on