diff options
| author | 2023-11-17 03:29:48 -0600 | |
|---|---|---|
| committer | 2023-11-17 03:29:48 -0600 | |
| commit | 9d3ff8760367833173ef1a784870be19196dac74 (patch) | |
| tree | 86bf972d3fb9e1f9f4a2a14b7ccf2f8e5a209d36 | |
| parent | initial commit (diff) | |
the root window is now no longer a dock
status bar and stuff
TODO: check ncurses calls that can failgit add --all!
| -rw-r--r-- | meson.options | 3 | ||||
| -rw-r--r-- | src/meson.build | 2 | ||||
| -rw-r--r-- | src/ui/base.c | 76 | ||||
| -rw-r--r-- | src/ui/debug.c | 26 | ||||
| -rw-r--r-- | src/ui/dock.c | 23 | ||||
| -rw-r--r-- | src/ui/root.c | 79 | ||||
| -rw-r--r-- | src/ui/ui.internal.h | 21 |
7 files changed, 177 insertions, 53 deletions
diff --git a/meson.options b/meson.options index 0a36339..6031bee 100644 --- a/meson.options +++ b/meson.options @@ -1,2 +1 @@ -option('ncurses_wide', type : 'boolean', value : false, - description : 'set to true to prevent usage of ncursesw') +option('ncurses_narrow', type : 'boolean', value : false, description : 'set to true to prevent usage of ncursesw') diff --git a/src/meson.build b/src/meson.build index d90d7c1..14e6269 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,4 +1,4 @@ -umps_srcs = files('main.c', 'ui/base.c', 'ui/dock.c') +umps_srcs = files('main.c', 'ui/base.c', 'ui/dock.c', 'ui/root.c', 'ui/debug.c') configure_file(input : 'config.h.in', output : 'config.h', configuration : conf_data) umps_config_inc = include_directories('.') diff --git a/src/ui/base.c b/src/ui/base.c index 74855b1..5607f4e 100644 --- a/src/ui/base.c +++ b/src/ui/base.c @@ -8,8 +8,7 @@ struct ui_window_root *ui_root = NULL; void ui__default_draw_proc(struct ui_window_base *base) { - redrawwin(base->cwindow); - wrefresh(base->cwindow); + wnoutrefresh(base->cwindow); /* root window calls doupdate */ } void ui__init_window_base(struct ui_window_base *base) @@ -37,13 +36,15 @@ void ui__init_window_dock(struct ui_window_dock *dock) dock->focus = UI__WINDOW_FOCUS_NONE; } -void ui__init_window_root(struct ui_window_root *root) +void ui__init_window_root(struct ui_window_root *root, WINDOW *cwindow) { - ui__init_window_dock(&root->super); - root->super.super.type = UI__WINDOW_TYPE_ROOT; - root->super.super.draw_proc = &ui__root_draw_proc; - root->super.super.layout_proc = &ui__root_layout_proc; + 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->content = NULL; root->floating = NULL; } @@ -53,10 +54,13 @@ void ui__destroy_window_dock(struct ui_window_dock *dock); void ui__window_destroy_root(struct ui_window_root *root) { + if (root->content) + ui__destroy_window(root->content); + if (root->floating) ui__destroy_window(root->floating); - ui__destroy_window_dock(&root->super); + ui__destroy_window_base(&root->super); } void ui__destroy_window_dock(struct ui_window_dock *dock) @@ -83,10 +87,10 @@ void ui__destroy_window(struct ui_window_base *base) switch (base->type) { case UI__WINDOW_TYPE_ROOT: - ui__window_destroy_root((struct ui_window_root *)base); + ui__window_destroy_root(ui__cast(root, base)); break; case UI__WINDOW_TYPE_DOCK: - ui__destroy_window_dock((struct ui_window_dock *)base); + ui__destroy_window_dock(ui__cast(dock, base)); break; case UI__WINDOW_TYPE_BASE: ui__destroy_window_base(base); @@ -98,17 +102,25 @@ void ui__destroy_window(struct ui_window_base *base) * which brings it to the "foreground", squashing whatever is behind it. */ struct ui_window_base *ui__find_focused(void) { - struct ui_window_base *window = (struct ui_window_base *)ui_root; - if (ui_root->floating) return ui_root->floating; + struct ui_window_base *window = ui__cast(base, ui_root); - while (true) - { - switch (window->type) - { - case UI__WINDOW_TYPE_DOCK: + while (true) { + switch (window->type) { case UI__WINDOW_TYPE_ROOT: { - struct ui_window_dock *dock = (struct ui_window_dock *)window; + struct ui_window_root *root = ui__cast(root, window); + if (root->floating) { + window = root->floating; + } else if (root->content) { + window = root->content; + } else { + return window; + } + break; + } + case UI__WINDOW_TYPE_DOCK: + { + struct ui_window_dock *dock = ui__cast(dock, window); if (dock->focus == UI__WINDOW_FOCUS_NONE || !dock->children[dock->focus]) { @@ -121,7 +133,7 @@ struct ui_window_base *ui__find_focused(void) } } - return (struct ui_window_base *)dock; /* the dock is focused if it is really a leaf */ + return window; /* the dock is focused if it is really a leaf */ } childfound: @@ -159,10 +171,9 @@ void ui__traces_draw_proc(struct ui_window_base *base) getmaxyx(base->cwindow, maxy, maxx); for (int i = 1; i < maxy-1; ++i) { - mvwhline(base->cwindow, i, 1, '%', maxx-2); + mvwhline(base->cwindow, i, 1, '.', maxx-2); } - touchwin(base->cwindow); - wrefresh(base->cwindow); + wnoutrefresh(base->cwindow); } void ui_init(void) @@ -178,21 +189,24 @@ void ui_init(void) curs_set(0); - ui__init_window_root(ui_root); - ui_root->super.super.cwindow = stdscr; /* initialize the ncurses window ourselves */ + ui__init_window_root(ui_root, stdscr); /* set up UI */ + struct ui_window_dock *maindock = malloc(sizeof(struct ui_window_dock)); + ui__init_window_dock(maindock); + ui__root_set_content(ui_root, ui__cast(base, maindock)); + for (int 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((struct ui_window_dock *)ui_root, win_traces, i, 1./5); + ui__dock_add_child(maindock, win_traces, i, 1./5); win_traces->draw_proc = &ui__traces_draw_proc; } - ui__call_draw_proc((struct ui_window_base *)ui_root); + ui__call_draw_proc(ui__cast(base, ui_root)); } void ui_handle(void) @@ -214,8 +228,14 @@ void ui_handle(void) } else if (inp == KEY_RESIZE) { - ui__call_layout_proc((struct ui_window_base *)ui_root); - ui__call_draw_proc((struct ui_window_base *)ui_root); + ui__call_layout_proc(ui__cast(base, ui_root)); + ui__call_draw_proc(ui__cast(base, ui_root)); + } else if (inp == NS('h')) { + ui__status_text = "Hello..."; + ui__call_draw_proc(ui__cast(base, ui_root)); + } else if (inp == NS('w')) { + ui__status_text = "World!"; + ui__call_draw_proc(ui__cast(base, ui_root)); } } diff --git a/src/ui/debug.c b/src/ui/debug.c new file mode 100644 index 0000000..d4f2e94 --- /dev/null +++ b/src/ui/debug.c @@ -0,0 +1,26 @@ +#ifndef NDEBUG + +#include <assert.h> + +#include "ui.internal.h" + +struct ui_window_base *ui__check_cast_to_base(void *obj) +{ + return obj; /* this cast always succeeds */ +} + +struct ui_window_dock *ui__check_cast_to_dock(void *obj) +{ + struct ui_window_base *base = obj; + 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); + return obj; +} + +#endif diff --git a/src/ui/dock.c b/src/ui/dock.c index 5b59b71..54c9fe9 100644 --- a/src/ui/dock.c +++ b/src/ui/dock.c @@ -16,7 +16,7 @@ unsigned ui__dock_position_opposite(unsigned position) case UI__WINDOW_DOCK_RIGHT: return UI__WINDOW_DOCK_LEFT; default: - assert(false); /* trap: this function should never be called here! */ + assert(false); /* trap: the center dock has no opposite! (or position is invalid) */ } } @@ -139,7 +139,7 @@ void ui__dock_add_child(struct ui_window_dock *dock, struct ui_window_base *chil void ui__dock_default_draw_proc(struct ui_window_base *base) { - struct ui_window_dock *dock = (struct ui_window_dock *)base; + struct ui_window_dock *dock = ui__cast(dock, base); wrefresh(dock->super.cwindow); for (unsigned i = 0; i < UI__WINDOW_DOCK_MAX; ++i) @@ -151,7 +151,7 @@ void ui__dock_default_draw_proc(struct ui_window_base *base) void ui__dock_default_layout_proc(struct ui_window_base *base) { - struct ui_window_dock *dock = (struct ui_window_dock *)base; + struct ui_window_dock *dock = ui__cast(dock, base); /* fix the layout of children */ for (unsigned i = 0; i < UI__WINDOW_DOCK_MAX; ++i) @@ -164,20 +164,3 @@ void ui__dock_default_layout_proc(struct ui_window_base *base) ui__call_layout_proc(child); } } - -void ui__root_draw_proc(struct ui_window_base *base) -{ - struct ui_window_root *root = (struct ui_window_root *)base; - ui__dock_default_draw_proc(base); - - if (root->floating) ui__call_draw_proc(root->floating); -} - -void ui__root_layout_proc(struct ui_window_base *base) -{ - struct ui_window_root *root = (struct ui_window_root *)base; - ui__dock_default_layout_proc(base); - - /* TODO: adjust floating window position :) */ - if (root->floating) ui__call_layout_proc(root->floating); -} diff --git a/src/ui/root.c b/src/ui/root.c new file mode 100644 index 0000000..26ca0ac --- /dev/null +++ b/src/ui/root.c @@ -0,0 +1,79 @@ +#include <assert.h> + +#include "ui.internal.h" + +/* top margin for menu bar */ +#define UI__ROOT_MARGIN_TOP (1) + +/* bottom margin for status bar */ +#define UI__ROOT_MARGIN_BOTTOM (1) + +#define UI__ROOT_MARGIN_LEFT (0) +#define UI__ROOT_MARGIN_RIGHT (0) + +const char *ui__status_text = NULL; + +WINDOW *ui__root_place_content_window(struct ui_window_root *root) +{ + 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; + + begx += UI__ROOT_MARGIN_LEFT; + begx -= UI__ROOT_MARGIN_LEFT + UI__ROOT_MARGIN_RIGHT; + + return newwin(maxy, maxx, begy, begx); +} + +void ui__root_draw_proc(struct ui_window_base *base) +{ + struct ui_window_root *root = ui__cast(root, base); + + attron(A_REVERSE); + mvwhline(base->cwindow, 0, 0, ' ', getmaxx(base->cwindow)); + mvwhline(base->cwindow, getmaxy(base->cwindow)-1, 0, ' ', getmaxx(base->cwindow)); + + if (ui__status_text) { + mvwprintw(base->cwindow, getmaxy(base->cwindow)-1, 1, "Status: %s", ui__status_text); + } + + attroff(A_REVERSE); + + wnoutrefresh(base->cwindow); + + if (root->content) { + ui__call_draw_proc(root->content); + } + + if (root->floating) { + ui__call_draw_proc(root->floating); + } + + doupdate(); +} + +void ui__root_layout_proc(struct ui_window_base *base) +{ + struct ui_window_root *root = ui__cast(root, base); + + if (root->content) { + delwin(root->content->cwindow); + root->content->cwindow = ui__root_place_content_window(root); + ui__call_layout_proc(root->content); + } +} + +void ui__root_set_content(struct ui_window_root *root, struct ui_window_base *window) +{ + assert(!window->parent); + assert(!window->cwindow); + assert(!root->content); + + window->cwindow = ui__root_place_content_window(root); + root->content = window; + window->parent = ui__cast(base, root); +} diff --git a/src/ui/ui.internal.h b/src/ui/ui.internal.h index 7c53bd4..6107c94 100644 --- a/src/ui/ui.internal.h +++ b/src/ui/ui.internal.h @@ -19,6 +19,16 @@ #define UI__WINDOW_DOCK_MAX UI__WINDOW_DOCK_CENTER+1 +#ifdef NDEBUG +#define ui__cast(_t, _v) ((struct ui_window_ ## _t *)(_v)) +#else +#define ui__cast(_t, _v) (ui__check_cast_to_ ## _t(_v)) + +struct ui_window_base *ui__check_cast_to_base(void *); +struct ui_window_dock *ui__check_cast_to_dock(void *); +struct ui_window_root *ui__check_cast_to_root(void *); +#endif + /* concrete type definitions */ /* called to refresh the window (should refresh children as well) */ @@ -46,8 +56,9 @@ struct ui_window_dock { }; struct ui_window_root { - struct ui_window_dock super; + struct ui_window_base super; + struct ui_window_base *content; struct ui_window_base *floating; }; @@ -56,7 +67,7 @@ struct ui_window_root { /* in-place constructors */ void ui__init_window_base(struct ui_window_base *); void ui__init_window_dock(struct ui_window_dock *); -void ui__init_window_root(struct ui_window_root *); +void ui__init_window_root(struct ui_window_root *, WINDOW *); struct ui_window_base *ui__find_focused(void); @@ -78,4 +89,10 @@ void ui__dock_default_layout_proc(struct ui_window_base *base); void ui__root_draw_proc(struct ui_window_base *); void ui__root_layout_proc(struct ui_window_base *); +/* root_window_utilities */ + +void ui__root_set_content(struct ui_window_root *, struct ui_window_base *); + +extern const char *ui__status_text; + #endif /* include guard */ |
