aboutsummaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorLibravatar bigfoot547 <[email protected]>2023-11-24 01:35:51 -0600
committerLibravatar bigfoot547 <[email protected]>2023-11-24 01:35:51 -0600
commit60e47519d3cd151348000d72811aa7037a01e3f4 (patch)
treefa408db8ee114277c8fac381fd1a683e32160508 /src/ui
parentcustom assert macros and other stuff (diff)
menu
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/base.c6
-rw-r--r--src/ui/dock.c8
-rw-r--r--src/ui/menu.c118
-rw-r--r--src/ui/root.c45
-rw-r--r--src/ui/ui.internal.h3
-rw-r--r--src/ui/uimenu.internal.h51
6 files changed, 220 insertions, 11 deletions
diff --git a/src/ui/base.c b/src/ui/base.c
index f251a3a..d914acf 100644
--- a/src/ui/base.c
+++ b/src/ui/base.c
@@ -3,6 +3,7 @@
#include <string.h>
#include "ui.internal.h"
+#include "ui/uimenu.internal.h"
struct ui_window_root *ui_root = NULL;
@@ -47,6 +48,9 @@ void ui__init_window_root(struct ui_window_root *root, WINDOW *cwindow)
root->undersize_scr = false;
root->content = NULL;
root->floating = NULL;
+
+ root->menu_root = malloc(sizeof(struct uimenu_item_menu));
+ uimenu_item_menu_init(root->menu_root, NULL);
}
/* type-specific destructors */
@@ -61,6 +65,8 @@ void ui__window_destroy_root(struct ui_window_root *root)
if (root->floating)
ui__destroy_window(root->floating);
+ uimenu_menu_free(root->menu_root);
+
ui__destroy_window_base(&root->super);
}
diff --git a/src/ui/dock.c b/src/ui/dock.c
index 178127f..fd895c2 100644
--- a/src/ui/dock.c
+++ b/src/ui/dock.c
@@ -141,8 +141,14 @@ 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 = 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);
+ }
- wrefresh(dock->super.cwindow);
+ wnoutrefresh(dock->super.cwindow);
for (unsigned i = 0; i < UI__WINDOW_DOCK_MAX; ++i)
{
if (dock->children[i])
diff --git a/src/ui/menu.c b/src/ui/menu.c
new file mode 100644
index 0000000..c0e8d58
--- /dev/null
+++ b/src/ui/menu.c
@@ -0,0 +1,118 @@
+#include <string.h>
+#include <stdlib.h>
+
+#include "uimenu.internal.h"
+#include "../macros.h"
+
+void uimenu_item_button_init(struct uimenu_item_button *button, unsigned id, const char *text, uimenu_button_action *action)
+{
+ button->header.type = UMPS__MENU_TYPE_BUTTON;
+ button->header.next = button->header.prev = NULL;
+
+ button->id = id;
+ button->text = text ? strdup(text) : NULL;
+ button->enabled = true;
+ button->action = action;
+}
+
+void uimenu_item_menu_init(struct uimenu_item_menu *menu, const char *text)
+{
+ menu->header.type = UMPS__MENU_TYPE_MENU;
+ menu->header.next = menu->header.prev = NULL;
+
+ menu->text = text ? strdup(text) : NULL;
+ menu->head = menu->tail = NULL;
+ menu->nchildren = 0;
+}
+
+struct uimenu_item_header *uimenu__item_menu_spacer_create(void)
+{
+ struct uimenu_item_header *spacer = malloc(sizeof(struct uimenu_item_header));
+ spacer->type = UMPS__MENU_TYPE_SPACER;
+ spacer->next = spacer->prev = NULL;
+ return spacer;
+}
+
+/* menu items will be freed on removal */
+void uimenu_menu_add_spacer(struct uimenu_item_menu *menu, struct uimenu_item_header *where, bool after)
+{
+ struct uimenu_item_header *spc = uimenu__item_menu_spacer_create();
+ uimenu_menu_add(menu, where, spc, after);
+}
+
+void uimenu_menu_add(struct uimenu_item_menu *menu, struct uimenu_item_header *where, struct uimenu_item_header *item, bool after)
+{
+ if (!menu->head) {
+ /* edge case: menu has no children :((((( */
+ menu->head = menu->tail = item;
+ item->next = item->prev = NULL;
+ ++menu->nchildren;
+ return;
+ }
+
+ umps_assert(where);
+
+ if (after) {
+ item->prev = where;
+ item->next = where->next;
+ where->next = item;
+
+ if (!item->next) menu->tail = item;
+ } else {
+ item->next = where;
+ item->prev = where->prev;
+ where->prev = item;
+
+ if (!item->prev) menu->head = item;
+ }
+
+ ++menu->nchildren;
+}
+
+void uimenu__item_free(struct uimenu_item_header *item)
+{
+ switch (item->type) {
+ case UMPS__MENU_TYPE_SPACER:
+ free(item);
+ break;
+ case UMPS__MENU_TYPE_BUTTON: {
+ struct uimenu_item_button *btn = (struct uimenu_item_button *)item;
+ free(btn->text);
+ free(btn);
+ break;
+ }
+ case UMPS__MENU_TYPE_MENU:
+ uimenu_menu_free((struct uimenu_item_menu *)item);
+ break;
+ default:
+ umps_trap;
+ }
+}
+
+void uimenu_menu_remove(struct uimenu_item_menu *menu, struct uimenu_item_header *item)
+{
+ if (item->prev) {
+ item->prev->next = item->next;
+ } else {
+ menu->head = item->next;
+ }
+
+ if (item->next) {
+ item->next->prev = item->prev;
+ } else {
+ menu->tail = item->prev;
+ }
+
+ --menu->nchildren;
+}
+
+/* frees children */
+void uimenu_menu_free(struct uimenu_item_menu *menu)
+{
+ for (struct uimenu_item_header *cur = menu->head, *next; cur; cur = next) {
+ next = cur->next;
+ uimenu__item_free(cur);
+ }
+ free(menu->text);
+ free(menu);
+}
diff --git a/src/ui/root.c b/src/ui/root.c
index 7ef536f..c3f7468 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -1,5 +1,6 @@
#include "ui.internal.h"
#include "macros.h"
+#include <curses.h>
#define UI__ROOT_MIN_Y (24)
#define UI__ROOT_MIN_X (80)
@@ -13,7 +14,7 @@
#define UI__ROOT_MARGIN_LEFT (0)
#define UI__ROOT_MARGIN_RIGHT (0)
-const char *ui__status_text = NULL;
+const char *ui__status_text = "Ready";
WINDOW *ui__root_place_content_window(struct ui_window_root *root)
{
@@ -31,6 +32,9 @@ WINDOW *ui__root_place_content_window(struct ui_window_root *root)
return newwin(maxy, maxx, begy, begx);
}
+void ui__root_draw_menu(struct ui_window_root *root);
+void ui__root_draw_status(struct ui_window_root *root);
+
void ui__root_draw_proc(struct ui_window_base *base)
{
struct ui_window_root *root = ui__cast(root, base);
@@ -47,15 +51,8 @@ void ui__root_draw_proc(struct ui_window_base *base)
return;
}
- 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);
+ ui__root_draw_menu(root);
+ ui__root_draw_status(root);
wnoutrefresh(base->cwindow);
@@ -70,6 +67,29 @@ void ui__root_draw_proc(struct ui_window_base *base)
doupdate();
}
+void ui__root_draw_menu(struct ui_window_root *root)
+{
+ WINDOW *mywin = root->super.cwindow;
+ attron(A_REVERSE);
+ mvwhline(mywin, 0, 0, ' ', getmaxx(mywin));
+ mvwaddstr(mywin, 0, 0, " UMPS v0.1.0-dev File Edit Filters Window Help");
+ attroff(A_REVERSE);
+}
+
+void ui__root_draw_status(struct ui_window_root *root)
+{
+ WINDOW *mywin = root->super.cwindow;
+
+ attron(A_REVERSE);
+ mvwhline(mywin, getmaxy(mywin)-1, 0, ' ', getmaxx(mywin));
+
+ if (ui__status_text) {
+ mvwaddstr(mywin, getmaxy(mywin)-1, 1, ui__status_text);
+ }
+
+ attroff(A_REVERSE);
+}
+
void ui__root_layout_proc(struct ui_window_base *base)
{
struct ui_window_root *root = ui__cast(root, base);
@@ -104,4 +124,9 @@ void ui__root_set_content(struct ui_window_root *root, struct ui_window_base *wi
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 b570654..161391f 100644
--- a/src/ui/ui.internal.h
+++ b/src/ui/ui.internal.h
@@ -2,6 +2,7 @@
#define UMPS_UI_INTERNAL_H_INCLUDED
#include "../ui.h"
+#include "uimenu.internal.h"
#include "config.h"
#include NCURSES_INCLUDE
@@ -63,6 +64,8 @@ struct ui_window_root {
struct ui_window_base *content;
struct ui_window_base *floating;
+
+ struct uimenu_item_menu *menu_root;
};
/* internal utils */
diff --git a/src/ui/uimenu.internal.h b/src/ui/uimenu.internal.h
new file mode 100644
index 0000000..82360f5
--- /dev/null
+++ b/src/ui/uimenu.internal.h
@@ -0,0 +1,51 @@
+#ifndef UMPS_UIMENU_INTERNAL_H_INCLUDED
+#define UMPS_UIMENU_INTERNAL_H_INCLUDED
+
+#include <stdbool.h>
+
+#define UMPS__MENU_TYPE_SPACER (0)
+#define UMPS__MENU_TYPE_BUTTON (1)
+#define UMPS__MENU_TYPE_MENU (2)
+
+/* this header is right out of a university data structures slide deck */
+
+struct uimenu_item_header {
+ unsigned type;
+ struct uimenu_item_header *next, *prev;
+};
+
+struct uimenu_item_button;
+
+typedef void (uimenu_button_action)(struct uimenu_item_button *);
+
+struct uimenu_item_button {
+ struct uimenu_item_header header;
+ unsigned id;
+ char *text;
+
+ uimenu_button_action *action;
+
+ bool enabled;
+};
+
+struct uimenu_item_menu {
+ struct uimenu_item_header header;
+ char *text;
+
+ struct uimenu_item_header *head, *tail;
+ unsigned nchildren;
+};
+
+void uimenu_item_button_init(struct uimenu_item_button *button, unsigned id, const char *text, uimenu_button_action *action);
+void uimenu_item_menu_init(struct uimenu_item_menu *menu, const char *text);
+
+/* menu items will be freed on removal */
+void uimenu_menu_add_spacer(struct uimenu_item_menu *menu, struct uimenu_item_header *where, bool after);
+void uimenu_menu_add(struct uimenu_item_menu *menu, struct uimenu_item_header *where, struct uimenu_item_header *item, bool after);
+
+void uimenu_menu_remove(struct uimenu_item_menu *menu, struct uimenu_item_header *item);
+
+/* frees children */
+void uimenu_menu_free(struct uimenu_item_menu *menu);
+
+#endif /* include guard */