The new window splits

This commit is contained in:
Krzosa Karol
2025-05-05 08:37:41 +02:00
parent 542b0f0a0a
commit 4a1554ce28
8 changed files with 224 additions and 163 deletions

View File

@@ -10,6 +10,8 @@
if (!(x)) { \
__debugbreak(); \
}
#define InvalidCodepath() Assert(!"invalid codepath")
#define ElseInvalidCodepath() else {InvalidCodepath()}
#if defined(__APPLE__) && defined(__MACH__)
#define OS_MAC 1

View File

@@ -195,21 +195,7 @@ void ReportErrorf(const char *fmt, ...) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error!", string.data, NULL);
View *view = GetView(NullViewID);
Command_Appendf(view, "%.*s\n", FmtString(string));
// Set console view as active
{
Window *w = GetWindow(NullWindowID);
if (!w) {
BSet bset = GetActiveMainSet();
w = GetNextLayoutWindow(bset.window);
Buffer *b = GetBuffer(NullBufferID);
CheckpointBeforeGoto(w);
WindowOpenBufferView(w, b->name);
}
ActiveWindow = w->id;
}
ActiveWindow = NullWindowID;
}
void ReportConsolef(const char *fmt, ...) {
@@ -224,21 +210,7 @@ void ReportWarningf(const char *fmt, ...) {
STRING_FORMAT(scratch, fmt, string);
View *null_view = GetView(NullViewID);
Command_Appendf(null_view, "%.*s\n", FmtString(string));
// Set console view as active
{
Window *w = GetWindow(NullWindowID);
if (!w) {
BSet bset = GetActiveMainSet();
w = GetNextLayoutWindow(bset.window);
Buffer *b = GetBuffer(NullBufferID);
CheckpointBeforeGoto(w);
WindowOpenBufferView(w, b->name);
}
ActiveWindow = w->id;
}
ActiveWindow = NullWindowID;
}
void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = false) {

View File

@@ -54,6 +54,83 @@ void Command_GetCFiles(void) {
WindowOpenBufferView(main.window, buffer_name);
}
Window *GetRightWindow(WindowSplit *split, Window *window, bool *next_is_the_one) {
if (split->kind == WindowSplitKind_Window) {
if (*next_is_the_one) {
return split->window;
}
if (split->window == window) {
*next_is_the_one = true;
}
} else if (split->kind == WindowSplitKind_Vertical || split->kind == WindowSplitKind_Horizontal) {
Window *a = GetRightWindow(split->left, window, next_is_the_one);
if (a != window) return a;
Window *b = GetRightWindow(split->right, window, next_is_the_one);
if (b != window) return b;
} ElseInvalidCodepath();
return window;
}
Window *GetRightWindow(WindowID id) {
Window *window = GetWindow(id);
WindowSplit *split = window->split_ref;
Assert(split->kind == WindowSplitKind_Window);
bool next_is_the_one = false;
Window *result = GetRightWindow(&WindowSplits, window, &next_is_the_one);
return result;
}
Window *GetLeftWindow(WindowSplit *split, Window *window, bool *next_is_the_one) {
if (split->kind == WindowSplitKind_Window) {
if (*next_is_the_one) {
return split->window;
}
if (split->window == window) {
*next_is_the_one = true;
}
} else if (split->kind == WindowSplitKind_Vertical || split->kind == WindowSplitKind_Horizontal) {
Window *b = GetLeftWindow(split->right, window, next_is_the_one);
if (b != window) return b;
Window *a = GetLeftWindow(split->left, window, next_is_the_one);
if (a != window) return a;
} ElseInvalidCodepath();
return window;
}
Window *GetLeftWindow(WindowID id) {
Window *window = GetWindow(id);
WindowSplit *split = window->split_ref;
Assert(split->kind == WindowSplitKind_Window);
bool next_is_the_one = false;
Window *result = GetLeftWindow(&WindowSplits, window, &next_is_the_one);
return result;
}
Window *GetNWindow(WindowSplit *split, Window *null_window, int n, int *counter) {
if (split->kind == WindowSplitKind_Window) {
*counter += 1;
if (n == *counter) {
return split->window;
}
} else if (split->kind == WindowSplitKind_Vertical || split->kind == WindowSplitKind_Horizontal) {
Window *a = GetNWindow(split->left, null_window, n, counter);
if (a) return a;
Window *b = GetNWindow(split->right, null_window, n, counter);
if (b) return b;
} ElseInvalidCodepath();
return NULL;
}
Window *GetNWindow(int n) {
int counter = 0;
Window *result = GetNWindow(&WindowSplits, GetWindow(NullWindowID), n, &counter);
return result;
}
void UpdateScroll(Window *window, bool update_caret_scrolling) {
ProfileFunction();
BSet set = GetBSet(window);
@@ -333,20 +410,15 @@ void OnCommand(Event event) {
}
}
if (CtrlPress(SDLK_GRAVE)) {
if (ActiveWindow != NullWindowID) {
ActiveWindow = NullWindowID;
// GetView(NullViewID);
}
}
if (CtrlPress(SDLK_P)) {
Command_ListBuffers();
}
if (CtrlShiftPress(SDLK_BACKSLASH)) {
AddRowWindow();
SplitWindow(WindowSplitKind_Horizontal);
} else if (CtrlPress(SDLK_BACKSLASH)) {
AddColumnWindow();
SplitWindow(WindowSplitKind_Vertical);
}
if (CtrlPress(SDLK_0)) {
@@ -361,16 +433,21 @@ void OnCommand(Event event) {
ToggleFullscreen();
}
if (CtrlPress(SDLK_GRAVE)) {
if (ActiveWindow != NullWindowID) {
ActiveWindow = NullWindowID;
}
}
if (CtrlPress(SDLK_1)) {
Window *window = GetLayoutWindow(0);
Window *window = GetNWindow(2);
if (window) ActiveWindow = window->id;
}
if (CtrlPress(SDLK_2)) {
Window *window = GetLayoutWindow(1);
Window *window = GetNWindow(3);
if (window) ActiveWindow = window->id;
}
if (CtrlPress(SDLK_3)) {
Window *window = GetLayoutWindow(2);
Window *window = GetNWindow(4);
if (window) ActiveWindow = window->id;
}
@@ -589,6 +666,14 @@ void OnCommand(Event event) {
ActiveWindow = GetWindow(active.window->title_bar_window)->id;
}
if (AltPress(SDLK_RIGHT)) {
ActiveWindow = GetRightWindow(ActiveWindow)->id;
}
if (AltPress(SDLK_LEFT)) {
ActiveWindow = GetLeftWindow(ActiveWindow)->id;
}
if (CtrlShiftPress(SDLK_G)) {
} else if (CtrlPress(SDLK_G)) {

View File

@@ -21,9 +21,8 @@ WindowID NullWindowID;
WindowID DebugWindowID; // +debug
BufferID DebugBufferID;
WindowSplit WindowSplits;
WindowID ActiveWindow;
WindowID ActiveWindowCounterID;
Int ActiveWindowCounter;
WindowID ScrollbarSelected = {-1};
WindowID DocumentSelected = {-1};

View File

@@ -174,7 +174,9 @@ void Update(Event event) {
}
OnCommand(event);
for (Window *it = FirstWindow; it; it = it->next) if (it->is_title_bar) ReplaceTitleBarData(it);
for (Window *it = FirstWindow; it; it = it->next) {
if (it->is_title_bar) ReplaceTitleBarData(it);
}
UpdateProcesses();
UpdateCo(&event);
ReloadLuaConfigs();

View File

@@ -1,7 +1,8 @@
struct Window; struct View;
struct Window; struct View; struct WindowSplit;
struct ViewID { Int id; View *o; };
struct WindowID { Int id; Window *o; }; // @todo: change name of object to something scary
struct View {
ViewID id;
BufferID active_buffer;
@@ -25,6 +26,7 @@ struct Window {
ViewID active_view;
Window *next;
Window *prev;
WindowSplit *split_ref;
WindowID title_bar_window;
Int title_bar_last_buffer_change_id; // @todo: bring back the changes to title bar?
@@ -52,12 +54,34 @@ struct Window {
bool absolute_position : 1;
bool is_title_bar : 1;
bool is_search_bar : 1;
bool is_column : 1;
bool deactivate_on_escape : 1;
};
};
enum WindowSplitKind {
WindowSplitKind_Window,
WindowSplitKind_Vertical,
WindowSplitKind_Horizontal,
};
enum ValueKind {
ValueKind_Proportion,
ValueKind_CharSize,
ValueKind_CharSizeOtherWindow,
};
struct WindowSplit {
WindowSplitKind kind;
WindowSplit *left;
WindowSplit *right;
WindowSplit *parent;
Window *window;
ValueKind value_kind;
double value;
};
struct Scroller {
Rect2 rect;
double begin;

View File

@@ -3,6 +3,7 @@
- Windows, Buffers, Views should not be in a dynamic list it risks memory errors. Should be instead in a Double linked list, any freeing should happen at GC stage
- Fix B: not opening
- Scroll the console properly
- commands for scrolling: center, cursor_at_bottom_of_screen, cursor_at_top
--------------
buffer = make_buffer()

View File

@@ -1,48 +1,3 @@
struct VisualColumn {
Window *window;
Array<Window *> rows;
};
Array<VisualColumn> GetVisualColumns(Allocator allocator) {
Array<VisualColumn> columns = {allocator};
for (Window *it = FirstWindow; it; it = it->next) {
if (!it->visible || it->absolute_position || it->is_title_bar || it->is_search_bar) {
continue;
}
if (it->is_column) {
Add(&columns, {it, {allocator}});
VisualColumn *col = GetLast(columns);
Add(&col->rows, it);
} else if (columns.len) {
VisualColumn *col = GetLast(columns);
Add(&col->rows, it);
}
}
return columns;
}
Window *GetLayoutWindow(int n) {
int i = 0;
for (Window *it = FirstWindow; it; it = it->next) {
if (!it->is_column || !it->visible || it->absolute_position || it->is_title_bar || it->is_search_bar) continue;
if (n == i) return it;
i += 1;
}
return NULL;
}
Window *GetNextLayoutWindow(Window *input_window) {
bool found = false;
for (Window *it = FirstWindow; it; it = it->next) {
if (!it->is_column || !it->visible || it->absolute_position || it->is_title_bar || it->is_search_bar) continue;
if (found) return it;
if (it->id == input_window->id) found = true;
}
return input_window;
}
Array<Window *> GetWindowZOrder(Allocator allocator) {
Array<Window *> order = {allocator};
for (Window *it = FirstWindow; it; it = it->next) if (it->z == 2) Add(&order, it);
@@ -105,22 +60,45 @@ Int GetTitleBarSize(Window *window) {
return (Int)result;
}
void AddColumnWindow() {
Window *window = CreateWindow();
window->is_column = true;
View *view = OpenBufferView(ScratchBuffer->name);
window->active_view = view->id;
CreateTitlebar(window->id);
CreateSearchBar(window->id);
WindowSplit *CreateSplitForWindow(Window *window) {
WindowSplit *split = AllocType(Perm, WindowSplit);
split->kind = WindowSplitKind_Window;
split->window = window;
window->split_ref = split;
return split;
}
void AddRowWindow() {
Window *active_window = GetActiveWindow();
void SplitWindowEx(WindowSplit **node, WindowSplit *split, Window *target, Window *new_window, WindowSplitKind kind) {
if (split->kind == WindowSplitKind_Horizontal || split->kind == WindowSplitKind_Vertical) {
SplitWindowEx(&split->left, split->left, target, new_window, kind);
SplitWindowEx(&split->right, split->right, target, new_window, kind);
} else {
Assert(split->kind == WindowSplitKind_Window);
if (target != split->window) {
return;
}
WindowSplit *hori = AllocType(Perm, WindowSplit);
hori->kind = kind;
hori->value_kind = ValueKind_Proportion;
hori->value = 0.5;
hori->left = *node;
hori->right = CreateSplitForWindow(new_window);
*node = hori;
}
}
void SplitWindow(WindowSplitKind kind) {
Window *window = CreateWindow();
View *view = OpenBufferView(ScratchBuffer->name);
window->active_view = view->id;
CreateTitlebar(window->id);
CreateSearchBar(window->id);
Window *active_window = GetActiveWindow();
SplitWindowEx(NULL, &WindowSplits, active_window, window, kind);
ActiveWindow = window->id;
}
void SetVisibility(WindowID window_id, bool v) {
@@ -192,37 +170,37 @@ https://www.lua.org/manual/5.4/
void InitWindows() {
Allocator sys_allocator = Perm;
WindowSplit *split = &WindowSplits;
split->kind = WindowSplitKind_Horizontal;
split->value_kind = ValueKind_CharSizeOtherWindow;
split->value = (double)StyleConsoleSizeSmall;
{
Window *window = CreateWindow();
window->active_view = NullViewID;
Assert(NullWindowID.id == 0);
// @todo - Windows, Buffers, Views should not be in a dynamic list it risks memory errors. Should be instead in a Double linked list, any freeing should happen at GC stage
WindowID id = window->id;
Assert(window->id.id == 0);
CreateTitlebar(window->id);
CreateSearchBar(window->id);
CreateTitlebar(id);
CreateSearchBar(id);
split->left = CreateSplitForWindow(window);
}
{
Window *window = CreateWindow();
// @todo - Windows, Buffers, Views should not be in a dynamic list it risks memory errors. Should be instead in a Double linked list, any freeing should happen at GC stage
WindowID window_id = window->id;
window->is_column = true;
Buffer *buffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkingDir, "test_buffer"));
View *view = CreateView(buffer->id);
LoadTestBufferMessage(buffer);
window->active_view = view->id;
CreateTitlebar(window_id);
CreateTitlebar(window->id);
CreateSearchBar(window->id);
ActiveWindow = window->id;
ActiveWindow = ActiveWindowCounterID = window_id;
split->right = CreateSplitForWindow(window);
}
{
Window *window = CreateWindow();
// @todo - Windows, Buffers, Views should not be in a dynamic list it risks memory errors. Should be instead in a Double linked list, any freeing should happen at GC stage
WindowID window_id = window->id;
DebugWindowID = window->id;
window->draw_line_numbers = false;
window->absolute_position = true;
@@ -237,65 +215,23 @@ void InitWindows() {
View *view = CreateView(buffer->id);
window->active_view = view->id;
Window *titlebar = CreateTitlebar(window_id);
Window *titlebar = CreateTitlebar(window->id);
Window *searchbar = CreateSearchBar(window->id);
titlebar->z = 2;
searchbar->z = 2;
SetVisibility(window_id, false);
SetVisibility(window->id, false);
}
}
void LayoutWindows(int16_t wx, int16_t wy) {
float ScrollBarSize = (10.f * DPIScale);
Rect2I screen_rect = RectI0Size(wx, wy);
void LayoutWindowSplit(WindowSplit *split, Rect2I rect) {
float scrollbar_size = (10.f * DPIScale);
float line_numbers_size = (float)FontCharSpacing * 10;
float sizex = (float)GetSize(screen_rect).x;
{
Window *window = GetWindow(NullWindowID);
Int console_panel_size = StyleConsoleSizeSmall;
if (ActiveWindow == window->id) {
console_panel_size = StyleConsoleSizeBig;
}
Rect2I rect = CutBottom(&screen_rect, FontLineSpacing*console_panel_size);
Window *title_bar_window = GetWindow(window->title_bar_window);
title_bar_window->total_rect = CutBottom(&window->total_rect, GetTitleBarSize(title_bar_window));
title_bar_window->document_rect = title_bar_window->total_rect;
Rect2I save_rect = window->document_rect;
CutLeft(&save_rect, GetSize(save_rect).x/2);
Window *search_bar_window = GetWindow(window->search_bar_window);
search_bar_window->total_rect = CutTop(&save_rect, GetTitleBarSize(search_bar_window));
search_bar_window->document_rect = search_bar_window->total_rect;
window->document_rect = window->total_rect;
if (window->draw_scrollbar) window->scrollbar_rect = CutRight(&window->document_rect, (Int)ScrollBarSize);
if (window->draw_line_numbers) window->line_numbers_rect = CutLeft(&window->document_rect, (Int)line_numbers_size);
window->total_rect = rect;
}
Scratch scratch;
Array<VisualColumn> columns = GetVisualColumns(scratch);
float delta_column = 1.0f / (float)columns.len;
ForItem(col, columns) {
Int add = 0;
if (IsLast(columns, col)) add += 2;
Rect2I rect = CutLeft(&screen_rect, (Int)(delta_column * sizex + add));
float sizey = (float)GetSize(rect).y;
float delta_row = 1.0f / (float)col.rows.len;
ForItem(row, col.rows) {
row->total_rect = CutTop(&rect, (Int)(delta_row * sizey));
}
}
for (Window *it = FirstWindow; it; it = it->next) {
if (!it->visible || it->absolute_position || it->is_title_bar || it->is_search_bar) continue;
if (split->kind == WindowSplitKind_Window) {
Window *it = split->window;
Assert(it->split_ref);
it->total_rect = rect;
Window *title_bar_window = GetWindow(it->title_bar_window);
title_bar_window->total_rect = CutBottom(&it->total_rect, GetTitleBarSize(title_bar_window));
@@ -308,10 +244,50 @@ void LayoutWindows(int16_t wx, int16_t wy) {
search_bar_window->document_rect = search_bar_window->total_rect;
it->document_rect = it->total_rect;
if (it->draw_scrollbar) it->scrollbar_rect = CutRight(&it->document_rect, (Int)ScrollBarSize);
if (it->draw_scrollbar) it->scrollbar_rect = CutRight(&it->document_rect, (Int)scrollbar_size);
if (it->draw_line_numbers) it->line_numbers_rect = CutLeft(&it->document_rect, (Int)line_numbers_size);
} else if (split->kind == WindowSplitKind_Vertical) {
Rect2I rect2 = {0};
if (split->value_kind == ValueKind_Proportion) {
rect2 = CutLeft(&rect, (Int)round((double)GetSize(rect).x * split->value));
} else if (split->value_kind == ValueKind_CharSize) {
rect2 = CutLeft(&rect, (Int)round((double)FontCharSpacing * split->value));
} else {
Assert(split->value_kind == ValueKind_CharSizeOtherWindow);
rect2 = CutRight(&rect, (Int)round((double)FontCharSpacing * split->value));
}
LayoutWindowSplit(split->left, rect2);
LayoutWindowSplit(split->right, rect);
} else if (split->kind == WindowSplitKind_Horizontal) {
Rect2I rect2 = {0};
if (split->value_kind == ValueKind_Proportion) {
rect2 = CutTop(&rect, (Int)round((double)GetSize(rect).y * split->value));
} else if (split->value_kind == ValueKind_CharSize) {
rect2 = CutTop(&rect, (Int)round((double)FontLineSpacing * split->value));
} else {
Assert(split->value_kind == ValueKind_CharSizeOtherWindow);
rect2 = CutBottom(&rect, (Int)round((double)FontLineSpacing * split->value));
}
LayoutWindowSplit(split->left, rect2);
LayoutWindowSplit(split->right, rect);
} else {
Assert(!"Invalid codepath");
}
}
void LayoutWindows(int16_t wx, int16_t wy) {
if (ActiveWindow == NullWindowID) {
WindowSplits.value = (double)StyleConsoleSizeBig;
} else {
WindowSplits.value = (double)StyleConsoleSizeSmall;
}
Rect2I screen_rect = RectI0Size(wx, wy);
LayoutWindowSplit(&WindowSplits, screen_rect);
// layout debug window
{
Window *window = GetWindow(DebugWindowID);
Rect2 screen_rect = Rect0Size(wx, wy);