diff options
| author | 2023-11-24 04:58:20 -0600 | |
|---|---|---|
| committer | 2023-11-24 04:58:20 -0600 | |
| commit | cb32a721d811caf450f3c55cfb419559d84fa891 (patch) | |
| tree | 4967bee504cfee63c94fe0b7e7e93566071ffbf0 /src/ui | |
| parent | add some menu test code (diff) | |
not every UI window maps to a curses window
Diffstat (limited to 'src/ui')
| -rw-r--r-- | src/ui/base.c | 91 | ||||
| -rw-r--r-- | src/ui/debug.c | 14 | ||||
| -rw-r--r-- | src/ui/dock.c | 96 | ||||
| -rw-r--r-- | src/ui/root.c | 50 | ||||
| -rw-r--r-- | src/ui/ui.internal.h | 20 |
5 files changed, 155 insertions, 116 deletions
diff --git a/src/ui/base.c b/src/ui/base.c index 50e6944..dd454ec 100644 --- a/src/ui/base.c +++ b/src/ui/base.c @@ -4,23 +4,61 @@ #include "ui.internal.h" #include "ui/uimenu.internal.h" +#include "../macros.h" struct ui_window_root *ui_root = NULL; void ui__default_draw_proc(struct ui_window_base *base) { - wnoutrefresh(base->cwindow); /* root window calls doupdate */ + umps_unused(base); +} + +void ui__leaf_draw_proc(struct ui_window_base *base) +{ + WINDOW *mywin = ((struct ui_window_leaf *)base)->cwindow; + int maxy, maxx; + getmaxyx(mywin, maxy, maxx); + + box(mywin, 0, 0); + mvwaddstr(mywin, 0, 2, "Traces"); + for (int i = 1; i < maxy-1; ++i) { + mvwhline(mywin, i, 1, '.', maxx - 2); + } + + wnoutrefresh(mywin); +} + +void ui__leaf_layout_proc(struct ui_window_base *base) +{ + struct ui_window_leaf *leaf = (struct ui_window_leaf *)base; + if (leaf->cwindow) delwin(leaf->cwindow); + leaf->cwindow = newwin(leaf->super.dims.maxy, leaf->super.dims.maxx, leaf->super.dims.begy, leaf->super.dims.begx); } void ui__init_window_base(struct ui_window_base *base) { base->type = UI__WINDOW_TYPE_BASE; base->parent = NULL; - base->cwindow = NULL; + + base->dims.begy = 0; + base->dims.begx = 0; + base->dims.maxy = 0; + base->dims.maxx = 0; + base->draw_proc = &ui__default_draw_proc; base->layout_proc = NULL; } +void ui__init_window_leaf(struct ui_window_leaf *leaf) +{ + ui__init_window_base(&leaf->super); + leaf->super.type = UI__WINDOW_TYPE_LEAF; + leaf->super.draw_proc = &ui__leaf_draw_proc; + leaf->super.layout_proc = &ui__leaf_layout_proc; + + leaf->cwindow = NULL; +} + void ui__init_window_dock(struct ui_window_dock *dock) { ui__init_window_base(&dock->super); @@ -40,11 +78,14 @@ void ui__init_window_dock(struct ui_window_dock *dock) void ui__init_window_root(struct ui_window_root *root, WINDOW *cwindow) { ui__init_window_base(&root->super); - root->super.cwindow = cwindow; root->super.type = UI__WINDOW_TYPE_ROOT; root->super.draw_proc = &ui__root_draw_proc; root->super.layout_proc = &ui__root_layout_proc; + root->cwindow = cwindow; + getmaxyx(cwindow, root->super.dims.maxy, root->super.dims.maxx); + getbegyx(cwindow, root->super.dims.begy, root->super.dims.begx); + root->undersize_scr = false; root->content = NULL; root->floating = NULL; @@ -55,6 +96,7 @@ void ui__init_window_root(struct ui_window_root *root, WINDOW *cwindow) /* type-specific destructors */ void ui__destroy_window_base(struct ui_window_base *base); +void ui__destroy_window_leaf(struct ui_window_leaf *leaf); void ui__destroy_window_dock(struct ui_window_dock *dock); void ui__window_destroy_root(struct ui_window_root *root) @@ -67,6 +109,8 @@ void ui__window_destroy_root(struct ui_window_root *root) uimenu_menu_free(root->menu_root); + if (root->cwindow) delwin(root->cwindow); + ui__destroy_window_base(&root->super); } @@ -81,9 +125,14 @@ void ui__destroy_window_dock(struct ui_window_dock *dock) ui__destroy_window_base(&dock->super); } +void ui__destroy_window_leaf(struct ui_window_leaf *leaf) +{ + if (leaf->cwindow) delwin(leaf->cwindow); + ui__destroy_window_base(&leaf->super); +} + void ui__destroy_window_base(struct ui_window_base *base) { - delwin(base->cwindow); free(base); } @@ -99,14 +148,17 @@ void ui__destroy_window(struct ui_window_base *base) case UI__WINDOW_TYPE_DOCK: ui__destroy_window_dock(ui__cast(dock, base)); break; + case UI__WINDOW_TYPE_LEAF: + ui__destroy_window_leaf(ui__cast(leaf, base)); + break; case UI__WINDOW_TYPE_BASE: ui__destroy_window_base(base); } } /* the focused window MUST be a leaf window, or the screen will get clobbered. - * This is because the focused window will have methods like getch() called on it, - * which brings it to the "foreground", squashing whatever is behind it. */ + * This is because the focused window will have wgetch() called for it, which + * calls wrefresh() sometimes. This will clobber windows inside of it. */ struct ui_window_base *ui__find_focused(void) { struct ui_window_base *window = ui__cast(base, ui_root); @@ -171,20 +223,6 @@ void ui__call_layout_proc(struct ui_window_base *base) } } -void ui__traces_draw_proc(struct ui_window_base *base) -{ - box(base->cwindow, 0, 0); - int maxy, maxx; - - mvwaddstr(base->cwindow, 0, 2, "Traces"); - getmaxyx(base->cwindow, maxy, maxx); - for (int i = 1; i < maxy-1; ++i) - { - mvwhline(base->cwindow, i, 1, '.', maxx-2); - } - wnoutrefresh(base->cwindow); -} - void ui_init(void) { ui_root = malloc(sizeof(struct ui_window_root)); /* TODO: check */ @@ -216,12 +254,12 @@ void ui_init(void) for (unsigned i = 0; i < UI__WINDOW_DOCK_MAX; ++i) { if (i == UI__WINDOW_DOCK_LEFT) continue; - struct ui_window_base *win_traces = malloc(sizeof(struct ui_window_base)); - ui__init_window_base(win_traces); - ui__dock_add_child(maindock, win_traces, i, 1./5); - win_traces->draw_proc = &ui__traces_draw_proc; + struct ui_window_leaf *win_traces = malloc(sizeof(struct ui_window_leaf)); + ui__init_window_leaf(win_traces); + ui__dock_add_child(maindock, ui__cast(base, win_traces), i, 1./5); } + /* ui__call_layout_proc(ui__cast(base, ui_root)); */ ui__call_draw_proc(ui__cast(base, ui_root)); } @@ -233,7 +271,8 @@ void ui_handle(void) #ifdef NCURSES_WIDE wint_t inp; - wget_wch(window->cwindow, &inp); + /* FIXME: find a better way of circumnavigating this annoying implied-wrefresh business */ + wget_wch(ui__cast(leaf, window)->cwindow, &inp); #else int inp = wgetch(window->cwindow); #endif @@ -244,6 +283,8 @@ void ui_handle(void) } else if (inp == KEY_RESIZE) { + getmaxyx(ui_root->cwindow, ui_root->super.dims.maxy, ui_root->super.dims.maxx); + getbegyx(ui_root->cwindow, ui_root->super.dims.begy, ui_root->super.dims.begx); ui__call_layout_proc(ui__cast(base, ui_root)); ui__call_draw_proc(ui__cast(base, ui_root)); } else if (inp == NS('h')) { diff --git a/src/ui/debug.c b/src/ui/debug.c index f30c12c..6d3ea5d 100644 --- a/src/ui/debug.c +++ b/src/ui/debug.c @@ -1,7 +1,6 @@ #ifndef NDEBUG -#include <assert.h> - +#include "../macros.h" #include "ui.internal.h" struct ui_window_base *ui__check_cast_to_base(void *obj) @@ -9,17 +8,24 @@ struct ui_window_base *ui__check_cast_to_base(void *obj) return obj; /* this cast always succeeds */ } +struct ui_window_leaf *ui__check_cast_to_leaf(void *obj) +{ + struct ui_window_base *base = obj; + umps_assert(base->type == UI__WINDOW_TYPE_LEAF); + return obj; +} + struct ui_window_dock *ui__check_cast_to_dock(void *obj) { struct ui_window_base *base = obj; - assert(base->type == UI__WINDOW_TYPE_DOCK); + umps_assert(base->type == UI__WINDOW_TYPE_DOCK); return obj; } struct ui_window_root *ui__check_cast_to_root(void *obj) { struct ui_window_base *base = obj; - assert(base->type == UI__WINDOW_TYPE_ROOT); + umps_assert(base->type == UI__WINDOW_TYPE_ROOT); return obj; } diff --git a/src/ui/dock.c b/src/ui/dock.c index fd895c2..82f6728 100644 --- a/src/ui/dock.c +++ b/src/ui/dock.c @@ -21,21 +21,21 @@ unsigned ui__dock_position_opposite(unsigned position) } } -void ui__dock_adjust(struct ui_window_dock *dock, unsigned flags, int *maxy, int *maxx, int *begy, int *begx) +void ui__dock_adjust(struct ui_window_dock *dock, unsigned flags, struct ui_dims *dims) { if (flags & 1) { if (dock->children[UI__WINDOW_DOCK_TOP]) { - unsigned top_maxy = getmaxy(dock->children[UI__WINDOW_DOCK_TOP]->cwindow); - *maxy -= top_maxy; - *begy += top_maxy; + unsigned top_maxy = dock->children[UI__WINDOW_DOCK_TOP]->dims.maxy; + dims->maxy -= top_maxy; + dims->begy += top_maxy; } if (dock->children[UI__WINDOW_DOCK_BOTTOM]) { - unsigned bottom_maxy = getmaxy(dock->children[UI__WINDOW_DOCK_BOTTOM]->cwindow); - *maxy -= bottom_maxy; + unsigned bottom_maxy = dock->children[UI__WINDOW_DOCK_BOTTOM]->dims.maxy; + dims->maxy -= bottom_maxy; } } @@ -43,15 +43,15 @@ void ui__dock_adjust(struct ui_window_dock *dock, unsigned flags, int *maxy, int { if (dock->children[UI__WINDOW_DOCK_LEFT]) { - unsigned left_maxx = getmaxx(dock->children[UI__WINDOW_DOCK_LEFT]->cwindow); - *maxx -= left_maxx; - *begx += left_maxx; + unsigned left_maxx = dock->children[UI__WINDOW_DOCK_LEFT]->dims.maxx; + dims->maxx -= left_maxx; + dims->begx += left_maxx; } if (dock->children[UI__WINDOW_DOCK_RIGHT]) { - unsigned right_maxx = getmaxx(dock->children[UI__WINDOW_DOCK_RIGHT]->cwindow); - *maxx -= right_maxx; + unsigned right_maxx = dock->children[UI__WINDOW_DOCK_RIGHT]->dims.maxx; + dims->maxx -= right_maxx; } } } @@ -62,64 +62,54 @@ void ui__dock_adjust(struct ui_window_dock *dock, unsigned flags, int *maxy, int * - Center * * Note that other methods (layout proc namely) require this same order to be present in the values of the dock constants. */ -WINDOW *ui__dock_place_window(struct ui_window_dock *dock, unsigned position, float size) +void ui__dock_place_window(struct ui_window_dock *dock, unsigned position, float size, struct ui_dims *dims) { - int maxy, maxx; - int begy, begx; - - int out_lines, out_cols; - int out_y, out_x; - - getmaxyx(dock->super.cwindow, maxy, maxx); - getbegyx(dock->super.cwindow, begy, begx); + struct ui_dims mydims = dock->super.dims; switch (position) { case UI__WINDOW_DOCK_TOP: - out_lines = maxy * size; - out_y = begy; - out_cols = maxx; - out_x = begx; + dims->maxy = mydims.maxy * size; + dims->begy = mydims.begy; + dims->maxx = mydims.maxx; + dims->begx = mydims.begx; break; case UI__WINDOW_DOCK_BOTTOM: - out_lines = maxy * size; - out_y = maxy - out_lines + begy; - out_cols = maxx; - out_x = begx; + dims->maxy = mydims.maxy * size; + dims->begy = mydims.maxy - dims->maxy + mydims.begy; + dims->maxx = mydims.maxx; + dims->begx = mydims.begx; break; case UI__WINDOW_DOCK_LEFT: - ui__dock_adjust(dock, 1, &maxy, &maxx, &begy, &begx); - out_lines = maxy; - out_y = begy; - out_cols = maxx * size; - out_x = begx; + ui__dock_adjust(dock, 1, &mydims); + dims->maxy = mydims.maxy; + dims->begy = mydims.begy; + dims->maxx = mydims.maxx * size; + dims->begx = mydims.begx; break; case UI__WINDOW_DOCK_RIGHT: - ui__dock_adjust(dock, 1, &maxy, &maxx, &begy, &begx); - out_lines = maxy; - out_y = begy; - out_cols = maxx * size; - out_x = maxx - out_cols + begx; + ui__dock_adjust(dock, 1, &mydims); + dims->maxy = mydims.maxy; + dims->begy = mydims.begy; + dims->maxx = mydims.maxx * size; + dims->begx = mydims.maxx - dims->maxx + mydims.begx; break; case UI__WINDOW_DOCK_CENTER: - ui__dock_adjust(dock, 3, &maxy, &maxx, &begy, &begx); - out_lines = maxy; - out_y = begy; - out_cols = maxx; - out_x = begx; + ui__dock_adjust(dock, 3, &mydims); + dims->maxy = mydims.maxy; + dims->begy = mydims.begy; + dims->maxx = mydims.maxx; + dims->begx = mydims.begx; break; default: umps_trap; } - - return newwin(out_lines, out_cols, out_y, out_x); } void ui__dock_add_child(struct ui_window_dock *dock, struct ui_window_base *child, unsigned position, float size) { umps_assert_s(!dock->children[position], "child present"); /* TODO: handle gracefully (technically invalid usage) */ umps_assert_s(!child->parent, "child parent present"); /* TODO: take this window from its current parent */ - umps_assert_s(!child->cwindow, "child already initialized"); child->parent = (struct ui_window_base *)dock; dock->children[position] = child; @@ -135,20 +125,13 @@ void ui__dock_add_child(struct ui_window_dock *dock, struct ui_window_base *chil } /* now set up the window for this child */ - child->cwindow = ui__dock_place_window(dock, position, size); + ui__dock_place_window(dock, position, size, &child->dims); + ui__call_layout_proc(child); } void ui__dock_default_draw_proc(struct ui_window_base *base) { struct ui_window_dock *dock = ui__cast(dock, base); - int maxy, maxx; - getmaxyx(base->cwindow, maxy, maxx); - - for (int i = 0; i < maxy; ++i) { - mvwhline(base->cwindow, i, 0, '.', maxx); - } - - wnoutrefresh(dock->super.cwindow); for (unsigned i = 0; i < UI__WINDOW_DOCK_MAX; ++i) { if (dock->children[i]) @@ -166,8 +149,7 @@ void ui__dock_default_layout_proc(struct ui_window_base *base) struct ui_window_base *child = dock->children[i]; if (!child) continue; - delwin(child->cwindow); - child->cwindow = ui__dock_place_window(dock, i, dock->childsizes[i]); + ui__dock_place_window(dock, i, dock->childsizes[i], &child->dims); ui__call_layout_proc(child); } } diff --git a/src/ui/root.c b/src/ui/root.c index 3877359..00eda14 100644 --- a/src/ui/root.c +++ b/src/ui/root.c @@ -1,7 +1,7 @@ #include "ui.internal.h" #include "macros.h" #include "ui/uimenu.internal.h" -#include <curses.h> +#include <string.h> #define UI__ROOT_MIN_Y (24) #define UI__ROOT_MIN_X (80) @@ -17,20 +17,15 @@ const char *ui__status_text = "Ready"; -WINDOW *ui__root_place_content_window(struct ui_window_root *root) +void ui__root_place_content_window(struct ui_window_root *root, struct ui_dims *dims) { - int maxy, maxx; - int begy, begx; - getmaxyx(root->super.cwindow, maxy, maxx); - getbegyx(root->super.cwindow, begy, begx); - - begy += UI__ROOT_MARGIN_TOP; - maxy -= UI__ROOT_MARGIN_TOP + UI__ROOT_MARGIN_BOTTOM; + memcpy(dims, &root->super.dims, sizeof(struct ui_dims)); - begx += UI__ROOT_MARGIN_LEFT; - begx -= UI__ROOT_MARGIN_LEFT + UI__ROOT_MARGIN_RIGHT; + dims->begy += UI__ROOT_MARGIN_TOP; + dims->maxy -= UI__ROOT_MARGIN_TOP + UI__ROOT_MARGIN_BOTTOM; - return newwin(maxy, maxx, begy, begx); + dims->begx += UI__ROOT_MARGIN_LEFT; + dims->maxx -= UI__ROOT_MARGIN_LEFT + UI__ROOT_MARGIN_RIGHT; } void ui__root_draw_menu(struct ui_window_root *root); @@ -41,21 +36,21 @@ void ui__root_draw_proc(struct ui_window_base *base) struct ui_window_root *root = ui__cast(root, base); int maxy, maxx; - getmaxyx(base->cwindow, maxy, maxx); + getmaxyx(root->cwindow, maxy, maxx); if (root->undersize_scr) { for (int y = 0; y < maxy; ++y) - mvwhline(base->cwindow, y, 0, y < 3 ? ' ' : '/', maxx); + mvwhline(root->cwindow, y, 0, y < 3 ? ' ' : '/', maxx); - mvwprintw(base->cwindow, 0, 0, "Your terminal is too small! It must be at least %dx%d.", UI__ROOT_MIN_X, UI__ROOT_MIN_Y); + mvwprintw(root->cwindow, 0, 0, "Your terminal is too small! It must be at least %dx%d.", UI__ROOT_MIN_X, UI__ROOT_MIN_Y); - wrefresh(base->cwindow); + wrefresh(root->cwindow); return; } ui__root_draw_menu(root); ui__root_draw_status(root); - wnoutrefresh(base->cwindow); + wnoutrefresh(root->cwindow); if (root->content) { ui__call_draw_proc(root->content); @@ -70,7 +65,7 @@ void ui__root_draw_proc(struct ui_window_base *base) void ui__root_draw_menu(struct ui_window_root *root) { - WINDOW *mywin = root->super.cwindow; + WINDOW *mywin = root->cwindow; attron(A_REVERSE); mvwhline(mywin, 0, 0, ' ', getmaxx(mywin)); mvwaddstr(mywin, 0, 0, " UMPS v0.1.0-dev"); @@ -101,7 +96,7 @@ void ui__root_draw_menu(struct ui_window_root *root) void ui__root_draw_status(struct ui_window_root *root) { - WINDOW *mywin = root->super.cwindow; + WINDOW *mywin = root->cwindow; attron(A_REVERSE); mvwhline(mywin, getmaxy(mywin)-1, 0, ' ', getmaxx(mywin)); @@ -117,10 +112,12 @@ void ui__root_layout_proc(struct ui_window_base *base) { struct ui_window_root *root = ui__cast(root, base); - int maxy, maxx; - getmaxyx(base->cwindow, maxy, maxx); + if (root->cwindow != stdscr) { + if (root->cwindow) delwin(root->cwindow); + root->cwindow = newwin(root->super.dims.maxy, root->super.dims.maxx, root->super.dims.begy, root->super.dims.begx); + } - if (maxy < UI__ROOT_MIN_Y || maxx < UI__ROOT_MIN_X) { + if (root->super.dims.maxy < UI__ROOT_MIN_Y || root->super.dims.maxx < UI__ROOT_MIN_X) { root->undersize_scr = true; return; } @@ -128,8 +125,7 @@ void ui__root_layout_proc(struct ui_window_base *base) root->undersize_scr = false; if (root->content) { - delwin(root->content->cwindow); - root->content->cwindow = ui__root_place_content_window(root); + ui__root_place_content_window(root, &root->content->dims); ui__call_layout_proc(root->content); } } @@ -137,18 +133,18 @@ void ui__root_layout_proc(struct ui_window_base *base) void ui__root_set_content(struct ui_window_root *root, struct ui_window_base *window) { umps_assert(!window->parent); - umps_assert(!window->cwindow); umps_assert(!root->content); - window->cwindow = ui__root_place_content_window(root); + ui__root_place_content_window(root, &window->dims); root->content = window; window->parent = ui__cast(base, root); + + ui__call_layout_proc(window); } void ui__root_set_floating(struct ui_window_root *root, struct ui_window_base *window) { umps_assert(!window->parent); - umps_assert(!window->cwindow); umps_assert(!root->floating); diff --git a/src/ui/ui.internal.h b/src/ui/ui.internal.h index 161391f..946d57a 100644 --- a/src/ui/ui.internal.h +++ b/src/ui/ui.internal.h @@ -17,8 +17,9 @@ #define UI__WINDOW_FOCUS_NONE (999u) #define UI__WINDOW_TYPE_BASE (0u) -#define UI__WINDOW_TYPE_DOCK (1u) -#define UI__WINDOW_TYPE_ROOT (2u) +#define UI__WINDOW_TYPE_LEAF (1u) +#define UI__WINDOW_TYPE_DOCK (2u) +#define UI__WINDOW_TYPE_ROOT (3u) #define UI__WINDOW_DOCK_MAX UI__WINDOW_DOCK_CENTER+1 @@ -28,6 +29,7 @@ #define ui__cast(_t, _v) (ui__check_cast_to_ ## _t(_v)) struct ui_window_base *ui__check_cast_to_base(void *); +struct ui_window_leaf *ui__check_cast_to_leaf(void *); struct ui_window_dock *ui__check_cast_to_dock(void *); struct ui_window_root *ui__check_cast_to_root(void *); #endif @@ -43,12 +45,21 @@ typedef void (ui__layout_proc)(struct ui_window_base *); struct ui_window_base { unsigned type; struct ui_window_base *parent; /* the parent of a window manages its memory */ - WINDOW *cwindow; /* ncurses window */ + struct ui_dims { + int maxy, maxx; + int begy, begx; + } dims; ui__draw_proc *draw_proc; ui__layout_proc *layout_proc; }; +struct ui_window_leaf { + struct ui_window_base super; + + WINDOW *cwindow; +}; + struct ui_window_dock { struct ui_window_base super; @@ -60,6 +71,8 @@ struct ui_window_dock { struct ui_window_root { struct ui_window_base super; + WINDOW *cwindow; + bool undersize_scr; struct ui_window_base *content; @@ -72,6 +85,7 @@ struct ui_window_root { /* in-place constructors */ void ui__init_window_base(struct ui_window_base *); +void ui__init_window_leaf(struct ui_window_leaf *); void ui__init_window_dock(struct ui_window_dock *); void ui__init_window_root(struct ui_window_root *, WINDOW *); |
