From de7f084633a282220f317800be3bed1824f649cc Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sun, 28 Jul 2024 14:30:24 +0200 Subject: [PATCH] Experimenting with tabs --- build_file.cpp | 11 +++++-- src/basic/string16.cpp | 42 ++++++++++++++++++++++++++ src/text_editor/commands.cpp | 9 ++++++ src/text_editor/generated.cpp | 25 +++++++++++++--- src/text_editor/text_editor.cpp | 11 ++++++- src/text_editor/text_editor.h | 5 +++- src/text_editor/todo.txt | 4 +-- src/text_editor/window.cpp | 10 +++++-- src/text_editor/window_draw.cpp | 52 +++++++++++++++++++++++++++++++-- 9 files changed, 153 insertions(+), 16 deletions(-) diff --git a/build_file.cpp b/build_file.cpp index fc16496..c887e68 100644 --- a/build_file.cpp +++ b/build_file.cpp @@ -354,18 +354,25 @@ void GenerateConfig() { gruvbox.add({"GruvboxFadedAqua" , "0x427b58ff"}); gruvbox.add({"GruvboxFadedOrange" , "0xaf3a03ff"}); + gruvbox.add({"_InactiveWindowColor" , "0x0000000F"}); + Array colors = {}; colors.add({"Text" , "GruvboxDark0Hard"}); colors.add({"Background" , "GruvboxLight0Hard"}); + colors.add({"InactiveWindow" , "_InactiveWindowColor"}); + colors.add({"TabText" , "GruvboxDark0Hard"}); + colors.add({"TabBackground" , "GruvboxLight0Hard"}); + colors.add({"TabBackgroundInactive" , "GruvboxLight2"}); + colors.add({"TabSeparator" , "GruvboxLight2"}); colors.add({"TextLineNumbers" , "GruvboxDark4"}); colors.add({"ScrollbarBackground" , "GruvboxLight2"}); colors.add({"ScrollbarScroller" , "GruvboxLight1"}); colors.add({"ScrollbarScrollerSelected", "GruvboxLight0Hard"}); - colors.add({"LineHighlight" , "GruvboxLight1"}); + colors.add({"LineHighlight" , "GruvboxLight0Soft"}); colors.add({"MainCaret" , "GruvboxDark0Hard"}); colors.add({"SubCaret" , "GruvboxGray245"}); colors.add({"Selection" , "GruvboxLight1"}); - colors.add({"WhitespaceDuringSelection", "GruvboxLight2"}); + colors.add({"WhitespaceDuringSelection", "GruvboxLight4"}); // clang-format on { diff --git a/src/basic/string16.cpp b/src/basic/string16.cpp index 4a2266d..c7c92ff 100644 --- a/src/basic/string16.cpp +++ b/src/basic/string16.cpp @@ -108,3 +108,45 @@ bool Seek(String16 string, String16 find, int64_t *index_out = NULL, SeekFlag fl return result; } + +String16 ChopLastSlash(String16 s) { + String16 result = s; + Seek(s, L"/", &result.len, SeekFlag_MatchFindLast); + return result; +} + +String16 ChopLastPeriod(String16 s) { + String16 result = s; + Seek(s, L".", &result.len, SeekFlag_MatchFindLast); + return result; +} + +String16 SkipToLastSlash(String16 s) { + int64_t pos; + String16 result = s; + if (Seek(s, L"/", &pos, SeekFlag_MatchFindLast)) { + result = Skip(result, pos + 1); + } + return result; +} + +String16 SkipToLastPeriod(String16 s) { + int64_t pos; + String16 result = s; + if (Seek(s, L".", &pos, SeekFlag_MatchFindLast)) { + result = Skip(result, pos + 1); + } + return result; +} + +String16 CutPrefix(String16 *string, int64_t len) { + String16 result = GetPrefix(*string, len); + *string = Skip(*string, len); + return result; +} + +String16 CutPostfix(String16 *string, int64_t len) { + String16 result = GetPostfix(*string, len); + *string = Chop(*string, len); + return result; +} diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index 156c790..0f5c696 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -355,6 +355,15 @@ void ReportErrorf(const char *fmt, ...) { ReplaceText(buffer, {}, string16); } +void ReportConsolef(const char *fmt, ...) { + Scratch scratch; + STRING_FORMAT(scratch, fmt, string); + String16 string16 = ToString16(scratch, string); + Buffer *buffer = GetBuffer("*console*"); + ReplaceText(buffer, {}, string16); + ReplaceText(buffer, Rng(string16.len), L"\n"); +} + void ReportWarningf(const char *fmt, ...) { Scratch scratch; STRING_FORMAT(scratch, fmt, string); diff --git a/src/text_editor/generated.cpp b/src/text_editor/generated.cpp index a3c37ef..8d54007 100644 --- a/src/text_editor/generated.cpp +++ b/src/text_editor/generated.cpp @@ -35,17 +35,23 @@ Color GruvboxFadedBlue = {0x07, 0x66, 0x78, 0xff}; Color GruvboxFadedPurple = {0x8f, 0x3f, 0x71, 0xff}; Color GruvboxFadedAqua = {0x42, 0x7b, 0x58, 0xff}; Color GruvboxFadedOrange = {0xaf, 0x3a, 0x03, 0xff}; +Color _InactiveWindowColor = {0x00, 0x00, 0x00, 0x0F}; Color ColorText = GruvboxDark0Hard; Color ColorBackground = GruvboxLight0Hard; +Color ColorInactiveWindow = _InactiveWindowColor; +Color ColorTabText = GruvboxDark0Hard; +Color ColorTabBackground = GruvboxLight0Hard; +Color ColorTabBackgroundInactive = GruvboxLight2; +Color ColorTabSeparator = GruvboxLight2; Color ColorTextLineNumbers = GruvboxDark4; Color ColorScrollbarBackground = GruvboxLight2; Color ColorScrollbarScroller = GruvboxLight1; Color ColorScrollbarScrollerSelected = GruvboxLight0Hard; -Color ColorLineHighlight = GruvboxLight1; +Color ColorLineHighlight = GruvboxLight0Soft; Color ColorMainCaret = GruvboxDark0Hard; Color ColorSubCaret = GruvboxGray245; Color ColorSelection = GruvboxLight1; -Color ColorWhitespaceDuringSelection = GruvboxLight2; +Color ColorWhitespaceDuringSelection = GruvboxLight4; String BaseLuaConfig = R"==( local GruvboxDark0Hard = 0x1d2021ff local GruvboxDark0 = 0x282828ff @@ -84,18 +90,24 @@ local GruvboxFadedBlue = 0x076678ff local GruvboxFadedPurple = 0x8f3f71ff local GruvboxFadedAqua = 0x427b58ff local GruvboxFadedOrange = 0xaf3a03ff +local _InactiveWindowColor = 0x0000000F Color = {} Color.Text = GruvboxDark0Hard Color.Background = GruvboxLight0Hard +Color.InactiveWindow = _InactiveWindowColor +Color.TabText = GruvboxDark0Hard +Color.TabBackground = GruvboxLight0Hard +Color.TabBackgroundInactive = GruvboxLight2 +Color.TabSeparator = GruvboxLight2 Color.TextLineNumbers = GruvboxDark4 Color.ScrollbarBackground = GruvboxLight2 Color.ScrollbarScroller = GruvboxLight1 Color.ScrollbarScrollerSelected = GruvboxLight0Hard -Color.LineHighlight = GruvboxLight1 +Color.LineHighlight = GruvboxLight0Soft Color.MainCaret = GruvboxDark0Hard Color.SubCaret = GruvboxGray245 Color.Selection = GruvboxLight1 -Color.WhitespaceDuringSelection = GruvboxLight2 +Color.WhitespaceDuringSelection = GruvboxLight4 -- @todo: should we rewrite linux paths to windows on windows and vice-versa? @@ -222,6 +234,11 @@ end void ReloadColors() { ColorText = GetColor("Text", ColorText); ColorBackground = GetColor("Background", ColorBackground); + ColorInactiveWindow = GetColor("InactiveWindow", ColorInactiveWindow); + ColorTabText = GetColor("TabText", ColorTabText); + ColorTabBackground = GetColor("TabBackground", ColorTabBackground); + ColorTabBackgroundInactive = GetColor("TabBackgroundInactive", ColorTabBackgroundInactive); + ColorTabSeparator = GetColor("TabSeparator", ColorTabSeparator); ColorTextLineNumbers = GetColor("TextLineNumbers", ColorTextLineNumbers); ColorScrollbarBackground = GetColor("ScrollbarBackground", ColorScrollbarBackground); ColorScrollbarScroller = GetColor("ScrollbarScroller", ColorScrollbarScroller); diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index 7982eec..0bc498e 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -168,6 +168,11 @@ int main() SDL_StartTextInput(window); SDL_GL_SetSwapInterval(1); // vsync + { + float scale = SDL_GetWindowDisplayScale(window); + if (scale != 1.0f) DPIScale = scale; + } + InitRender(); ReloadFont(16); InitLua(); @@ -268,6 +273,11 @@ int main() String16 string16 = GetString(*lua_buffer); String string = ToString(scratch, string16); if (luaL_dostring(LuaState, string.data) == LUA_OK) { + if (lua_isstring(LuaState, -1)) { + const char *text = lua_tostring(LuaState, -1); + ReportConsolef(text); + lua_pop(LuaState, 1); + } ReloadColors(); } else { const char *error_message = lua_tostring(LuaState, -1); @@ -289,7 +299,6 @@ int main() View *view = GetView(window->active_view); UpdateScroll(window, !AreEqual(view->main_caret_on_begin_frame, view->carets[0]) && view->update_scroll); - DrawWindow(window); } EndFrameRender(ColorBackground); diff --git a/src/text_editor/text_editor.h b/src/text_editor/text_editor.h index c91e3b8..e5baa23 100644 --- a/src/text_editor/text_editor.h +++ b/src/text_editor/text_editor.h @@ -58,6 +58,7 @@ struct Window { Array views; Rect2I total_rect; + Rect2I tabs_rect; Rect2I scrollbar_rect; Rect2I line_numbers_rect; Rect2I document_rect; @@ -72,9 +73,10 @@ struct Window { bool draw_scrollbar : 1; bool draw_line_numbers : 1; + bool draw_tabs : 1; bool visible : 1; - bool fuzzy_search : 1; + bool fuzzy_search : 1; // @todo: consider moving this to view and introducing view commands bool execute_line : 1; bool invisible_when_inactive : 1; bool dont_save_in_active_window_history : 1; @@ -94,6 +96,7 @@ String WorkingDir; String ConfigDir; String ExeDir; Arena Perm; +float DPIScale = 1.0f; String16 EvalString(Allocator allocator, String16 string16); Rect2I GetVisibleCells(Window *window); diff --git a/src/text_editor/todo.txt b/src/text_editor/todo.txt index b4355e5..372b201 100644 --- a/src/text_editor/todo.txt +++ b/src/text_editor/todo.txt @@ -1,15 +1,13 @@ - Save file (utf16->utf8) - make sure we only save file buffers - resize windows +- color the line number with line highlight - page up and down should also scroll and leave you in exactly same scroll - laying out windows, more choice - window borders - file dock on left side - We can actually combine this with command window and lua, it's just going to be a buffer of - open "asd/asd/asd/asd" -- console buffer with output and errors - - some popup for errors - - good error reporting for user - word completion - Colored strings - open project files in folder and only show open views in Ctrl+P diff --git a/src/text_editor/window.cpp b/src/text_editor/window.cpp index 0016918..55b8927 100644 --- a/src/text_editor/window.cpp +++ b/src/text_editor/window.cpp @@ -10,9 +10,10 @@ void InitWindows(View *null_view) { Allocator sys_allocator = GetSystemAllocator(); { - Window *w = CreateWindow(); - Buffer *b = CreateBuffer(sys_allocator, "*load_text_a*"); - View *v = CreateView(b->id); + Window *w = CreateWindow(); + w->draw_tabs = true; + Buffer *b = CreateBuffer(sys_allocator, "*load_text_a*"); + View *v = CreateView(b->id); LoadTextA(b); LoadUnicode(b); AddView(w, null_view->id); @@ -21,6 +22,7 @@ void InitWindows(View *null_view) { { Window *w = CreateWindow(); + w->draw_tabs = true; Buffer *b = CreateBuffer(sys_allocator, "*console*"); b->no_history = true; View *v = CreateView(b->id); @@ -120,6 +122,7 @@ void LayoutWindows() { int i = 0; Windows[i].total_rect = CutLeft(&screen_rect, (Int)((double)sizex * 0.5)); Windows[i].document_rect = Windows[i].total_rect; + if (Windows[i].draw_tabs) Windows[i].tabs_rect = CutTop(&Windows[i].document_rect, (Int)FontLineSpacing); if (Windows[i].draw_scrollbar) Windows[i].scrollbar_rect = CutRight(&Windows[i].document_rect, 10); if (Windows[i].draw_line_numbers) Windows[i].line_numbers_rect = CutLeft(&Windows[i].document_rect, (Int)line_numbers_size); } @@ -127,6 +130,7 @@ void LayoutWindows() { int i = 1; Windows[i].total_rect = CutLeft(&screen_rect, (Int)((double)sizex)); Windows[i].document_rect = Windows[i].total_rect; + if (Windows[i].draw_tabs) Windows[i].tabs_rect = CutTop(&Windows[i].document_rect, (Int)FontLineSpacing); if (Windows[i].draw_scrollbar) Windows[i].scrollbar_rect = CutRight(&Windows[i].document_rect, 10); if (Windows[i].draw_line_numbers) Windows[i].line_numbers_rect = CutLeft(&Windows[i].document_rect, (Int)line_numbers_size); } diff --git a/src/text_editor/window_draw.cpp b/src/text_editor/window_draw.cpp index 376b0e8..bf65eb4 100644 --- a/src/text_editor/window_draw.cpp +++ b/src/text_editor/window_draw.cpp @@ -93,9 +93,10 @@ void DrawWindow(Window *window) { View *view = GetActiveView(window); Buffer *buffer = GetBuffer(view->active_buffer); SetScissor(GetScreenRectF()); - DrawRect(window->total_rect, ColorBackground); bool is_active = IsActive(window) || window->id.id == GetLastActiveWindow().id; + DrawRect(window->total_rect, ColorBackground); + SetScissor(window->document_rect); BeginProfileScope(draw_caret_selection); Rect2I visible = GetVisibleCells(window); @@ -197,8 +198,55 @@ void DrawWindow(Window *window) { DrawRect(rect, color); } + if (window->draw_tabs) { + Rect2 rect = ToRect2(window->tabs_rect); + SetScissor(rect); + DrawRect(rect, ColorTabBackgroundInactive); + + Int open_views = window->views.len; + Vec2 entire_tab_size = GetSize(rect); + + Vec2 tab_size = {200 * DPIScale, entire_tab_size.y}; + // Vec2 tab_size = {entire_tab_size.x / (float)open_views, }; + + // float total = entire_tab_size.x / tab_size.x; + float offset = entire_tab_size.x / (float)window->views.len; + offset = ClampTop(tab_size.x, offset); + + float i = (float)window->views.len - 1; + For(window->views) { + Rect2 tab_rect = Rect2FromSize({rect.min.x + offset * i, rect.min.y}, tab_size); + i -= 1.f; + + Scratch scratch; + View *view = GetView(it); + Buffer *buffer = GetBuffer(view->active_buffer); + + String16 string16 = ToString16(scratch, buffer->name); + string16 = SkipToLastSlash(string16); + Vec2 string_size = GetStringSize(&MainFont, string16); + Vec2 pos = {tab_rect.min.x + (tab_size.x - string_size.x) / 2}; + pos.y = tab_rect.min.y; + + if (window->active_view.id == it.id) { + DrawRect(tab_rect, ColorTabBackground); + } else { + DrawRect(tab_rect, ColorTabBackgroundInactive); + } + DrawString(&MainFont, string16, pos, ColorTabText); + + Rect2 sep = CutRight(&tab_rect, 1); + DrawRect(sep, ColorTabSeparator); + sep = CutLeft(&tab_rect, 1); + DrawRect(sep, ColorTabSeparator); + } + + Rect2 sep = CutRight(&rect, 1); + DrawRect(sep, ColorTabSeparator); + } + if (!is_active) { SetScissor(GetScreenRectF()); - DrawRect(window->total_rect, {0, 0, 0, 30}); + DrawRect(window->total_rect, ColorInactiveWindow); } }