commit 7fe76c958f890df51545862337b8c669677d4a53
parent 724f53a36a61bc30c84d90a9d69babcd775bea4b
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Fri, 2 Sep 2022 01:59:26 +0200
Extract menu interface, hide border from widgets
Diffstat:
A | include/menu.h | | | 45 | +++++++++++++++++++++++++++++++++++++++++++++ |
M | include/pane.h | | | 46 | ++++++---------------------------------------- |
M | src/main.c | | | 3 | ++- |
A | src/menu.c | | | 121 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/pane.c | | | 154 | ++++++++++++++++++------------------------------------------------------------- |
5 files changed, 209 insertions(+), 160 deletions(-)
diff --git a/include/menu.h b/include/menu.h
@@ -0,0 +1,45 @@
+#ifndef MENU_H
+#define MENU_H
+
+#include "pane.h"
+
+typedef struct menu_T *menu_T;
+typedef struct menuItem_T *menuItem_T;
+typedef struct menuStyle_T *menuStyle_T;
+typedef struct menuInfo_T *menuInfo_T;
+
+struct menuItem_T {
+ void (*callback)(char *, int);
+ char *name;
+};
+
+struct menuStyle_T {
+ char *separator;
+ int padding;
+ int spacing;
+};
+
+struct menuInfo_T {
+ int start;
+ int end;
+
+ int y;
+ int x;
+ int x_sep;
+
+ int max_item_len;
+ int sep_len;
+ int items_num;
+};
+
+struct menu_T {
+ int current;
+
+ int items_size;
+ struct menuItem_T items[];
+};
+
+void pane_menu(widget_T widget);
+int menu_hadleInput(data_T data, struct tb_event ev);
+
+#endif
diff --git a/include/pane.h b/include/pane.h
@@ -13,9 +13,15 @@ int pane_resize(T self);
T pane_child(T self, int index);
+int pane_x(T self);
+int pane_y(T self);
+int pane_width(T self);
+int pane_height(T self);
+
T *pane_split(T self, size_t count, ...);
T *pane_vsplit(T self, size_t count, ...);
void pane_unsplit(T self);
+void pane_clear(T self, int clear_border);
void setActive(int direction);
void pane_setTitle(T self, char *title);
@@ -48,45 +54,5 @@ struct widget_T {
int widget_activate(widget_T self, Pane_T pane);
widget_T pane_widget(T self);
-/* MENU */
-
-typedef struct menu_T *menu_T;
-typedef struct menuItem_T *menuItem_T;
-typedef struct menuStyle_T *menuStyle_T;
-typedef struct menuInfo_T *menuInfo_T;
-
-struct menuItem_T {
- void (*callback)(char *, int);
- char *name;
-};
-
-struct menuStyle_T {
- char *separator;
- int padding;
- int spacing;
-};
-
-struct menuInfo_T {
- int start;
- int end;
-
- int y;
- int x;
- int x_sep;
-
- int max_item_len;
- int sep_len;
- int items_num;
-};
-
-struct menu_T {
- int current;
-
- int items_size;
- struct menuItem_T items[];
-};
-
-void pane_menu(widget_T widget);
-int menu_hadleInput(data_T data, struct tb_event ev);
#undef T
#endif
diff --git a/src/main.c b/src/main.c
@@ -5,6 +5,7 @@
#include "pane.h"
#include "utils.h"
+#include "menu.h"
extern Pane_T MAIN, ACTIVE;
@@ -80,7 +81,7 @@ void input_loop(void)
tb_poll_event(&ev);
switch (ev.type) {
case TB_EVENT_RESIZE:
- pane_handle_resize();
+ pane_handle_resize();
continue;
case TB_EVENT_KEY: {
widget_T widget;
diff --git a/src/menu.c b/src/menu.c
@@ -0,0 +1,121 @@
+#include "menu.h"
+#include "pane.h"
+#include "utils.h"
+
+int centerVertical(Pane_T pane, int len)
+{
+ return pane_y(pane) + (pane_height(pane) - len) / 2;
+}
+
+int centerHorisontal(Pane_T pane, int len)
+{
+ return pane_x(pane) + (pane_width(pane) - len - 2) / 2 + 1;
+}
+
+int menu_hadleInput(data_T data, struct tb_event ev)
+{
+ menu_T menu = (menu_T)data->payload;
+
+ if (ev.type == TB_EVENT_KEY) {
+ if (ev.ch == 'k' || ev.ch == 'w') {
+ menu->current--;
+ CLAMP(menu->current, 0, menu->items_size - 1);
+ return 1;
+ }
+ if (ev.ch == 'j' || ev.ch == 's') {
+ menu->current++;
+ CLAMP(menu->current, 0, menu->items_size - 1);
+ return 1;
+ }
+ if (ev.key == TB_KEY_ENTER) {
+ struct menuItem_T *item = menu->items + menu->current;
+ item->callback(item->name, menu->current);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void pane_menu(widget_T widget)
+{
+ size_t i;
+ Pane_T pane = widget->pane;
+ menuInfo_T info = (menuInfo_T)(widget->info);
+ menuStyle_T style = (menuStyle_T)(widget->style);
+ menu_T menu = (menu_T)(widget->data->payload);
+
+ if (!widget->inited) {
+ widget->inited = 1;
+ widget->resized = 1;
+
+ int len, maxi = 0;
+
+ for (i = 0; i < menu->items_size; i++)
+ if ((len = strlen(menu->items[i].name)) > maxi)
+ maxi = len;
+
+ info->max_item_len = maxi;
+ info->sep_len = strlen(style->separator);
+ info->start = 0;
+ info->end = info->items_num - 1;
+ }
+
+ if (widget->resized) {
+ widget->resized = 0;
+
+ int padding = (style->padding * 2 + 1 > pane_height(pane)) ?
+ 0 :
+ style->padding;
+ // optimal number of elements to display on the screen
+ int max_items =
+ (pane_height(pane) - padding * 2 + style->spacing - 2) /
+ (style->spacing + 1);
+ // number of items displayed cant exceed actual number of items in the menu
+ info->items_num = ACLAMP(max_items, 0, menu->items_size);
+
+ info->x_sep = centerHorisontal(pane, info->sep_len);
+ info->x = centerHorisontal(pane, info->max_item_len);
+ info->y = centerVertical(
+ pane, info->items_num * (style->spacing + 1) -
+ style->spacing);
+ }
+
+ /* while (1) { */
+ pane_clear(pane, 0);
+
+ int relative = menu->current - info->start;
+ if (relative < 0) {
+ info->start--;
+ info->end--;
+ } else if (relative > 0 && relative > info->end - info->start - 1) {
+ info->start++;
+ info->end++;
+ }
+
+ CLAMP(info->start, 0, menu->items_size - info->items_num);
+ CLAMP(info->end, info->items_num, menu->items_size);
+
+ if (!menu->items_size) {
+ char *message = "NOTHING TO DISPLAY HERE!";
+ int x = centerHorisontal(pane, strlen(message));
+ tb_print(x, info->y, TB_BLUE, 0, message);
+ return;
+ }
+
+ if (info->items_num != menu->items_size && info->start == 0)
+ tb_print(info->x_sep, info->y - 1, TB_BLUE, 0,
+ style->separator);
+
+ int y = info->y;
+ for (i = info->start; i < info->end; i++) {
+ int color = (i == menu->current) ? TB_RED : TB_BLUE;
+ tb_printf(info->x, y, color, 0, "%s", menu->items[i].name);
+ y += style->spacing + 1;
+ }
+
+ if (info->items_num != menu->items_size &&
+ info->end == menu->items_size)
+ tb_print(info->x_sep, y - style->spacing, TB_BLUE, 0,
+ style->separator);
+}
diff --git a/src/pane.c b/src/pane.c
@@ -30,6 +30,41 @@ struct T {
T parent;
};
+int pane_hasBorder(T self)
+{
+ return !self->children;
+}
+
+int pane_x(T self)
+{
+ if (pane_hasBorder(self))
+ return self->x + 1;
+ else
+ return self->x;
+}
+
+int pane_y(T self)
+{
+ if (pane_hasBorder(self))
+ return self->y + 1;
+ else
+ return self->y;
+}
+int pane_width(T self)
+{
+ if (pane_hasBorder(self))
+ return self->width - 2;
+ else
+ return self->width;
+}
+int pane_height(T self)
+{
+ if (pane_hasBorder(self))
+ return self->height - 2;
+ else
+ return self->height;
+}
+
#define UP(pane) pane->direction[0]
#define RIGHT(pane) pane->direction[1]
#define DOWN(pane) pane->direction[2]
@@ -357,16 +392,6 @@ void setActive(int dir)
tb_present();
}
-int centerVertical(T self, int len)
-{
- return self->y + (self->height - len) / 2;
-}
-
-int centerHorisontal(T self, int len)
-{
- return self->x + (self->width - len - 2) / 2 + 1;
-}
-
/* WIDGET */
int widget_activate(widget_T self, Pane_T pane)
@@ -384,112 +409,3 @@ int widget_activate(widget_T self, Pane_T pane)
return 1;
}
-
-/* MENU DISPLAY */
-
-int menu_hadleInput(data_T data, struct tb_event ev)
-{
- menu_T menu = (menu_T)data->payload;
-
- if (ev.type == TB_EVENT_KEY) {
- if (ev.ch == 'k' || ev.ch == 'w') {
- menu->current--;
- CLAMP(menu->current, 0, menu->items_size - 1);
- return 1;
- }
- if (ev.ch == 'j' || ev.ch == 's') {
- menu->current++;
- CLAMP(menu->current, 0, menu->items_size - 1);
- return 1;
- }
- if (ev.key == TB_KEY_ENTER) {
- struct menuItem_T *item = menu->items + menu->current;
- item->callback(item->name, menu->current);
- return 1;
- }
- }
-
- return 0;
-}
-
-void pane_menu(widget_T widget)
-{
- size_t i;
- Pane_T pane = widget->pane;
- menuInfo_T info = (menuInfo_T)(widget->info);
- menuStyle_T style = (menuStyle_T)(widget->style);
- menu_T menu = (menu_T)(widget->data->payload);
-
- if (!widget->inited) {
- widget->inited = 1;
- widget->resized = 1;
-
- int len, maxi = 0;
-
- for (i = 0; i < menu->items_size; i++)
- if ((len = strlen(menu->items[i].name)) > maxi)
- maxi = len;
-
- info->max_item_len = maxi;
- info->sep_len = strlen(style->separator);
- info->start = 0;
- info->end = info->items_num - 1;
- }
-
- if (widget->resized) {
- widget->resized = 0;
-
- int padding = (style->padding * 2 + 1 > pane->height) ?
- 0 :
- style->padding;
- // optimal number of elements to display on the screen
- int max_items = (pane->height - padding * 2 + style->spacing) /
- (style->spacing + 1);
- // number of items displayed cant exceed actual number of items in the menu
- info->items_num = ACLAMP(max_items, 0, menu->items_size);
-
- info->x_sep = centerHorisontal(pane, info->sep_len);
- info->x = centerHorisontal(pane, info->max_item_len);
- info->y = centerVertical(
- pane, info->items_num * (style->spacing + 1) -
- style->spacing);
- }
-
- /* while (1) { */
- pane_clear(pane, 0);
-
- int relative = menu->current - info->start;
- if (relative < 0) {
- info->start--;
- info->end--;
- } else if (relative > 0 && relative > info->end - info->start - 1) {
- info->start++;
- info->end++;
- }
-
- CLAMP(info->start, 0, menu->items_size - info->items_num);
- CLAMP(info->end, info->items_num, menu->items_size);
-
- if (!menu->items_size) {
- char *message = "NOTHING TO DISPLAY HERE!";
- int x = centerHorisontal(pane, strlen(message));
- tb_print(x, info->y, TB_BLUE, 0, message);
- return;
- }
-
- if (info->items_num != menu->items_size && info->start == 0)
- tb_print(info->x_sep, info->y - 1, TB_BLUE, 0,
- style->separator);
-
- int y = info->y;
- for (i = info->start; i < info->end; i++) {
- int color = (i == menu->current) ? TB_RED : TB_BLUE;
- tb_printf(info->x, y, color, 0, "%s", menu->items[i].name);
- y += style->spacing + 1;
- }
-
- if (info->items_num != menu->items_size &&
- info->end == menu->items_size)
- tb_print(info->x_sep, y - style->spacing, TB_BLUE, 0,
- style->separator);
-}