aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ui/base.c90
-rw-r--r--src/ui/dock.c12
-rw-r--r--src/ui/root.c81
-rw-r--r--src/ui/ui.internal.h21
4 files changed, 179 insertions, 25 deletions
diff --git a/src/ui/base.c b/src/ui/base.c
index dd454ec..0db31b3 100644
--- a/src/ui/base.c
+++ b/src/ui/base.c
@@ -47,6 +47,7 @@ void ui__init_window_base(struct ui_window_base *base)
base->draw_proc = &ui__default_draw_proc;
base->layout_proc = NULL;
+ base->control_proc = NULL;
}
void ui__init_window_leaf(struct ui_window_leaf *leaf)
@@ -65,6 +66,7 @@ void ui__init_window_dock(struct ui_window_dock *dock)
dock->super.type = UI__WINDOW_TYPE_DOCK;
dock->super.draw_proc = &ui__dock_default_draw_proc;
dock->super.layout_proc = &ui__dock_default_layout_proc;
+ dock->super.control_proc = &ui__dock_default_control_proc;
for (unsigned i = 0; i < UI__WINDOW_DOCK_MAX; ++i)
{
@@ -81,14 +83,19 @@ void ui__init_window_root(struct ui_window_root *root, WINDOW *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->super.control_proc = &ui__root_control_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->menu_cwindow = newwin(1, root->super.dims.maxx, 0, 0);
+ root->menu_selected = NULL;
+
root->undersize_scr = false;
root->content = NULL;
root->floating = NULL;
+ root->modal = NULL;
root->menu_root = malloc(sizeof(struct uimenu_item_menu));
uimenu_item_menu_init(root->menu_root, NULL);
@@ -207,6 +214,55 @@ childfound:
}
}
+WINDOW *ui__find_focused_leaf(struct ui_window_base *start)
+{
+ switch (start->type) {
+ case UI__WINDOW_TYPE_LEAF:
+ return ui__cast(leaf, start)->cwindow;
+ case UI__WINDOW_TYPE_DOCK: {
+ struct ui_window_dock *dock = ui__cast(dock, start);
+
+ for (unsigned i = 0; i < UI__WINDOW_DOCK_MAX; ++i) {
+ if (dock->children[i]) {
+ WINDOW *focus = ui__find_focused_leaf(dock->children[i]);
+ if (focus) return focus;
+ }
+ }
+
+ return NULL;
+ }
+ case UI__WINDOW_TYPE_ROOT: {
+ struct ui_window_root *root = ui__cast(root, start);
+ WINDOW *focus;
+
+ if (root->undersize_scr)
+ return root->cwindow; /* gobble up focus if the screen is undersize */
+
+ if (root->modal) {
+ focus = ui__find_focused_leaf(root->modal);
+ if (focus) return focus;
+ }
+
+ if (root->floating) {
+ focus = ui__find_focused_leaf(root->modal);
+ if (focus) return focus;
+ }
+
+ if (root->menu_selected) {
+ return root->menu_cwindow;
+ }
+
+ if (root->content) {
+ return ui__find_focused_leaf(root->content);
+ }
+
+ return NULL;
+ }
+ default:
+ umps_trap;
+ }
+}
+
void ui__call_draw_proc(struct ui_window_base *base)
{
if (base->draw_proc)
@@ -223,6 +279,16 @@ void ui__call_layout_proc(struct ui_window_base *base)
}
}
+struct ui_window_base *ui__call_control_proc(struct ui_window_base *base, ui_control inp)
+{
+ if (base->control_proc)
+ {
+ return (*base->control_proc)(base, inp);
+ }
+
+ return NULL;
+}
+
void ui_init(void)
{
ui_root = malloc(sizeof(struct ui_window_root)); /* TODO: check */
@@ -267,17 +333,18 @@ void ui_handle(void)
{
while (true)
{
- struct ui_window_base *window = ui__find_focused();
+ WINDOW *cwindow = ui__find_focused_leaf(ui__cast(base, ui_root));
+
+ ui_control inp;
#ifdef NCURSES_WIDE
- wint_t inp;
- /* FIXME: find a better way of circumnavigating this annoying implied-wrefresh business */
- wget_wch(ui__cast(leaf, window)->cwindow, &inp);
+ keypad(cwindow, TRUE);
+ wget_wch(cwindow, &inp);
#else
- int inp = wgetch(window->cwindow);
+ inp = wgetch(window->cwindow);
#endif
- if (inp == NS('q'))
+ if (inp == NS('q')) /* TODO: make quitting flag in ui_root */
{
break;
}
@@ -287,12 +354,11 @@ void ui_handle(void)
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')) {
- ui__status_text = "Hello...";
- ui__call_draw_proc(ui__cast(base, ui_root));
- } else if (inp == NS('w')) {
- ui__status_text = "World\u0416!";
- ui__call_draw_proc(ui__cast(base, ui_root));
+ }
+
+ struct ui_window_base *target = ui__cast(base, ui_root);
+ while (target) {
+ target = ui__call_control_proc(target, inp);
}
}
diff --git a/src/ui/dock.c b/src/ui/dock.c
index 82f6728..c0931ba 100644
--- a/src/ui/dock.c
+++ b/src/ui/dock.c
@@ -153,3 +153,15 @@ void ui__dock_default_layout_proc(struct ui_window_base *base)
ui__call_layout_proc(child);
}
}
+
+struct ui_window_base *ui__dock_default_control_proc(struct ui_window_base *base, ui_control inp)
+{
+ struct ui_window_dock *dock = ui__cast(dock, base);
+ umps_unused(inp);
+
+ if (dock->focus != UI__WINDOW_FOCUS_NONE && dock->children[dock->focus]) {
+ return dock->children[dock->focus];
+ }
+
+ return NULL; /* no focus */
+}
diff --git a/src/ui/root.c b/src/ui/root.c
index 00eda14..6846d45 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -1,6 +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)
@@ -51,6 +52,7 @@ void ui__root_draw_proc(struct ui_window_base *base)
ui__root_draw_status(root);
wnoutrefresh(root->cwindow);
+ wnoutrefresh(root->menu_cwindow);
if (root->content) {
ui__call_draw_proc(root->content);
@@ -65,17 +67,18 @@ void ui__root_draw_proc(struct ui_window_base *base)
void ui__root_draw_menu(struct ui_window_root *root)
{
- WINDOW *mywin = root->cwindow;
- attron(A_REVERSE);
- mvwhline(mywin, 0, 0, ' ', getmaxx(mywin));
- mvwaddstr(mywin, 0, 0, " UMPS v0.1.0-dev");
+ wattron(root->menu_cwindow, A_REVERSE);
+ mvwhline(root->menu_cwindow, 0, 0, ' ', getmaxx(root->menu_cwindow));
+ mvwaddstr(root->menu_cwindow, 0, 0, " UMPS v0.1.0-dev");
char *text;
- for (struct uimenu_item_header *item = root->menu_root->head; item; item = item->next) {
- waddstr(mywin, " ");
+ int idx = 0;
+ for (struct uimenu_item_header *item = root->menu_root->head; item; item = item->next, ++idx) {
+ waddstr(root->menu_cwindow, " ");
+
switch (item->type) {
case UMPS__MENU_TYPE_SPACER:
- waddstr(mywin, "--");
+ waddstr(root->menu_cwindow, "--");
continue;
case UMPS__MENU_TYPE_BUTTON:
text = ((struct uimenu_item_button *)item)->text;
@@ -87,11 +90,23 @@ void ui__root_draw_menu(struct ui_window_root *root)
umps_trap;
}
- if (text) waddstr(mywin, text);
- else waddstr(mywin, "???");
+ if (item == root->menu_selected)
+ wattroff(root->menu_cwindow, A_REVERSE);
+
+ if (text) waddstr(root->menu_cwindow, text);
+ else waddstr(root->menu_cwindow, "???");
+
+ wattron(root->menu_cwindow, A_REVERSE);
}
- attroff(A_REVERSE);
+ wattroff(root->menu_cwindow, A_REVERSE);
+}
+
+void ui__root_redraw_menu(struct ui_window_root *root)
+{
+ ui__root_draw_menu(root);
+ wnoutrefresh(root->menu_cwindow);
+ doupdate();
}
void ui__root_draw_status(struct ui_window_root *root)
@@ -117,6 +132,9 @@ void ui__root_layout_proc(struct ui_window_base *base)
root->cwindow = newwin(root->super.dims.maxy, root->super.dims.maxx, root->super.dims.begy, root->super.dims.begx);
}
+ delwin(root->menu_cwindow);
+ root->menu_cwindow = newwin(1, root->super.dims.maxx, 0, 0);
+
if (root->super.dims.maxy < UI__ROOT_MIN_Y || root->super.dims.maxx < UI__ROOT_MIN_X) {
root->undersize_scr = true;
return;
@@ -130,6 +148,49 @@ void ui__root_layout_proc(struct ui_window_base *base)
}
}
+struct ui_window_base *ui__root_control_proc(struct ui_window_base *base, ui_control inp)
+{
+ struct ui_window_root *root = ui__cast(root, base);
+
+ if (root->undersize_scr) return NULL;
+
+ switch (inp) {
+ case NS('h'):
+ ui__status_text = "Hello...";
+ ui__call_draw_proc(ui__cast(base, ui_root));
+ break;
+ case NS('w'):
+ ui__status_text = "World!";
+ ui__call_draw_proc(ui__cast(base, ui_root));
+ break;
+ case NS('m'):
+ if (root->menu_selected) {
+ root->menu_selected = NULL;
+ } else {
+ root->menu_selected = root->menu_root->head;
+ }
+ ui__root_redraw_menu(root);
+ return NULL;
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ if (root->menu_selected) {
+ struct uimenu_item_header *nxt = inp == KEY_RIGHT ? root->menu_selected->next : root->menu_selected->prev;
+ if (nxt) {
+ root->menu_selected = nxt;
+ ui__root_redraw_menu(root);
+ }
+ return NULL;
+ }
+ break;
+ }
+
+ if (root->menu_selected) {
+ return NULL;
+ } else {
+ return root->content;
+ }
+}
+
void ui__root_set_content(struct ui_window_root *root, struct ui_window_base *window)
{
umps_assert(!window->parent);
diff --git a/src/ui/ui.internal.h b/src/ui/ui.internal.h
index 201e61e..763f9a7 100644
--- a/src/ui/ui.internal.h
+++ b/src/ui/ui.internal.h
@@ -53,6 +53,14 @@ typedef void (ui__draw_proc)(struct ui_window_base *);
/* called to recalculate the layout of the window (for resize) */
typedef void (ui__layout_proc)(struct ui_window_base *);
+#ifdef NCURSES_WIDE
+typedef wint_t ui_control;
+#else
+typedef int ui_control;
+#endif
+
+typedef struct ui_window_base *(ui__control_proc)(struct ui_window_base *, ui_control);
+
struct ui_window_base {
unsigned type;
struct ui_window_base *parent; /* the parent of a window manages its memory */
@@ -63,6 +71,7 @@ struct ui_window_base {
ui__draw_proc *draw_proc;
ui__layout_proc *layout_proc;
+ ui__control_proc *control_proc;
};
struct ui_window_leaf {
@@ -82,12 +91,15 @@ struct ui_window_dock {
struct ui_window_root {
struct ui_window_base super;
- WINDOW *cwindow;
+ WINDOW *cwindow, *menu_cwindow;
+
+ struct uimenu_item_header *menu_selected;
bool undersize_scr;
- struct ui_window_base *content;
- struct ui_window_base *floating;
+ struct ui_window_base *content; /* content of the editor */
+ struct ui_window_base *floating; /* floating menu layer */
+ struct ui_window_base *modal; /* modal (dialog) layer */
struct uimenu_item_menu *menu_root;
};
@@ -115,13 +127,16 @@ void ui__destroy_window(struct ui_window_base *);
void ui__dock_add_child(struct ui_window_dock *, struct ui_window_base *, unsigned position, float size);
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_base *ui__dock_default_control_proc(struct ui_window_base *base, ui_control inp);
/* root window hooks */
void ui__root_draw_proc(struct ui_window_base *);
void ui__root_layout_proc(struct ui_window_base *);
+struct ui_window_base *ui__root_control_proc(struct ui_window_base *base, ui_control inp);
/* root_window_utilities */
+void ui__root_redraw_menu(struct ui_window_root *);
void ui__root_set_content(struct ui_window_root *, struct ui_window_base *);
extern const char *ui__status_text;