commit 2d45bf507eaa7814eb4bf765d1970c8c6f8ee5d4
parent 7fe76c958f890df51545862337b8c669677d4a53
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Thu, 8 Sep 2022 12:21:24 +0200
Streamlining interface and general improvements
Diffstat:
6 files changed, 232 insertions(+), 105 deletions(-)
diff --git a/Makefile b/Makefile
@@ -20,12 +20,12 @@ OBJS=$(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(SRCS))
CFLAGS = -I$(INCLUDE)
ifeq ($(DEBUG),Y)
- CFLAGS += -Wall -ggdb
+ CFLAGS += -Wall -ggdb -lciid
SRCS := $(filter-out $(SRC)/mem.c, $(SRCS))
LIBNAME =$(NAME)d
LIB = $(OBJ)/lib$(LIBNAME)
else
- CFLAGS += -DNDEBUG
+ CFLAGS += -DNDEBUG -lcii
SRCS := $(filter-out $(SRC)/memchk.c, $(SRCS))
LIBNAME = $(NAME)
LIB = $(OBJ)/lib$(LIBNAME)
@@ -44,7 +44,7 @@ $(OBJ)/%.o: $(SRC)/%.c
install:
install -d /usr/local/include/$(NAME)
- install -p -m 644 $(INCLUDE)/* /usr/local/include/$(NAME)
+ install -p -m 644 $(INCLUDE)/* /usr/local/include/
install -d /usr/local/lib
install -p -m 644 $(LIB).a /usr/local/lib
diff --git a/include/menu.h b/include/menu.h
@@ -3,14 +3,17 @@
#include "pane.h"
+extern Pane_T MAIN, ACTIVE;
+
typedef struct menu_T *menu_T;
typedef struct menuItem_T *menuItem_T;
typedef struct menuStyle_T *menuStyle_T;
typedef struct menuInfo_T *menuInfo_T;
+typedef void (*menuItem_select_f)(char *, int);
struct menuItem_T {
- void (*callback)(char *, int);
- char *name;
+ menuItem_select_f select_f;
+ const char *name;
};
struct menuStyle_T {
@@ -21,7 +24,7 @@ struct menuStyle_T {
struct menuInfo_T {
int start;
- int end;
+ /* int end; */
int y;
int x;
@@ -32,13 +35,17 @@ struct menuInfo_T {
int items_num;
};
+typedef void (*menu_back_f)(void);
struct menu_T {
int current;
+ menu_back_f back_f;
int items_size;
struct menuItem_T items[];
};
+menu_T menu_new(int item_num, menu_back_f back_f);
+
void pane_menu(widget_T widget);
int menu_hadleInput(data_T data, struct tb_event ev);
diff --git a/include/pane.h b/include/pane.h
@@ -6,8 +6,9 @@
#define T Pane_T
typedef struct T *T;
-int pane_start(void);
+int pane_start(int active);
int pane_stop(void);
+void pane_event_loop(void);
int pane_handle_resize(void);
int pane_resize(T self);
@@ -26,14 +27,20 @@ void setActive(int direction);
void pane_setTitle(T self, char *title);
+int centerVertical(Pane_T pane, int len);
+int centerHorisontal(Pane_T pane, int len);
+void draw_border(int x, int y, int x_max, int y_max, uintattr_t color);
+
/* WIDGET */
typedef struct data_T *data_T;
typedef struct widget_T *widget_T;
+typedef int (*data_handler)(data_T, struct tb_event);
+
struct data_T {
+ data_handler handle_input;
void *payload;
- int (*handle_input)(data_T, struct tb_event);
int widget_num;
widget_T *widgets;
@@ -51,7 +58,11 @@ struct widget_T {
void (*callback)(widget_T);
};
+data_T data_new(void *payload, data_handler handler);
+
int widget_activate(widget_T self, Pane_T pane);
+int widget_deactivate(widget_T self);
+void widget_setData(widget_T self, data_T data);
widget_T pane_widget(T self);
#undef T
diff --git a/src/main.c b/src/main.c
@@ -7,8 +7,6 @@
#include "utils.h"
#include "menu.h"
-extern Pane_T MAIN, ACTIVE;
-
void quit(char *pass, int index)
{
pane_stop();
@@ -33,8 +31,8 @@ struct menu_T mainMenu = {
struct menuStyle_T mainMenuStyle = {
.separator = "<------------->",
- .padding = 5,
- .spacing = 2,
+ .padding = 1,
+ .spacing = 1,
};
struct menuStyle_T mainMenuStyle2 = {
@@ -72,62 +70,9 @@ struct widget_T mainMenu_widget2 = {
.info = &mainMenuInfo2,
};
-void input_loop(void)
-{
- struct tb_event ev;
- size_t i;
-
- while (1) {
- tb_poll_event(&ev);
- switch (ev.type) {
- case TB_EVENT_RESIZE:
- pane_handle_resize();
- continue;
- case TB_EVENT_KEY: {
- widget_T widget;
- data_T payload;
-
- switch (ev.key) {
- case TB_KEY_ARROW_UP:
- setActive(0);
- continue;
- case TB_KEY_ARROW_RIGHT:
- setActive(1);
- continue;
- case TB_KEY_ARROW_DOWN:
- setActive(2);
- continue;
- case TB_KEY_ARROW_LEFT:
- setActive(3);
- continue;
- }
- if (ev.ch == 'q' || ev.key == TB_KEY_ESC) {
- return;
- }
-
- if (!(widget = pane_widget(ACTIVE)))
- continue;
-
- if (!(payload = widget->data)) {
- continue;
- }
-
- if (payload->handle_input(payload, ev)) {
- for (i = 0; i < payload->widget_num; i++) {
- widget = payload->widgets[i];
- widget->callback(widget);
- tb_present();
- }
- }
- break;
- }
- }
- }
-}
-
int main(int argc, char **argv)
{
- pane_start();
+ pane_start(0);
{
Pane_T *sections, *mids, *bots;
@@ -139,7 +84,7 @@ int main(int argc, char **argv)
widget_activate(&mainMenu_widget, mids[1]);
widget_activate(&mainMenu_widget2, bots[1]);
- input_loop();
+ pane_event_loop();
}
pane_stop();
return 0;
diff --git a/src/menu.c b/src/menu.c
@@ -2,14 +2,16 @@
#include "pane.h"
#include "utils.h"
-int centerVertical(Pane_T pane, int len)
+menu_T menu_new(int item_num, menu_back_f back_f)
{
- return pane_y(pane) + (pane_height(pane) - len) / 2;
-}
+ menu_T menu =
+ malloc(sizeof(*menu) + item_num * sizeof(struct menuItem_T));
-int centerHorisontal(Pane_T pane, int len)
-{
- return pane_x(pane) + (pane_width(pane) - len - 2) / 2 + 1;
+ menu->items_size = item_num;
+ menu->current = 0;
+ menu->back_f = back_f;
+
+ return menu;
}
int menu_hadleInput(data_T data, struct tb_event ev)
@@ -29,9 +31,15 @@ int menu_hadleInput(data_T data, struct tb_event ev)
}
if (ev.key == TB_KEY_ENTER) {
struct menuItem_T *item = menu->items + menu->current;
- item->callback(item->name, menu->current);
+ item->select_f(item->name, menu->current);
return 1;
}
+ if (ev.key == TB_KEY_BACKSPACE || ev.key == TB_KEY_BACKSPACE2) {
+ if (menu->back_f) {
+ menu->back_f();
+ return 1;
+ }
+ }
}
return 0;
@@ -49,6 +57,8 @@ void pane_menu(widget_T widget)
widget->inited = 1;
widget->resized = 1;
+ pane_clear(pane, 0);
+
int len, maxi = 0;
for (i = 0; i < menu->items_size; i++)
@@ -58,7 +68,7 @@ void pane_menu(widget_T widget)
info->max_item_len = maxi;
info->sep_len = strlen(style->separator);
info->start = 0;
- info->end = info->items_num - 1;
+ /* info->end = info->items_num - 1; */
}
if (widget->resized) {
@@ -69,7 +79,7 @@ void pane_menu(widget_T widget)
style->padding;
// optimal number of elements to display on the screen
int max_items =
- (pane_height(pane) - padding * 2 + style->spacing - 2) /
+ (pane_height(pane) - 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);
@@ -79,6 +89,11 @@ void pane_menu(widget_T widget)
info->y = centerVertical(
pane, info->items_num * (style->spacing + 1) -
style->spacing);
+
+ /* info->start = menu->current - in */
+ /* info->end = info->start + info->items_num - 1; */
+ if (menu->current >= info->start + info->items_num)
+ info->start += menu->current - info->items_num;
}
/* while (1) { */
@@ -87,14 +102,14 @@ void pane_menu(widget_T widget)
int relative = menu->current - info->start;
if (relative < 0) {
info->start--;
- info->end--;
- } else if (relative > 0 && relative > info->end - info->start - 1) {
+ } else if (relative > 0 && relative > info->items_num - 1) {
info->start++;
- info->end++;
}
+ tb_printf(pane_x(pane), pane_y(pane), TB_GREEN, 0, "%d", info->start);
+
CLAMP(info->start, 0, menu->items_size - info->items_num);
- CLAMP(info->end, info->items_num, menu->items_size);
+ /* CLAMP(menu->current, info->start, info->start + info->items_num); */
if (!menu->items_size) {
char *message = "NOTHING TO DISPLAY HERE!";
@@ -108,14 +123,14 @@ void pane_menu(widget_T widget)
style->separator);
int y = info->y;
- for (i = info->start; i < info->end; i++) {
+ for (i = info->start; i < info->start + info->items_num; 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)
+ info->start + info->items_num == 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
@@ -88,33 +88,36 @@ void draw_title(T self)
tb_printf(self->x + 1, self->y, TB_RED, 0, " %d ", self->index);
}
-void draw_border(T self)
+void draw_border(int x, int y, int x_max, int y_max, uintattr_t color)
{
size_t i;
- int x_max = self->x + self->width - 1;
- int y_max = self->y + self->height - 1;
-
- int color = (self->active) ? TB_BLUE : TB_GREEN;
- for (i = self->x + 1; i < x_max; i++) {
- tb_print(i, self->y, color, 0, BORDER_HORIZONTAL);
+ for (i = x + 1; i < x_max; i++) {
+ tb_print(i, y, color, 0, BORDER_HORIZONTAL);
tb_print(i, y_max, color, 0, BORDER_HORIZONTAL);
}
- for (i = self->y + 1; i < y_max; i++) {
- tb_print(self->x, i, color, 0, BORDER_VERTICAL);
+ for (i = y + 1; i < y_max; i++) {
+ tb_print(x, i, color, 0, BORDER_VERTICAL);
tb_print(x_max, i, color, 0, BORDER_VERTICAL);
}
- tb_print(self->x, self->y, color, 0, BORDER_CORNER_1);
- tb_print(x_max, self->y, color, 0, BORDER_CORNER_2);
- tb_print(self->x, y_max, color, 0, BORDER_CORNER_3);
+ tb_print(x, y, color, 0, BORDER_CORNER_1);
+ tb_print(x_max, y, color, 0, BORDER_CORNER_2);
+ tb_print(x, y_max, color, 0, BORDER_CORNER_3);
tb_print(x_max, y_max, color, 0, BORDER_CORNER_4);
+}
+void pane_draw_border(T self)
+{
+ int x_max = self->x + self->width - 1;
+ int y_max = self->y + self->height - 1;
+ uintattr_t color = (self == ACTIVE) ? TB_BLUE : TB_GREEN;
+ draw_border(self->x, self->y, x_max, y_max, color);
draw_title(self);
- tb_printf(self->x, self->y, TB_RED, 0, "%dx%d", self->height,
- self->width);
+ /* tb_printf(self->x, self->y, TB_RED, 0, "%dx%d", self->height, */
+ /* self->width); */
}
void pane_clear(T self, int clear_border)
@@ -214,7 +217,7 @@ int pane_resize(T self)
}
if (self->children_num == 0) {
- draw_border(self);
+ pane_draw_border(self);
return 1;
}
@@ -231,6 +234,10 @@ int pane_handle_resize(void)
MAIN->width = tb_width();
MAIN->x = 0;
MAIN->y = 0;
+ MAIN->direction[0] = NULL;
+ MAIN->direction[1] = NULL;
+ MAIN->direction[2] = NULL;
+ MAIN->direction[3] = NULL;
tb_clear();
pane_resize(MAIN);
@@ -239,17 +246,20 @@ int pane_handle_resize(void)
return 1;
}
-int pane_start(void)
+int pane_start(int active)
{
tb_init();
MAIN = calloc(1, sizeof(*MAIN));
MAIN->height = tb_height();
MAIN->width = tb_width();
- MAIN->active = 1;
MAIN->parent = MAIN;
pane_handle_resize();
- ACTIVE = MAIN;
+ if (active) {
+ ACTIVE = MAIN;
+ MAIN->active = 1;
+ }
+
return 1;
}
@@ -292,6 +302,9 @@ void split(T self, size_t count, va_list ap)
ACTIVE = self->children[0];
}
+ if (self->widget)
+ widget_deactivate(self->widget);
+
pane_resize(self);
}
@@ -318,7 +331,7 @@ void pane_unsplit(T self)
ACTIVE = self;
}
pane_clear(self, 1);
- draw_border(self);
+ pane_draw_border(self);
tb_present();
}
@@ -362,6 +375,9 @@ void pane_setTitle(T self, char *title)
void setActive(int dir)
{
T old = ACTIVE, tmp;
+ if (!ACTIVE->direction[dir])
+ return;
+
ACTIVE = ACTIVE->direction[dir];
while (ACTIVE->children_num) {
@@ -387,25 +403,158 @@ void setActive(int dir)
tmp->parent->active = tmp->child_no;
}
- draw_border(old);
- draw_border(ACTIVE);
+ pane_draw_border(old);
+ pane_draw_border(ACTIVE);
tb_present();
}
+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;
+}
+
+/* DATA */
+
+data_T data_new(void *payload, data_handler handler)
+{
+ data_T data = calloc(1, sizeof(*data));
+ data->handle_input = handler;
+ data->payload = payload;
+ return data;
+}
+
/* WIDGET */
int widget_activate(widget_T self, Pane_T pane)
{
+ size_t i;
+
self->pane = pane;
pane->widget = self;
pane_setTitle(pane, self->title);
+ self->callback(self);
+ tb_present();
+
data_T data = self->data;
+ for (i = 0; i < data->widget_num; i++)
+ if (data->widgets[i] == self)
+ return 1;
+
data->widgets = realloc(data->widgets, data->widget_num + 1);
data->widgets[data->widget_num++] = self;
- self->callback(self);
- tb_present();
+ return 1;
+}
+
+int widget_deactivate(widget_T self)
+{
+ size_t i, j;
+
+ pane_setTitle(self->pane, NULL);
+ self->pane->widget = NULL;
+ self->pane = NULL;
+
+ data_T data = self->data;
+ for (i = j = 0; i < data->widget_num; i++)
+ if (data->widgets[i] != self)
+ data->widgets[j++] = data->widgets[i];
+ data->widget_num = j;
return 1;
}
+
+void widget_setData(widget_T self, data_T data)
+{
+ self->inited = 0;
+ if (self->data) {
+ data->widget_num = self->data->widget_num;
+ data->widgets = self->data->widgets;
+ }
+ self->data = data;
+}
+
+int pane_handle_input(Pane_T self, struct tb_event ev)
+{
+ size_t i;
+ widget_T widget;
+ data_T data;
+
+ if ((widget = pane_widget(self)) && (data = widget->data)) {
+ if (data->handle_input(data, ev)) {
+ size_t size = data->widget_num;
+ for (i = 0; i < size; i++) {
+ widget = data->widgets[i];
+ widget->callback(widget);
+ size = data->widget_num;
+ }
+ tb_present();
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int pane_recursive_handle(Pane_T self, struct tb_event ev)
+{
+ size_t i;
+
+ if (!self)
+ return 0;
+
+ if (!pane_handle_input(self, ev)) {
+ for (i = 0; i < self->children_num; i++)
+ if (pane_recursive_handle(self->children[i], ev))
+ return 1;
+ }
+
+ return 0;
+}
+
+void pane_event_loop(void)
+{
+ struct tb_event ev;
+
+ while (1) {
+ tb_poll_event(&ev);
+ switch (ev.type) {
+ case TB_EVENT_RESIZE:
+ pane_handle_resize();
+ continue;
+ case TB_EVENT_KEY: {
+ if (ev.ch == 'q' || ev.key == TB_KEY_ESC) {
+ return;
+ }
+
+ if (ACTIVE) {
+ switch (ev.key) {
+ case TB_KEY_ARROW_UP:
+ setActive(0);
+ continue;
+ case TB_KEY_ARROW_RIGHT:
+ setActive(1);
+ continue;
+ case TB_KEY_ARROW_DOWN:
+ setActive(2);
+ continue;
+ case TB_KEY_ARROW_LEFT:
+ setActive(3);
+ continue;
+ }
+ if (!pane_handle_input(ACTIVE, ev))
+ continue;
+ break;
+ } else {
+ pane_recursive_handle(MAIN, ev);
+ }
+ }
+ }
+ }
+}
+
+/* CENTER WIDGET */