From 4661a36acfafc4baab85853810f68a064c12bd22 Mon Sep 17 00:00:00 2001 From: Alexander Zhylin Date: Thu, 15 Jan 2026 15:04:36 +0200 Subject: [PATCH] ui: file list modal (not finished) --- src/ui/app.c | 2 +- src/ui/modals/server_message.c | 2 +- src/ui/modals/upload_dialogue.c | 6 ++---- src/ui/widget.h | 2 +- src/ui/widget/dialogue.c | 36 +++++++++++++++++++++++---------- src/ui/widget/file_list.c | 2 +- src/ui/widget/fs_file_list.c | 33 +++++++++++++++--------------- src/ui/widget/group.c | 12 ++++++++++- src/ui/widget/group.h | 14 +++++-------- 9 files changed, 64 insertions(+), 45 deletions(-) diff --git a/src/ui/app.c b/src/ui/app.c index 8c820b6..68fab99 100644 --- a/src/ui/app.c +++ b/src/ui/app.c @@ -71,7 +71,7 @@ void init_nc() { cbreak(); keypad(stdscr, TRUE); noecho(); - curs_set(0); + curs_set(false); if (!has_colors()) { printf("Your terminal does not support color\n"); diff --git a/src/ui/modals/server_message.c b/src/ui/modals/server_message.c index 505de0f..53ec6b5 100644 --- a/src/ui/modals/server_message.c +++ b/src/ui/modals/server_message.c @@ -20,7 +20,7 @@ void server_message_modal_cb(callback_args_t *args) { memcpy(&d_args, args, sizeof(callback_args_t)); d_args.app = NULL; d_args.resp_data = &response; - d_args.widget = app->active_widget; + d_args.element = app->active_widget; dialogue_default_callback(&d_args); if (response > -1) { switch (response) { diff --git a/src/ui/modals/upload_dialogue.c b/src/ui/modals/upload_dialogue.c index 154f1af..a7f9c91 100644 --- a/src/ui/modals/upload_dialogue.c +++ b/src/ui/modals/upload_dialogue.c @@ -13,7 +13,7 @@ void upload_dialogue_modal_cb(callback_args_t *args) { memcpy(&d_args, args, sizeof(callback_args_t)); d_args.app = NULL; d_args.resp_data = &response; - d_args.widget = app->active_widget; + d_args.element = app->active_widget; dialogue_default_callback(&d_args); if (response > -1) { switch (response) { @@ -30,12 +30,11 @@ dialogue_t *init_upload_dialogue_modal(app_t *app) { if (app == NULL) return NULL; group_el_init_t content[] = { - {.type = w_input, .label = "File description", .length = 30}, + // {.type = w_input, .label = "File description", .length = 30}, {.type = w_fs_file_list, .label = "File", .length = 30}, {.type = w_end}}; group_el_init_t actions[] = { - {.type = w_button, .label = "Upload", .is_default = 1}, {.type = w_button, .label = "Cancel", .is_default = 0}, {.type = w_end}}; @@ -48,7 +47,6 @@ dialogue_t *init_upload_dialogue_modal(app_t *app) { d->g_content = init_group(&(d->win), &(d->w), content, horizontal); d->g_action = init_group(&(d->win), &(d->w), actions, horizontal); - app->query_args->progress_bar = d->g_content->elements[0].element; app->query_args->active_dialogue = d; dialogue_init_active_id(d); diff --git a/src/ui/widget.h b/src/ui/widget.h index 57ed7b3..6db125a 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h @@ -17,7 +17,7 @@ enum w_type { typedef struct { void *app; - void *widget; + void *element; void *data; void *resp_data; uint32_t active_id; diff --git a/src/ui/widget/dialogue.c b/src/ui/widget/dialogue.c index 5cb051c..56c4b4f 100644 --- a/src/ui/widget/dialogue.c +++ b/src/ui/widget/dialogue.c @@ -43,7 +43,7 @@ } void dialogue_default_callback(callback_args_t *args) { - dialogue_t *d = (void *)args->widget; + dialogue_t *d = (void *)args->element; int32_t key = *((int32_t *)args->data); app_t *app = (app_t *)args->app; callback_args_t new_args; @@ -54,7 +54,7 @@ void dialogue_default_callback(callback_args_t *args) { int32_t diff; d->needs_update = true; input_t *input; - switch (key) { + switch (key) { case '\t': if (d->active.type == g_content) { INCR_ACTIVE_ID(d, g_content, g_action); @@ -99,7 +99,7 @@ void dialogue_default_callback(callback_args_t *args) { break; case '\n': if (d->active.type == g_action) { - new_args.widget = new_args.widget = d->g_action; + new_args.element = new_args.element = d->g_action; group_default_callback(&new_args); } else if (d->g_action != NULL) { for (int i = 0; i < d->g_action->count; i++) { @@ -115,17 +115,29 @@ void dialogue_default_callback(callback_args_t *args) { } break; case KEY_UP: - CH_GROUP(d, g_action, g_content); + if (d->g_content->elements[d->active.id - d->g_content->first_id].type == + w_fs_file_list) { + new_args.element = d->g_content; + group_default_callback(&new_args); + } else { + CH_GROUP(d, g_action, g_content); + } break; case KEY_DOWN: - CH_GROUP(d, g_content, g_action); + if (d->g_content->elements[d->active.id - d->g_content->first_id].type == + w_fs_file_list) { + new_args.element = d->g_content; + group_default_callback(&new_args); + } else { + CH_GROUP(d, g_content, g_action); + } break; default: /* run callback function */ if (d->active.type == g_content) { - new_args.widget = new_args.widget = d->g_content; + new_args.element = new_args.element = d->g_content; } else { - new_args.widget = new_args.widget = d->g_action; + new_args.element = new_args.element = d->g_action; } group_default_callback(&new_args); } @@ -152,7 +164,8 @@ void dialogue_init_active_id(dialogue_t *dialogue) { if (dialogue->g_content != NULL) { for (int i = 0; i < dialogue->g_content->count; i++) { widget_type = dialogue->g_content->elements[i].type; - if (widget_type == w_button || widget_type == w_input) { + if (widget_type == w_button || widget_type == w_input || + widget_type == w_fs_file_list) { /* Add here new types */ dialogue->active.type = g_content; widget_t *w = (widget_t *)dialogue->g_content->elements[i].element; dialogue->active.id = w->id; @@ -162,7 +175,8 @@ void dialogue_init_active_id(dialogue_t *dialogue) { } else if (dialogue->g_action != NULL) { for (int i = 0; i < dialogue->g_action->count; i++) { widget_type = dialogue->g_action->elements[i].type; - if (widget_type == w_button || widget_type == w_input) { + if (widget_type == w_button || widget_type == w_input || + widget_type == w_fs_file_list) { dialogue->active.type = g_action; widget_t *w = (widget_t *)dialogue->g_action->elements[i].element; dialogue->active.id = w->id; @@ -264,10 +278,10 @@ int32_t draw_dialogue(dialogue_t *d) { d->w.cur.x -= input->cur_pos; if (d->w.cur.y || d->w.cur.x) { wmove(d->win, d->w.cur.y, d->w.cur.x); - curs_set(1); + curs_set(true); } } else { - curs_set(0); + curs_set(false); } } diff --git a/src/ui/widget/file_list.c b/src/ui/widget/file_list.c index 63497f6..b9400e8 100644 --- a/src/ui/widget/file_list.c +++ b/src/ui/widget/file_list.c @@ -87,7 +87,7 @@ void draw_file_list(ui_file_list_t *fl_ui) { fl_item_t *el = *(fl_ui->start); fl_item_t *active_el = *(fl_ui->start); int32_t cur_el_idx = 0; - curs_set(0); + curs_set(false); if (fl_ui->activate_last) { fl_ui->current_idx = fl_ui->current_count - 1; diff --git a/src/ui/widget/fs_file_list.c b/src/ui/widget/fs_file_list.c index b1186ad..0d1733a 100644 --- a/src/ui/widget/fs_file_list.c +++ b/src/ui/widget/fs_file_list.c @@ -1,6 +1,6 @@ +#include "fs_file_list.h" #include "../../file_processor.h" #include "../app.h" -#include "fs_file_list.h" #include "progress_bar.h" #include #include @@ -27,6 +27,7 @@ static void fl_add(fl_item_t **f_start, fl_item_t **f_current, *f_current = c_item; } else { (*f_current)->next = c_item; + *f_current = c_item; } } @@ -48,8 +49,7 @@ fl_item_t *get_files_from_fs(char *path) { } void fs_file_list_cb(callback_args_t *args) { - app_t *app = args->app; - ui_fs_file_list_t *fui = app->query_args->file_list_ui; + ui_fs_file_list_t *fui = args->element; int32_t key = *((int32_t *)args->data); int32_t q_len = 0; fl_item_t *f_item; @@ -87,6 +87,9 @@ ui_fs_file_list_t *init_fs_file_list(WINDOW **win, widget_t *w_parent) { fl_ui->current_count = 0; fl_ui->activate_last = false; fl_ui->info_win = NULL; + fl_ui->start = malloc(sizeof(fl_item_t *)); /* For compatibility reasons */ + *(fl_ui->start) = get_files_from_fs("./"); + fl_ui->w.callback = fs_file_list_cb; return fl_ui; } @@ -102,12 +105,12 @@ void draw_fs_file_list(ui_fs_file_list_t *fl_ui) { WINDOW *win = *(fl_ui->w.parent_win); getmaxyx(win, sz_y, sz_x); int32_t sz_y_f = sz_y - 2; // actual size (without box) + int32_t sz_x_f = sz_x - 2; // actual size (without box) p_y = 1; p_x = 1; fl_item_t *el = *(fl_ui->start); fl_item_t *active_el = *(fl_ui->start); int32_t cur_el_idx = 0; - curs_set(0); if (fl_ui->activate_last) { fl_ui->current_idx = fl_ui->current_count - 1; @@ -118,6 +121,8 @@ void draw_fs_file_list(ui_fs_file_list_t *fl_ui) { p_y -= fl_ui->current_idx - sz_y_f + 2; } + wattrset(win, A_REVERSE); /* Match with window background */ + do { if (p_y < 1) { p_y++; @@ -125,14 +130,14 @@ void draw_fs_file_list(ui_fs_file_list_t *fl_ui) { continue; } if (cur_el_idx == fl_ui->current_idx) { - wattrset(win, A_BOLD | A_REVERSE); + wattrset(win, COLOR_PAIR(3) | A_BOLD | A_REVERSE); active_el = el; } p_x = 1; mvwprintw(win, p_y, p_x, "%s%n", el->name, &p_x); - mvwprintw(win, p_y, p_x + 1, "%*s", sz_x - p_x, ""); + mvwprintw(win, p_y, p_x + 1, "%*s", sz_x_f - p_x, ""); if (cur_el_idx == fl_ui->current_idx) { - wattroff(win, A_BOLD | A_REVERSE); + wattroff(win, COLOR_PAIR(3) | A_BOLD); } p_y++; cur_el_idx++; @@ -141,20 +146,16 @@ void draw_fs_file_list(ui_fs_file_list_t *fl_ui) { p_x = 1; for (; p_y < sz_y_f; p_y++) { - mvwprintw(win, p_y, p_x, "%*s", sz_x - 1, ""); + mvwprintw(win, p_y, p_x, "%*s", sz_x_f - 1, ""); } - char p_info[24]; - uint32_t p_len; - p_x = 1; - uint32_t l_pad = (sz_x - p_len) / 2; - - wattrset(win, A_BOLD); - mvwprintw(win, p_y, p_x, "%*s%s%*s", l_pad, "", p_info, l_pad, ""); - wattroff(win, A_BOLD); + wattroff(win, A_BOLD | A_REVERSE); + wattrset(win, COLOR_PAIR(0)); + curs_set(false); } void destroy_fs_file_list(ui_fs_file_list_t *fui) { fl_clear(fui->start, fui->current); + free(fui->start); free(fui); } \ No newline at end of file diff --git a/src/ui/widget/group.c b/src/ui/widget/group.c index ce2d9ea..7228ce7 100644 --- a/src/ui/widget/group.c +++ b/src/ui/widget/group.c @@ -16,13 +16,15 @@ } void group_default_callback(callback_args_t *args) { - group_t *g = (group_t *)args->widget; + group_t *g = (group_t *)args->element; int32_t key = *((int32_t *)args->data); int32_t *response = (int32_t *)args->resp_data; input_t *input; + widget_t *widget; group_el_t *element_ptr; int32_t element_idx = -1; u_int32_t start_pos = 0; + callback_args_t new_args; switch (key) { case '\n': /* Enter */ FIND_ACTIVE_ELEMENT(g, args->active_id, element_ptr, element_idx); @@ -60,6 +62,13 @@ void group_default_callback(callback_args_t *args) { input->value[input->value_len] = '\0'; } } + } else { + widget = (widget_t *) element_ptr->element; + if (widget->callback != NULL) { + memccpy(&new_args, args, 1, sizeof(callback_args_t *)); + new_args.element = element_ptr->element; + widget->callback(&new_args); + } } MAKE_RESPONSE_M1(args, resp_data, response); break; @@ -124,6 +133,7 @@ group_t *init_group(WINDOW **win, widget_t *w_parent, group_el_init_t *children, } if (i == 0) { group->first_id = w->id; + group->last_id = w->id; } else { group->last_id = w->id; } diff --git a/src/ui/widget/group.h b/src/ui/widget/group.h index 291aa8b..4516dc6 100644 --- a/src/ui/widget/group.h +++ b/src/ui/widget/group.h @@ -32,18 +32,14 @@ typedef struct { uint32_t first_id, last_id; } group_t; -#define FIND_ACTIVE_ELEMENT(g, active_id, element_ptr, element_idx) \ - for (int i = 0; i < g->count; i++) { \ - if (g->elements[i].id == active_id) { \ - element_ptr = &(g->elements[i]); \ - element_idx = i; \ - break; \ - } \ - } +#define FIND_ACTIVE_ELEMENT(g, active_id, element_ptr, element_idx) \ + element_idx = active_id - g->first_id; \ + element_ptr = &(g->elements[element_idx]); 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, int32_t active_id, widget_t *dialog_w); +void draw_group(WINDOW *win, group_t *group, int32_t active_id, + widget_t *dialog_w); void destroy_group(group_t *group); void group_default_callback(callback_args_t *args);