pane

Termbox2 based terminal UI library
git clone git://git.dimitrijedobrota.com/pane.git
Log | Files | Refs

commit bc97ab55b639aaa9d2c4210a50cfd82789657917
parent 2d45bf507eaa7814eb4bf765d1970c8c6f8ee5d4
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Thu,  8 Sep 2022 23:28:04 +0200

General improvements and bug fixing

Diffstat:
MMakefile | 31++++++++++++-------------------
Minclude/pane.h | 2++
Ainclude/widgets.h | 22++++++++++++++++++++++
Msrc/main.c | 10+++-------
Msrc/menu.c | 5++---
Msrc/pane.c | 89++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Asrc/widgets.c | 48++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 141 insertions(+), 66 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,12 +1,12 @@ -# GNU Makefile for C Interfaces and Implementations +# GNU Makefile for Termbox2 based display library # # Usage: make [-f path\Makefile] [DEBUG=Y] target -NAME = display +NAME = pane CC = gcc SRC = src -OBJ = . +OBJ = obj BIN = bin INCLUDE = include LATEX = docs/latex @@ -20,15 +20,13 @@ OBJS=$(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(SRCS)) CFLAGS = -I$(INCLUDE) ifeq ($(DEBUG),Y) - CFLAGS += -Wall -ggdb -lciid + CFLAGS += -Wall -ggdb SRCS := $(filter-out $(SRC)/mem.c, $(SRCS)) - LIBNAME =$(NAME)d - LIB = $(OBJ)/lib$(LIBNAME) + LIB = $(OBJ)/lib$(NAME)d else - CFLAGS += -DNDEBUG -lcii + CFLAGS += -DNDEBUG SRCS := $(filter-out $(SRC)/memchk.c, $(SRCS)) - LIBNAME = $(NAME) - LIB = $(OBJ)/lib$(LIBNAME) + LIB = $(OBJ)/lib$(NAME) endif all: $(LIB) main @@ -36,27 +34,23 @@ all: $(LIB) main $(LIB): $(OBJS) ar crs $@.a $^ -main: main.o - gcc $(SRC)/main.c -o $(BIN)/main $(CFLAGS) $(LDFLAGS) -L. -l$(LIBNAME) +main: $(OBJ)/main.o + gcc $(SRC)/main.c -o $(BIN)/main $(CFLAGS) $(LDFLAGS) -L. -l:$(LIB).a $(OBJ)/%.o: $(SRC)/%.c $(CC) -c $< -o $@ $(CFLAGS) $(LDFLAGS) install: install -d /usr/local/include/$(NAME) - install -p -m 644 $(INCLUDE)/* /usr/local/include/ + install -p -m 644 $(INCLUDE)/* /usr/local/include/$(NAME) install -d /usr/local/lib install -p -m 644 $(LIB).a /usr/local/lib clean: - -$(RM) $(OBJS) $(LIB).a - -docs: - doxygen - make -C $(LATEX) + -$(RM) $(BIN)/* $(OBJ)/* help: - @echo "Terbox2 based display library" + @echo "Termbox2 based display library" @echo @echo "Usage: make [-f path\Makefile] [DEBUG=Y] target" @echo @@ -65,7 +59,6 @@ help: @echo " install - Installs the static library and header files" @echo " clean - Clean the project by removing binaries" @echo " help - Prints a help message with target rules" - @echo " docs - Compile html and pdf documentation using doxygen and pdflatex" @echo @echo "Optional parameters:" @echo " DEBUG - Compile binary file with debug flags enabled" diff --git a/include/pane.h b/include/pane.h @@ -3,6 +3,8 @@ #include <termbox.h> +enum INPUT_SIGNALS { INPUT_IGNORED, INPUT_HANDLED, INPUT_REFORM }; + #define T Pane_T typedef struct T *T; diff --git a/include/widgets.h b/include/widgets.h @@ -0,0 +1,22 @@ +#ifndef WIDGETLIST_H +#define WIDGETLIST_H + +#include <stdarg.h> +#include "pane.h" + +typedef struct widgetList_T *widgetList_T; +struct widgetList_T { + Pane_T pane; + size_t items_num; + size_t index_start; + int end; + int display_num; + int y_start; +}; + +widgetList_T widgetList_new(Pane_T pane, int size); +void widgetList_cacl(widgetList_T self, int index_current); + +void widgetCenter_print(widget_T widget); + +#endif diff --git a/src/main.c b/src/main.c @@ -41,16 +41,10 @@ struct menuStyle_T mainMenuStyle2 = { .spacing = 0, }; -struct data_T mainMenu_payload = { - .payload = (void *)&mainMenu, - .handle_input = menu_hadleInput, -}; - struct menuInfo_T mainMenuInfo; struct widget_T mainMenu_widget = { .pane = NULL, - .data = &mainMenu_payload, .callback = pane_menu, .title = "Main Menu", .style = &mainMenuStyle, @@ -63,7 +57,6 @@ struct widget_T mainMenu_widget2 = { .pane = NULL, .inited = 0, .resized = 0, - .data = &mainMenu_payload, .callback = pane_menu, .title = "Main Menu 2", .style = &mainMenuStyle2, @@ -82,6 +75,9 @@ int main(int argc, char **argv) pane_vsplit(mids[0], 2, 1, 1); + data_T mainMenu_payload = data_new(&mainMenu, menu_hadleInput); + widget_setData(&mainMenu_widget, mainMenu_payload); + widget_setData(&mainMenu_widget2, mainMenu_payload); widget_activate(&mainMenu_widget, mids[1]); widget_activate(&mainMenu_widget2, bots[1]); pane_event_loop(); diff --git a/src/menu.c b/src/menu.c @@ -106,8 +106,6 @@ void pane_menu(widget_T widget) info->start++; } - 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(menu->current, info->start, info->start + info->items_num); */ @@ -125,7 +123,8 @@ void pane_menu(widget_T widget) int y = info->y; 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); + tb_printf(info->x, y, color, 0, "%.*s", + pane_width(widget->pane), menu->items[i].name); y += style->spacing + 1; } diff --git a/src/pane.c b/src/pane.c @@ -1,6 +1,5 @@ #include <termbox.h> #include <stdarg.h> -#include <mem.h> #include <stdlib.h> #include "pane.h" @@ -112,12 +111,10 @@ 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; + int 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); */ } void pane_clear(T self, int clear_border) @@ -322,6 +319,8 @@ void pane_unsplit(T self) } free(self->children); free(self->rules); + self->children = NULL; + self->rules = NULL; } else { active = self->active; } @@ -368,8 +367,10 @@ T *pane_vsplit(T self, size_t count, ...) void pane_setTitle(T self, char *title) { self->title = title; - if (self->children_num == 0) + if (self->children_num == 0) { + pane_draw_border(self); draw_title(self); + } } void setActive(int dir) @@ -410,11 +411,17 @@ void setActive(int dir) int centerVertical(Pane_T pane, int len) { + if (len > pane_height(pane)) + return pane_hasBorder(pane) ? 1 : 0; + return pane_y(pane) + (pane_height(pane) - len) / 2; } int centerHorisontal(Pane_T pane, int len) { + if (len > pane_width(pane)) + return pane_hasBorder(pane) ? 1 : 0; + return pane_x(pane) + (pane_width(pane) - len - 2) / 2 + 1; } @@ -425,6 +432,8 @@ data_T data_new(void *payload, data_handler handler) data_T data = calloc(1, sizeof(*data)); data->handle_input = handler; data->payload = payload; + data->widget_num = 0; + data->widgets = NULL; return data; } @@ -432,8 +441,6 @@ data_T data_new(void *payload, data_handler handler) int widget_activate(widget_T self, Pane_T pane) { - size_t i; - self->pane = pane; pane->widget = self; pane_setTitle(pane, self->title); @@ -441,14 +448,6 @@ int widget_activate(widget_T self, Pane_T pane) 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; - return 1; } @@ -472,48 +471,66 @@ int widget_deactivate(widget_T self) 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; + data->widgets = realloc(data->widgets, (data->widget_num + 1) * + sizeof(*data->widgets)); + data->widgets[data->widget_num++] = self; } int pane_handle_input(Pane_T self, struct tb_event ev) { size_t i; + int res; 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; + if (data->handle_input) { + switch ((res = data->handle_input(data, ev))) { + case INPUT_HANDLED: { + data = widget->data; + 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; + } + case INPUT_IGNORED: + case INPUT_REFORM: + return res; } - tb_present(); - return 1; } } - return 0; + return INPUT_IGNORED; } int pane_recursive_handle(Pane_T self, struct tb_event ev) { size_t i; + int res; 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; + switch ((res = pane_handle_input(self, ev))) { + case INPUT_HANDLED: + case INPUT_REFORM: + return res; } - return 0; + for (i = 0; i < self->children_num; i++) + switch ((res = pane_recursive_handle(self->children[i], ev))) { + case INPUT_IGNORED: + continue; + case INPUT_HANDLED: + case INPUT_REFORM: + return res; + } + + return INPUT_IGNORED; } void pane_event_loop(void) @@ -527,7 +544,7 @@ void pane_event_loop(void) pane_handle_resize(); continue; case TB_EVENT_KEY: { - if (ev.ch == 'q' || ev.key == TB_KEY_ESC) { + if (ev.key == TB_KEY_ESC) { return; } @@ -556,5 +573,3 @@ void pane_event_loop(void) } } } - -/* CENTER WIDGET */ diff --git a/src/widgets.c b/src/widgets.c @@ -0,0 +1,48 @@ +#include <math.h> + +#include "pane.h" +#include "widgets.h" +#include "utils.h" + +widgetList_T widgetList_new(Pane_T pane, int size) +{ + widgetList_T list = calloc(1, sizeof(*list)); + list->items_num = size; + list->pane = pane; + + return list; +} + +void widgetList_cacl(widgetList_T self, int index_current) +{ + int max_items = pane_height(self->pane); + self->display_num = ACLAMP(max_items, 0, self->items_num); + + int relative = index_current - self->index_start; + if (relative < 0 && self->index_start > 0) { + self->index_start += relative; + } else if (relative > 0 && relative > self->display_num - 1) { + self->index_start += relative - (self->display_num - 1); + } + CLAMP(self->index_start, 0, self->items_num - self->display_num); +} + +void widgetCenter_print(widget_T widget) +{ + size_t i; + char *message = (char *)widget->data->payload; + Pane_T pane = widget->pane; + + pane_clear(pane, 0); + + int len = strlen(message); + int width = pane_width(pane); + int lines = ceil((double)len / width); + int start_x = centerHorisontal(pane, MIN(len, width)); + int y = centerVertical(pane, lines); + + for (i = 0; i < lines; i++, y++) + tb_printf(start_x, y, TB_RED, 0, "%.*s", pane_width(pane), + message + i * width); + tb_present(); +}