From 24f51eb22bb4c7c85abddfd860f8ebd5be9d524a Mon Sep 17 00:00:00 2001 From: Alexander Zhylin Date: Wed, 3 Dec 2025 12:14:38 +0200 Subject: [PATCH] dialogue: count dimensions correctly --- TODO.md | 2 +- src/main.c | 2 +- src/ui/modals/login.c | 6 ++--- src/ui/widget.c | 11 +++++--- src/ui/widget.h | 10 +++---- src/ui/widget/button.c | 10 +++---- src/ui/widget/button.h | 2 +- src/ui/widget/dialogue.c | 57 +++++++++++++++++++++++++++++----------- src/ui/widget/dialogue.h | 6 ++--- src/ui/widget/group.c | 8 +++--- src/ui/widget/group.h | 2 +- 11 files changed, 73 insertions(+), 43 deletions(-) diff --git a/TODO.md b/TODO.md index ce6f03e..f8a36eb 100644 --- a/TODO.md +++ b/TODO.md @@ -2,4 +2,4 @@ TODO: - [x] More universal Makefile - [ ] Check and fix registration and login - [x] UI: destroy child elements everywhere -- [ ] use parent widgets pointers to count the margins correctly \ No newline at end of file +- [x] use parent widgets pointers to count the margins correctly \ No newline at end of file diff --git a/src/main.c b/src/main.c index 69ee61f..f4eee3a 100644 --- a/src/main.c +++ b/src/main.c @@ -32,7 +32,7 @@ int main(int argc, char **argv) { app->modal.active = login; init_login_modal(app); - draw_dialogue(app, &(app->modal.dialogue), app->cur_x, app->cur_y); + draw_dialogue(app, &(app->modal.dialogue)); event_loop(app); diff --git a/src/ui/modals/login.c b/src/ui/modals/login.c index 112dff2..b4f05fd 100644 --- a/src/ui/modals/login.c +++ b/src/ui/modals/login.c @@ -1,6 +1,7 @@ #include "../app.h" #include "../widget/dialogue.h" #include "../widget/group.h" +#include #include #include @@ -21,13 +22,12 @@ dialogue_t *init_login_modal(app_t *app) { dialogue_t *d = init_dialogue("Login", "Select your login " - "option", - 50, 20); + "option"); memcpy(&(app->modal.dialogue), d, sizeof(dialogue_t)); free(d); app->modal.dialogue.ch_group = - init_group(&(app->modal.dialogue.win), d->w.id, children, horizontal); + init_group(&(app->modal.dialogue.win), &(d->w), children, horizontal); group_bt_t *ch_btns = (group_bt_t *)app->modal.dialogue.ch_group->elements; ch_btns[0].element->is_hovered = 1; diff --git a/src/ui/widget.c b/src/ui/widget.c index 582376f..f8df5d2 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c @@ -6,22 +6,23 @@ extern uint32_t m_id; -void init_widget(widget_t *w, WINDOW **win, char *title, uint32_t parent_id) { +void init_widget(widget_t *w, widget_t *w_parent, WINDOW **win, char *title) { w->id = m_id++; w->x = 0; w->y = 0; w->m_x = 0; w->m_y = 0; w->parent_win = win; - w->parent_id = parent_id; + w->w_parent = w_parent; strcpy(w->title, title); } -int32_t get_max_line_len(const char *text) { +int32_t get_max_line_len(const char *text, uint32_t *line_count) { uint32_t nl_pos = 0; // new line position uint32_t c_start = 0; // current line start position uint32_t c_len = 0; // current line length uint32_t m_len = 0; // max length + uint32_t line_num = 1; for (int i = 0; text[i] != '\0'; i++, c_len++) { if (text[i] == '\n') { if (i - nl_pos > c_len || !m_len) { @@ -30,8 +31,10 @@ int32_t get_max_line_len(const char *text) { nl_pos = i; c_start = i + 1; c_len = 0; + line_num++; } } + if (line_count != NULL) *line_count = line_num; if (c_len > m_len) { return c_len; } else { @@ -62,7 +65,7 @@ uint32_t print_multiline_text(WINDOW *win, const char *text, char l_buf[DIALOGUE_TEXT]; if (attrs & PMT_POS_CENTER) { - m_line_len = get_max_line_len(text); + m_line_len = get_max_line_len(text, NULL); } for (; text[i]; i++, c_line_len++) { diff --git a/src/ui/widget.h b/src/ui/widget.h index 41334d3..fbef381 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h @@ -12,15 +12,15 @@ enum w_type { w_group, }; -typedef struct { +typedef struct widget_t { uint32_t id; char title[DIALOGUE_TITLE]; uint32_t x; uint32_t y; uint32_t m_x; uint32_t m_y; - WINDOW **parent_win; - uint32_t parent_id; + WINDOW *const* parent_win; + struct widget_t *w_parent; } widget_t; enum pmt_attrs { @@ -28,8 +28,8 @@ enum pmt_attrs { PMT_ALIGN_CENTER = 03, }; -void init_widget(widget_t *w, WINDOW **win, char *title, uint32_t parent_id); -int32_t get_max_line_len(const char *text); +void init_widget(widget_t *w, widget_t *w_parent, WINDOW **win, char *title); +int32_t get_max_line_len(const char *text, uint32_t *line_count); uint32_t print_multiline_text(WINDOW *win, const char *text, const uint32_t win_width, const uint32_t y, const uint32_t x, const uint16_t attrs); diff --git a/src/ui/widget/button.c b/src/ui/widget/button.c index e590c35..0ef5218 100644 --- a/src/ui/widget/button.c +++ b/src/ui/widget/button.c @@ -7,9 +7,9 @@ #include "../widget.h" #include "button.h" -button_t *init_button(WINDOW **win, uint32_t parent_id, char *label) { +button_t *init_button(WINDOW **win, widget_t *w_parent, char *label) { button_t *btn = malloc(sizeof(button_t)); - init_widget(&(btn->w), win, label, parent_id); + init_widget(&(btn->w), w_parent, win, label); btn->is_disabled = 0; btn->is_focused = 0; btn->is_hovered = 0; @@ -23,8 +23,8 @@ button_t *init_button(WINDOW **win, uint32_t parent_id, char *label) { int32_t draw_button(button_t *btn) { char title[DIALOGUE_TITLE + 6]; WINDOW *win = *(btn->w.parent_win); - uint32_t cur_y = btn->w.m_y; - uint32_t cur_x = btn->w.m_x; + uint32_t margin_y = btn->w.m_y + btn->w.w_parent->m_y; + uint32_t margin_x = btn->w.m_x + btn->w.w_parent->m_x; if (btn->is_focused) { sprintf(title, "[< %s >]", btn->w.title); @@ -38,7 +38,7 @@ int32_t draw_button(button_t *btn) { wattrset(win, COLOR_PAIR(0) | A_REVERSE); } - mvwprintw(win, cur_y, cur_x, "%s", title); + mvwprintw(win, margin_y, margin_x, "%s", title); wattroff(win, A_BOLD | A_REVERSE); return strlen(title); diff --git a/src/ui/widget/button.h b/src/ui/widget/button.h index 84a270e..492fbe8 100644 --- a/src/ui/widget/button.h +++ b/src/ui/widget/button.h @@ -14,7 +14,7 @@ typedef struct { callback_t *callback; } button_t; -button_t *init_button(WINDOW **win, uint32_t parent_id, char *label); +button_t *init_button(WINDOW **win, widget_t *w_parent, char *label); int32_t draw_button(button_t *btn); void destroy_button(button_t *btn); #endif \ No newline at end of file diff --git a/src/ui/widget/dialogue.c b/src/ui/widget/dialogue.c index b8a12b8..763a318 100644 --- a/src/ui/widget/dialogue.c +++ b/src/ui/widget/dialogue.c @@ -1,30 +1,58 @@ -#include "dialogue.h" -#include "../app.h" -#include "group.h" #include #include #include #include +#include -dialogue_t *init_dialogue(const char title[], const char text[], - const uint32_t width, const uint32_t height) { +#include "../app.h" +#include "dialogue.h" +#include "group.h" + +dialogue_t *init_dialogue(const char title[], const char text[]) { dialogue_t *dialogue = malloc(sizeof(dialogue_t)); dialogue->win = 0; dialogue->ch_group = NULL; - dialogue->w.x = width; - dialogue->w.y = height; + dialogue->w.x = 0; + dialogue->w.y = 0; strcpy(dialogue->w.title, title); strcpy(dialogue->text, text); return dialogue; } -int32_t draw_dialogue(void *app, dialogue_t *d, uint32_t cur_x, uint32_t cur_y) { - app_t *_app = (app_t *) app; - d->w.m_x = (cur_x - d->w.x) / 2; - d->w.m_y = (cur_y - d->w.y) / 2; +int32_t draw_dialogue(void *_app, dialogue_t *d) { + app_t *app = (app_t *)_app; - d->win = newwin(d->w.y, d->w.x, d->w.m_y, d->w.m_x); + /* count dimensions */ + uint32_t x = 1; /* when uses box */ + uint32_t y = 1; /* when uses box */ + uint32_t line_count = 0; + uint32_t line_max_len = 0; + line_max_len = get_max_line_len(d->text, &line_count); + y += line_count; + y += 2; /* margin for text */ + + if (d->ch_group) { + d->ch_group->w.m_y = y; + if (line_max_len < d->ch_group->w.x) { + line_max_len = d->ch_group->w.x; + d->ch_group->w.m_x = 1; /* when uses box */ + } else { + /* TODO: centering */ + } + y += d->ch_group->w.y; + } + x += line_max_len; + + x += 1; /* when uses box */ + y += 1; /* when uses box */ + d->w.x = x; + d->w.y = y; + d->w.m_x = (app->cur_x - x) / 2; + d->w.m_y = (app->cur_y - y) / 2; + + /* render window */ + d->win = newwin(y, x, d->w.m_y, d->w.m_x); wattrset(d->win, COLOR_PAIR(0) | A_BOLD | A_REVERSE); /* background */ @@ -42,10 +70,9 @@ int32_t draw_dialogue(void *app, dialogue_t *d, uint32_t cur_x, uint32_t cur_y) mvwprintw(d->win, 0, title_mx_pos + strlen(d->w.title), " "); /* text */ - print_multiline_text(d->win, d->text, d->w.x, 1, 1, PMT_ALIGN_CENTER); + wattroff(d->win, A_BOLD); + print_multiline_text(d->win, d->text, d->w.x, 2, 1, PMT_ALIGN_CENTER); wattroff(d->win, A_REVERSE); - d->ch_group->w.m_x = (d->w.x - d->ch_group->w.x) / 2; - d->ch_group->w.m_y = 4; draw_group(d->win, d->ch_group); wrefresh(d->win); diff --git a/src/ui/widget/dialogue.h b/src/ui/widget/dialogue.h index babf27f..37ce0a5 100644 --- a/src/ui/widget/dialogue.h +++ b/src/ui/widget/dialogue.h @@ -1,10 +1,10 @@ #ifndef DIALOGUE_H #define DIALOGUE_H -#include #include "../widget.h" #include "button.h" #include "group.h" +#include typedef struct { WINDOW *win; @@ -13,8 +13,8 @@ typedef struct { char text[DIALOGUE_TEXT]; } dialogue_t; -dialogue_t *init_dialogue(const char title[], const char text[], const uint32_t w, const uint32_t h); -int32_t draw_dialogue(void *app, dialogue_t *d, const uint32_t cur_x, const uint32_t cur_y); +dialogue_t *init_dialogue(const char title[], const char text[]); +int32_t draw_dialogue(void *app, dialogue_t *d); void destroy_active_dialogue(dialogue_t *d); #endif \ No newline at end of file diff --git a/src/ui/widget/group.c b/src/ui/widget/group.c index 0ca9bb8..d600e86 100644 --- a/src/ui/widget/group.c +++ b/src/ui/widget/group.c @@ -4,7 +4,7 @@ #include #include -group_t *init_group(WINDOW **win, uint32_t par_id, group_el_init_t *children, +group_t *init_group(WINDOW **win, widget_t *w_parent, group_el_init_t *children, enum g_direction direction) { group_t *group = malloc(sizeof(group_t)); @@ -12,8 +12,8 @@ group_t *init_group(WINDOW **win, uint32_t par_id, group_el_init_t *children, uint32_t count = 0; for (; children[count].type != w_end; count++) ; - count++; /* TODO: improve counting */ group->elements = calloc(count, sizeof(group_el_t)); + group->w.w_parent = w_parent; group_el_t *elements = group->elements; for (int i = 0; i < count; i++) { elements[i].type = children[i].type; @@ -23,7 +23,7 @@ group_t *init_group(WINDOW **win, uint32_t par_id, group_el_init_t *children, for (int i = 0; elements[i].type != w_end; i++) { switch (elements[i].type) { case w_button: - elements[i].element = init_button(win, par_id, children[i].label); + elements[i].element = init_button(win, &(group->w), children[i].label); if (direction == horizontal) { button_t *b = (button_t *)elements[i].element; b->w.m_x = group->w.x; @@ -40,7 +40,7 @@ group_t *init_group(WINDOW **win, uint32_t par_id, group_el_init_t *children, break; } } - + return group; } diff --git a/src/ui/widget/group.h b/src/ui/widget/group.h index 44f05f5..4e32872 100644 --- a/src/ui/widget/group.h +++ b/src/ui/widget/group.h @@ -25,7 +25,7 @@ typedef struct { enum g_direction direction; } group_t; -group_t *init_group(WINDOW **win, uint32_t par_id, group_el_init_t *children, +group_t *init_group(WINDOW **win, widget_t *w_parent, group_el_init_t *children, enum g_direction dir); void draw_group(WINDOW *win, group_t *group); void destroy_group(group_t *group);