Merge pull request #2 from zheiling/children-groups

Children groups
This commit is contained in:
2026-02-26 15:09:48 +02:00
committed by GitHub
33 changed files with 489 additions and 357 deletions
+9 -1
View File
@@ -1,15 +1,23 @@
# TODO:
## Current:
- [x] UI: vertical layout (needs for email in registration)
- [x] Nested groups
- [x] Create dynamic map of elements IDs and their pointers
- [x] Adapt modals to new value-forwarding method
- [ ] Move text to the end if text in the input is larger, than field
- [ ] More intuitive navigation between nested groups (by pressing left and right buttons)
## Features:
- [x] Search files
- [x] Correct spacing in the search bar
- [x] Finish registration
- [ ] UI: vertical layout (needs for email in registration)
- [ ] Get rid of old notification mechanism
- [ ] Privilege settings for files
- [ ] Files removal
- [ ] Encryption
- [ ] UTF-8 support
## Fixes:
- [ ] Check and fix registration and login
- [ ] Hotkeys for buttons
+2
View File
@@ -44,6 +44,7 @@ add_subdirectory(widget_core)
add_subdirectory(widget)
add_subdirectory(modals)
add_subdirectory(lib)
add_subdirectory(utils)
target_link_libraries(zbbs-client-tui
PRIVATE
@@ -51,5 +52,6 @@ target_link_libraries(zbbs-client-tui
widget
modals
bstring
utils
${CURSES_LIBRARIES}
)
+1
View File
@@ -44,6 +44,7 @@ int main(int argc, char **argv) {
q_args->buf = malloc(INBUFSIZE);
app->query_args = q_args;
q_args->file_list_ui = init_file_list(&(app->left_win), &(app->right_win));
draw_file_list(q_args->file_list_ui);
/* init client to connect to the server */
app->params->sd = init_client();
+8 -1
View File
@@ -3,7 +3,13 @@ add_library(modals STATIC)
file(GLOB M_HEADERS "*.h")
file(GLOB M_SOURCES "*.c")
target_link_libraries(modals PRIVATE widget widget_core bstring)
target_link_libraries(modals
PRIVATE
widget
widget_core
bstring
utils
)
target_sources(modals
PRIVATE
@@ -17,3 +23,4 @@ target_sources(modals
target_include_directories(modals PRIVATE "../widget")
target_include_directories(modals PRIVATE "../widget_core")
target_include_directories(modals PRIVATE "../lib/")
target_include_directories(widget PRIVATE "../utils/")
+2 -2
View File
@@ -25,7 +25,7 @@ void notification(const char *title, const char *message,
return;
group_el_init_t actions[] = {
{.type = w_button, .label = "OK", .is_default = 1}, {.type = w_end}};
{.type = w_button, .label = "OK", .is_default = true}, {.type = w_end}};
dialogue_t *d = malloc(sizeof(dialogue_t));
@@ -33,7 +33,7 @@ void notification(const char *title, const char *message,
d->w.callback = alert_cb;
d->g_content = NULL;
d->g_action = init_group(&(d->win), &(d->w), actions, horizontal);
d->g_action = init_group(&(d->win), &(d->w), actions,&(d->id_map), horizontal, g_action);
dialogue_init_active_id(d);
d->color_scheme = color;
+8 -15
View File
@@ -1,15 +1,10 @@
#include <stdint.h>
#include <string.h>
#include <ncurses.h>
// #include "../app.h"
// #include "../widget/dialogue.h"
// #include "../widget/group.h"
// #include "../widget/input.h"
// #include "../widget/button.h"
#include <widget.h>
#include <widget_core.h>
#include "../connection.h"
#include "group.h"
typedef struct {
button_t *element;
@@ -17,19 +12,17 @@ typedef struct {
} group_bt_t;
void asa_modal_dialogue_callback(callback_args_t *args) {
int32_t response;
callback_args_t d_args;
app_t *app = args->app;
dialogue_t *d = (dialogue_t *)app->active_widget;
memcpy(&d_args, args, sizeof(callback_args_t));
d_args.app = NULL;
d_args.resp_data = &response;
d_args.element = app->active_widget;
input_t *in_ip = d->g_content->elements[0].element;
input_t *in_port = d->g_content->elements[1].element;
dialogue_default_callback(&d_args);
if (response > -1) {
switch (response) {
if (d_args.resp_data.code == cbrp_val) {
switch (d_args.resp_data.val.val.num) {
case 0:
get_ip_port(app->params, in_ip->value, in_port->value);
connect_to_server(app);
@@ -51,8 +44,8 @@ dialogue_t *init_asa_modal(app_t *app) {
{.type = w_end}};
group_el_init_t actions[] = {
{.type = w_button, .label = "Connect", .is_default = 1},
{.type = w_button, .label = "Cancel", .is_default = 0},
{.type = w_button, .label = "Connect", .is_default = true, .val.num = 1},
{.type = w_button, .label = "Cancel", .is_default = false, .val.num = 2},
{.type = w_end}};
init_dialogue(&(app->modal), "Connect to server",
@@ -60,8 +53,8 @@ dialogue_t *init_asa_modal(app_t *app) {
dialogue_t *d = &(app->modal);
d->w.callback = asa_modal_dialogue_callback;
d->g_content = init_group(&(d->win), &(d->w), content, horizontal);
d->g_action = init_group(&(d->win), &(d->w), actions, horizontal);
d->g_content = init_group(&(d->win), &(d->w), content,&(d->id_map), horizontal, g_content);
d->g_action = init_group(&(d->win), &(d->w), actions,&(d->id_map), horizontal, g_action);
dialogue_init_active_id(d);
+4 -3
View File
@@ -1,3 +1,4 @@
#include "group.h"
#include <widget.h>
#include <ncurses.h>
#include <stdint.h>
@@ -16,7 +17,7 @@ dialogue_t *init_dwn_pr_modal(app_t *app, bool is_upload) {
sprintf(text, "%s file: %s", is_upload ? "Uploading" : "Downloading",
is_upload ? app->query_args->file->name : app->file_args->f_selected.name);
group_el_init_t actions[] = {
{.type = w_button, .label = "Cancel", .is_default = 1}, {.type = w_end}};
{.type = w_button, .label = "Cancel", .is_default = true, .val.num = 1}, {.type = w_end}};
app->modal.w.parent_win = &app->win;
init_dialogue(&(app->modal), is_upload ? "Upload" : "Download", text,
@@ -24,8 +25,8 @@ dialogue_t *init_dwn_pr_modal(app_t *app, bool is_upload) {
dialogue_t *d = &(app->modal);
d->w.callback = dwn_pr_modal_cb;
d->g_content = init_group(&(d->win), &(d->w), content, horizontal);
d->g_action = init_group(&(d->win), &(d->w), actions, horizontal);
d->g_content = init_group(&(d->win), &(d->w), content, &(d->id_map), horizontal, g_content);
d->g_action = init_group(&(d->win), &(d->w), actions, &(d->id_map), horizontal, g_action);
app->query_args->progress_bar = d->g_content->elements[0].element;
app->query_args->active_dialogue = d;
+9 -10
View File
@@ -1,3 +1,4 @@
#include "group.h"
#include <ncurses.h>
#include <stdint.h>
#include <stdlib.h>
@@ -12,20 +13,18 @@ typedef struct {
} group_bt_t;
void init_login_credentials_modal_cb(callback_args_t *args) {
int32_t response;
callback_args_t d_args;
app_t *app = args->app;
dialogue_t *d = (dialogue_t *)app->active_widget;
memcpy(&d_args, args, sizeof(callback_args_t));
d_args.app = NULL;
d_args.resp_data = &response;
d_args.element = app->active_widget;
input_t *in_name = d->g_content->elements[0].element;
input_t *in_pass = d->g_content->elements[1].element;
dialogue_default_callback(&d_args);
if (response > -1) {
switch (response) {
case 0:
if (d_args.resp_data.code == cbrp_val) {
switch (d_args.resp_data.val.val.num) {
case 1:
app->params->uname = malloc(in_name->value_len + 1);
app->params->pass = malloc(in_pass->value_len + 1);
strncpy(app->params->uname, in_name->value, in_name->value_len);
@@ -37,7 +36,7 @@ void init_login_credentials_modal_cb(callback_args_t *args) {
d->needs_destroy = true;
print_bars(app);
break;
case 1:
case 2:
app->query_args->state = S_ASK_LOGIN_TYPE;
app->modal.needs_destroy = true;
}
@@ -56,8 +55,8 @@ dialogue_t *init_login_credentials_modal(app_t *app) {
{.type = w_end}};
group_el_init_t actions[] = {
{.type = w_button, .label = "Login", .is_default = true},
{.type = w_button, .label = "Cancel", .is_default = false},
{.type = w_button, .label = "Login", .is_default = true, .val.num = 1},
{.type = w_button, .label = "Cancel", .is_default = false, .val.num = 2},
{.type = w_end}};
init_dialogue(&(app->modal), "Login", "Your login credentials",
@@ -65,8 +64,8 @@ dialogue_t *init_login_credentials_modal(app_t *app) {
dialogue_t *d = &(app->modal);
d->w.callback = init_login_credentials_modal_cb;
d->g_content = init_group(&(d->win), &(d->w), content, horizontal);
d->g_action = init_group(&(d->win), &(d->w), actions, horizontal);
d->g_content = init_group(&(d->win), &(d->w), content, &(d->id_map), horizontal, g_content);
d->g_action = init_group(&(d->win), &(d->w), actions, &(d->id_map), horizontal, g_action);
dialogue_init_active_id(d);
+12 -14
View File
@@ -1,3 +1,4 @@
#include "group.h"
#include <ncurses.h>
#include <stdint.h>
#include <stdlib.h>
@@ -12,30 +13,28 @@ typedef struct {
} group_bt_t;
void login_modal_option_cb(callback_args_t *args) {
int32_t response;
callback_args_t d_args;
app_t *app = args->app;
dialogue_t *d = (dialogue_t *)app->active_widget;
memcpy(&d_args, args, sizeof(callback_args_t));
d_args.app = NULL;
d_args.resp_data = &response;
d_args.element = app->active_widget;
dialogue_default_callback(&d_args);
if (response > -1) {
switch (response) {
case 0:
if (d_args.resp_data.code == cbrp_val) {
switch (d_args.resp_data.val.val.num) {
case 1:
d->needs_destroy = true;
app->params->uname = malloc(sizeof "anonymous");
strcpy(app->params->uname, "anonymous");
write(app->params->sd, app->params->uname, sizeof "anonymous"-1);
write(app->params->sd, app->params->uname, sizeof "anonymous" - 1);
app->query_args->state = S_WAIT_SERVER;
print_bars(app);
break;
case 1:
case 2:
d->needs_destroy = true;
app->query_args->state = S_ASK_LOGIN_USER;
break;
case 2:
case 3:
d->needs_destroy = true;
app->query_args->state = S_ASK_REGISTER;
break;
@@ -46,18 +45,17 @@ void login_modal_option_cb(callback_args_t *args) {
dialogue_t *init_login_option_modal(app_t *app) {
if (app == NULL)
return NULL;
group_el_init_t children[] = {{.type = w_button, .label = "Anonymous"},
{.type = w_button, .label = "User"},
{.type = w_button, .label = "Register"},
group_el_init_t children[] = {{.type = w_button, .label = "Anonymous", .val.num = 1},
{.type = w_button, .label = "User", .val.num = 2},
{.type = w_button, .label = "Register", .val.num = 3},
{.type = w_end}};
init_dialogue(&(app->modal), "Login",
"Select your login "
"option",
&(app->coordinates));
app->modal.g_action =
init_group(&(app->modal.win), &(app->modal.w), children,
horizontal);
app->modal.g_action = init_group(&(app->modal.win), &(app->modal.w), children,
&(app->modal.id_map), horizontal, g_action);
app->modal.w.callback = login_modal_option_cb;
dialogue_init_active_id(&(app->modal));
+5 -6
View File
@@ -1,3 +1,4 @@
#include "group.h"
#include <ncurses.h>
#include <stdint.h>
#include <stdlib.h>
@@ -5,21 +6,17 @@
#include <widget.h>
/* TODO: get rid of this mechanism */
typedef struct {
button_t *element;
enum w_type type;
} group_bt_t;
void init_notification_modal_cb(callback_args_t *args) {
int32_t response;
callback_args_t d_args;
app_t *app = args->app;
dialogue_t *d = (dialogue_t *)app->active_widget;
memcpy(&d_args, args, sizeof(callback_args_t));
d_args.app = NULL;
d_args.resp_data = &response;
d_args.element = app->active_widget;
dialogue_default_callback(&d_args);
@@ -32,7 +29,8 @@ dialogue_t *init_notification_modal(app_t *app) {
return NULL;
group_el_init_t actions[] = {
{.type = w_button, .label = "OK", .is_default = 1}, {.type = w_end}};
{.type = w_button, .label = "OK", .is_default = true, .val.num = 1},
{.type = w_end}};
init_dialogue(&(app->modal), "Notification", app->query_args->notification,
&(app->coordinates));
@@ -43,7 +41,8 @@ dialogue_t *init_notification_modal(app_t *app) {
d->w.callback = init_notification_modal_cb;
d->g_content = NULL;
d->g_action = init_group(&(d->win), &(d->w), actions, horizontal);
d->g_action = init_group(&(d->win), &(d->w), actions, &(d->id_map),
horizontal, g_action);
dialogue_init_active_id(d);
+38 -24
View File
@@ -8,6 +8,8 @@
#include <widget.h>
#include "alert.h"
#include "group.h"
#include "widget_core.h"
typedef struct {
button_t *element;
@@ -17,21 +19,23 @@ typedef struct {
void init_register_modal_cb(callback_args_t *args) {
char query[256];
int32_t qlen = 0;
int32_t response;
callback_args_t d_args;
app_t *app = args->app;
dialogue_t *d = (dialogue_t *)app->active_widget;
memcpy(&d_args, args, sizeof(callback_args_t));
d_args.app = NULL;
d_args.resp_data = &response;
d_args.element = app->active_widget;
input_t *in_name = d->g_content->elements[0].element;
input_t *in_pass = d->g_content->elements[1].element;
input_t *in_pass_r = d->g_content->elements[2].element;
group_t *g_email_user = d->g_content->elements[0].element;
group_t *g_passwords = d->g_content->elements[1].element;
input_t *in_name = g_email_user->elements[0].element;
input_t *in_email = g_email_user->elements[1].element;
input_t *in_pass = g_passwords->elements[0].element;
input_t *in_pass_r = g_passwords->elements[1].element;
dialogue_default_callback(&d_args);
if (response > -1) {
switch (response) {
case 0:
if (d_args.resp_data.code == cbrp_val &&
d_args.resp_data.val.type == val_num) {
switch (d_args.resp_data.val.val.num) {
case 1:
if (strcmp(in_pass->value, in_pass_r->value)) {
alert("Your passwords do not match");
in_pass->value[0] = '\0';
@@ -46,12 +50,12 @@ void init_register_modal_cb(callback_args_t *args) {
app->params->uname[in_name->value_len] = 0;
strncpy(app->params->pass, in_pass->value, in_pass->value_len);
app->params->pass[in_pass->value_len] = 0;
sprintf(query, "register %s %s\n%n", app->params->uname, app->params->pass,
&qlen);
sprintf(query, "register %s %s %*s\n%n", app->params->uname,
app->params->pass, (int) in_email->value_len, in_email->value, &qlen);
write(app->params->sd, query, qlen);
app->query_args->state = S_WAIT_REGISTER_CONFIRMATION;
break;
case 1:
case 2:
app->query_args->state = S_ASK_LOGIN_TYPE;
app->modal.needs_destroy = true;
}
@@ -61,21 +65,29 @@ void init_register_modal_cb(callback_args_t *args) {
dialogue_t *init_register_modal(app_t *app) {
if (app == NULL)
return NULL;
group_el_init_t content_name_email[] = {
{.type = w_input, .label = "Username", .length = 18},
{.type = w_input, .label = "Email", .length = 18},
{.type = w_end}};
group_el_init_t content_pass[] = {{.type = w_input,
.label = "Password",
.length = 18,
.is_hidden_value = true},
{.type = w_input,
.label = "Password (repeat)",
.length = 18,
.is_hidden_value = true},
{.type = w_end}};
group_el_init_t content[] = {
{.type = w_input, .label = "Username", .length = 15},
{.type = w_input,
.label = "Password",
.length = 15,
.is_hidden_value = true},
{.type = w_input,
.label = "Password (repeat)",
.length = 15,
.is_hidden_value = true},
{.type = w_group, .direction = vertical, .children = content_name_email},
{.type = w_group, .direction = vertical, .children = content_pass},
{.type = w_end}};
group_el_init_t actions[] = {
{.type = w_button, .label = "Register", .is_default = true},
{.type = w_button, .label = "Cancel", .is_default = false},
{.type = w_button, .label = "Register", .is_default = true, .val.num = 1},
{.type = w_button, .label = "Cancel", .is_default = false, .val.num = 2},
{.type = w_end}};
init_dialogue(&(app->modal), "Credentials", "There is information needed",
@@ -83,8 +95,10 @@ dialogue_t *init_register_modal(app_t *app) {
dialogue_t *d = &(app->modal);
d->w.callback = init_register_modal_cb;
d->g_content = init_group(&(d->win), &(d->w), content, horizontal);
d->g_action = init_group(&(d->win), &(d->w), actions, horizontal);
d->g_content = init_group(&(d->win), &(d->w), content, &(d->id_map),
horizontal, g_content);
d->g_action = init_group(&(d->win), &(d->w), actions, &(d->id_map),
horizontal, g_action);
dialogue_init_active_id(d);
+6 -7
View File
@@ -1,3 +1,4 @@
#include "group.h"
#include <ncurses.h>
#include <stdint.h>
#include <stdlib.h>
@@ -11,18 +12,16 @@ typedef struct {
} group_bt_t;
void server_message_modal_cb(callback_args_t *args) {
int32_t response;
callback_args_t d_args;
app_t *app = args->app;
dialogue_t *d = (dialogue_t *)app->active_widget;
memcpy(&d_args, args, sizeof(callback_args_t));
d_args.app = NULL;
d_args.resp_data = &response;
d_args.element = app->active_widget;
dialogue_default_callback(&d_args);
if (response > -1) {
switch (response) {
case 0:
if (d_args.resp_data.code == cbrp_val) {
switch (d_args.resp_data.val.val.num) {
case 1:
d->needs_destroy = true;
/* TODO: macros */
free(app->query_args->server_message.text);
@@ -39,12 +38,12 @@ void *init_server_message_modal(app_t *app) {
if (app == NULL)
return NULL;
group_el_init_t children[] = {
{.type = w_button, .label = "OK", .is_default = 1}, {.type = w_end}};
{.type = w_button, .label = "OK", .is_default = true, .val.num = 1}, {.type = w_end}};
init_dialogue(&(app->modal), "Server response",
app->query_args->server_message.text, &(app->coordinates));
app->modal.g_action =
init_group(&(app->modal.win), &(app->modal.w), children, horizontal);
init_group(&(app->modal.win), &(app->modal.w), children, &(app->modal.id_map), horizontal, g_action);
app->modal.w.callback = server_message_modal_cb;
dialogue_init_active_id(&(app->modal));
+22 -19
View File
@@ -1,34 +1,35 @@
#include "../file_processor.h"
#include <widget.h>
#include "group.h"
#include <ncurses.h>
#include <stdint.h>
#include <string.h>
#include <widget.h>
void upload_dialogue_modal_cb(callback_args_t *args) {
int32_t response = -1;
callback_args_t d_args;
app_t *app = args->app;
dialogue_t *d = (dialogue_t *)app->active_widget;
memcpy(&d_args, args, sizeof(callback_args_t));
d_args.app = NULL;
d_args.resp_data = &response;
d_args.element = app->active_widget;
dialogue_default_callback(&d_args);
ui_fs_file_list_t *fui =
(ui_fs_file_list_t *)d->g_content->elements[0].element;
switch (response) {
case 0:
app->query_args->state = S_WAIT_SERVER;
d->needs_destroy = true;
break;
case 1:
file_upload_open(fui->d_path, fui->current->name, app->query_args);
d->needs_destroy = true;
app->query_args->state = S_UPLOAD_PARAMS;
break;
case -2:
d->needs_destroy = true;
app->query_args->state = WAIT_CLIENT;
if (d_args.resp_data.code == cbrp_val) {
switch (d_args.resp_data.val.val.num) {
case 0:
app->query_args->state = S_WAIT_SERVER;
d->needs_destroy = true;
break;
case 1:
file_upload_open(fui->d_path, fui->current->name, app->query_args);
d->needs_destroy = true;
app->query_args->state = S_UPLOAD_PARAMS;
break;
case -2:
d->needs_destroy = true;
app->query_args->state = WAIT_CLIENT;
}
}
}
@@ -41,7 +42,7 @@ dialogue_t *init_upload_dialogue_modal(app_t *app) {
{.type = w_end}};
group_el_init_t actions[] = {
{.type = w_button, .label = "Cancel", .is_default = 0}, {.type = w_end}};
{.type = w_button, .label = "Cancel", .is_default = false, .val.num = 0}, {.type = w_end}};
app->modal.w.parent_win = &app->win;
init_dialogue(&(app->modal), "Upload new file", "Enter essential data",
@@ -49,8 +50,10 @@ dialogue_t *init_upload_dialogue_modal(app_t *app) {
dialogue_t *d = &(app->modal);
d->w.callback = upload_dialogue_modal_cb;
d->g_content = init_group(&(d->win), &(d->w), content, horizontal);
d->g_action = init_group(&(d->win), &(d->w), actions, horizontal);
d->g_content = init_group(&(d->win), &(d->w), content, &(d->id_map),
horizontal, g_content);
d->g_action = init_group(&(d->win), &(d->w), actions, &(d->id_map),
horizontal, g_action);
app->query_args->active_dialogue = d;
+7 -8
View File
@@ -1,3 +1,4 @@
#include "group.h"
#include <widget.h>
#include <ncurses.h>
#include <stdint.h>
@@ -7,20 +8,18 @@
#include <unistd.h>
void upload_props_dialogue_modal_cb(callback_args_t *args) {
int32_t response = -1;
callback_args_t d_args;
app_t *app = args->app;
dialogue_t *d = (dialogue_t *)app->active_widget;
memcpy(&d_args, args, sizeof(callback_args_t));
d_args.app = NULL;
d_args.resp_data = &response;
d_args.element = app->active_widget;
dialogue_default_callback(&d_args);
char query[256];
int32_t query_len = 0;
input_t *desc_input = (input_t *)d->g_content->elements[0].element;
if (response > -1) {
switch (response) {
if (d_args.resp_data.code == cbrp_val) {
switch (d_args.resp_data.val.val.num) {
case 0:
query_len =
sprintf(query, "file upload \"%s\" %zu 1\n",
@@ -53,8 +52,8 @@ dialogue_t *init_upload_props_dialogue_modal(app_t *app) {
{.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_button, .label = "Upload", .is_default = true},
{.type = w_button, .label = "Cancel", .is_default = false},
{.type = w_end},
};
@@ -64,8 +63,8 @@ dialogue_t *init_upload_props_dialogue_modal(app_t *app) {
dialogue_t *d = &(app->modal);
d->w.callback = upload_props_dialogue_modal_cb;
d->g_content = init_group(&(d->win), &(d->w), content, horizontal);
d->g_action = init_group(&(d->win), &(d->w), actions, horizontal);
d->g_content = init_group(&(d->win), &(d->w), content, &(d->id_map), horizontal, g_content);
d->g_action = init_group(&(d->win), &(d->w), actions, &(d->id_map), horizontal, g_action);
app->query_args->active_dialogue = d;
+5 -3
View File
@@ -16,7 +16,6 @@
#include <time.h>
#include <unistd.h>
#include "app.h"
#include "connection.h"
#include "draw_modal.h"
#include "file_processor.h"
@@ -25,6 +24,7 @@
#include "server.h"
#include "types.h"
#include "widget/app.h"
#include "widget_core/widget_core.h"
static void wait_side(app_t *app);
void user_request_description(query_args_t *q_args);
@@ -45,8 +45,10 @@ void query_loop(app_t *app) {
size_t qlen;
int sr;
static file_args_t file_args;
callback_args_t d_args = {
.app = app, .element = NULL, .data = NULL, .resp_data = NULL};
callback_args_t d_args = {.app = app,
.element = NULL,
.data = NULL,
.resp_data.code = cbrc_none};
init_file_args(&file_args);
query_args->sd = sd;
+15
View File
@@ -0,0 +1,15 @@
add_library(utils STATIC)
file(GLOB M_HEADERS "*.h")
file(GLOB M_SOURCES "*.c")
list(REMOVE_ITEM M_HEADERS "utils.h")
target_sources(utils
PRIVATE
${M_SOURCES}
PUBLIC
FILE_SET HEADERS
FILES
${M_HEADERS}
)
+34
View File
@@ -0,0 +1,34 @@
#include "d_array.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
void init_d_arr_ptr(d_array_ptr_t *arr, int64_t init_capacity) {
arr->capacity = init_capacity;
arr->length = 0;
arr->arr = malloc(sizeof(void *) * init_capacity);
arr->fist_el = NULL;
arr->last_el = NULL;
memset(arr->arr, 0, init_capacity);
}
void add_d_arr_ptr(d_array_ptr_t *arr, void *ptr, int64_t idx) {
int64_t new_capacity = idx * 2;
if (idx > arr->capacity - 1) {
arr->arr = realloc(arr->arr, new_capacity);
memset(arr->arr+arr->capacity, 0, arr->capacity - new_capacity);
arr->capacity = new_capacity;
}
if (arr->fist_el == NULL) arr->fist_el = ptr;
arr->last_el = ptr;
arr->arr[idx] = ptr;
arr->length = idx+1;
}
void free_d_arr(d_array_ptr_t *arr) {
arr->capacity = 0;
arr->length = 0;
free(arr->arr);
arr->arr = NULL;
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef D_ARRAY_H
#define D_ARRAY_H
/* Dynamic array of numbers */
#include <stdint.h>
typedef struct d_array_ptr_t {
int64_t capacity;
int64_t length;
void **arr;
void *fist_el;
void *last_el;
} d_array_ptr_t;
void init_d_arr_ptr(d_array_ptr_t *arr, int64_t init_capacity);
void add_d_arr_ptr(d_array_ptr_t *arr, void *ptr, int64_t idx);
void free_d_arr(d_array_ptr_t *arr);
#endif
+4
View File
@@ -0,0 +1,4 @@
#ifndef D_UTILS_H
#define D_UTILS_H
#include "d_array.h"
#endif
+2
View File
@@ -18,7 +18,9 @@ target_link_libraries(widget
PRIVATE
bstring
widget_core
utils
)
target_include_directories(widget PRIVATE "../widget_core")
target_include_directories(widget PRIVATE "../lib/")
target_include_directories(widget PRIVATE "../utils/")
-1
View File
@@ -10,7 +10,6 @@
typedef enum {
modal_color_pair = 3,
modal_border_color_pair = 4,
} color;
typedef enum {
+10 -2
View File
@@ -21,8 +21,16 @@ button_t *init_button(WINDOW **win, widget_t *w_parent, char *label) {
int32_t draw_button(button_t *btn, uint32_t active_id) {
char title[DIALOGUE_TITLE + 6];
WINDOW *win = *(btn->w.parent_win);
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;
uint32_t margin_y = btn->w.m_y;
uint32_t margin_x = btn->w.m_x;
widget_t *w_par = btn->w.w_parent;
while (w_par->parent_win == btn->w.parent_win) {
margin_y += w_par->m_y;
margin_x += w_par->m_x;
w_par = w_par->w_parent;
}
if (btn->w.id == active_id) {
sprintf(title, "[< %s >]", btn->w.title);
-1
View File
@@ -1,7 +1,6 @@
#ifndef BUTTON_H
#define BUTTON_H
#include "../main.h"
#include <widget_core.h>
#include <stdint.h>
+91 -149
View File
@@ -8,26 +8,42 @@
#include "file_list.h"
#include "group.h"
#include "input.h"
#include "widget_core.h"
#define INCR_ACTIVE_ID(d, current, next) \
if (d->active.id != d->current->last_id) { \
d->active.id = d->active.id + 1; \
} else if (d->next != NULL) { \
d->active.id = d->next->first_id; \
d->active.type = next; \
} else { \
d->active.id = d->current->first_id; \
void incr_active_id(dialogue_t *d) {
group_el_t *active_el = NULL;
while (true) {
for (int i = d->active_el->id + 1;
active_el == NULL && d->id_map.length > i; i++) {
active_el = d->id_map.arr[i];
}
d->active_el = active_el;
if (d->active_el == NULL) {
d->active_el = d->id_map.fist_el;
break;
} else if (d->active_el->type != w_box && d->active_el->type != w_group) {
break;
}
active_el = NULL;
}
}
#define DECR_ACTIVE_ID(d, current, next) \
if (d->active.id != d->current->first_id) { \
d->active.id = d->active.id - 1; \
} else if (d->next != NULL) { \
d->active.id = d->next->last_id; \
d->active.type = next; \
} else { \
d->active.id = d->current->last_id; \
void decr_active_id(dialogue_t *d) {
group_el_t *active_el = NULL;
while (true) {
for (int i = d->active_el->id - 1; active_el == NULL && i > 0; i--) {
active_el = d->id_map.arr[i];
}
d->active_el = active_el;
if (d->active_el == NULL) {
d->active_el = d->id_map.last_el;
break;
} else if (d->active_el->type != w_box && d->active_el->type != w_group) {
break;
}
active_el = NULL;
}
}
#define CH_GROUP(d, current, next) \
{ \
@@ -42,118 +58,78 @@
} \
}
widget_t *get_active_widget(dialogue_t *d) {
group_t *g;
if (d->active.type == g_action) {
g = d->g_action;
} else {
g = d->g_content;
}
widget_t *w = (widget_t *)g->elements[d->active.id - g->first_id].element;
return w;
}
void dialogue_default_callback(callback_args_t *args) {
dialogue_t *d = (void *)args->element;
int32_t key = *((int32_t *)args->data);
callback_args_t new_args;
int32_t *resp_value = (int32_t *)args->resp_data;
memcpy(&new_args, args, sizeof(callback_args_t));
new_args.active_id = d->active.id;
new_args.active_el = d->active_el;
int32_t diff;
d->needs_update = true;
input_t *input;
widget_t *widget;
switch (key) {
case '\t':
if (d->active.type == g_content) {
INCR_ACTIVE_ID(d, g_content, g_action);
} else if (d->active.type == g_action) {
INCR_ACTIVE_ID(d, g_action, g_content);
}
*resp_value = -1;
incr_active_id(d);
args->resp_data.code = cbrc_none;
break;
case '\33': /* Esc key */
*resp_value = -2;
args->resp_data.code = cbrp_val;
args->resp_data.val.val.num = -2;
break;
case KEY_RIGHT:
if (d->active.type == g_content) {
if (d->g_content->elements[d->active.id - d->g_content->first_id].type ==
w_input) {
input = d->g_content->elements[d->active.id - d->g_content->first_id]
.element;
if (input->cur_pos > 0) {
input->cur_pos -= 1;
}
} else {
INCR_ACTIVE_ID(d, g_content, g_action);
}
} else if (d->active.type == g_action) {
INCR_ACTIVE_ID(d, g_action, g_content);
}
*resp_value = -1;
incr_active_id(d);
args->resp_data.code = cbrc_none;
break;
case KEY_LEFT:
if (d->active.type == g_content) {
if (d->g_content->elements[d->active.id - d->g_content->first_id].type ==
w_input) {
input = d->g_content->elements[d->active.id - d->g_content->first_id]
.element;
if (input->value_len > input->cur_pos) {
input->cur_pos += 1;
}
} else {
DECR_ACTIVE_ID(d, g_content, g_action);
}
} else if (d->active.type == g_action) {
DECR_ACTIVE_ID(d, g_action, g_content);
}
*resp_value = -1;
decr_active_id(d);
args->resp_data.code = cbrc_none;
break;
case '\n':
widget = get_active_widget(d);
widget = (widget_t *)d->active_el->element;
if (widget->callback != NULL) { /* Existing callback case */
new_args.element = widget;
widget->callback(&new_args);
break;
} /* Default cases */
if (d->active.type == g_action) {
if (d->active_el->g_type == g_action) {
new_args.element = d->g_action;
group_default_callback(&new_args);
mempcpy(&(args->resp_data), &(new_args.resp_data),
sizeof(new_args.resp_data));
} else if (d->g_action != NULL) {
for (int i = 0; i < d->g_action->count; i++) {
if (d->g_action->elements[i].is_default) {
*resp_value = i;
args->resp_data.code = cbrp_val;
args->resp_data.val.val.num = i;
return;
}
}
} else {
/* TODO: temp solution, improve */
*resp_value = d->active.id - d->g_content->first_id;
args->resp_data.code = cbrp_val;
args->resp_data.val.val.num = d->active_el->idx;
return;
}
break;
case KEY_UP:
if (d->g_content->elements[d->active.id - d->g_content->first_id].type ==
w_fs_file_list) {
if (d->active_el->type == w_fs_file_list) {
new_args.element = d->g_content;
group_default_callback(&new_args);
} else {
CH_GROUP(d, g_action, g_content);
/* CH_GROUP(d, g_action, g_content); */
}
break;
case KEY_DOWN:
if (d->g_content->elements[d->active.id - d->g_content->first_id].type ==
w_fs_file_list) {
if (d->active_el->type == w_fs_file_list) {
new_args.element = d->g_content;
group_default_callback(&new_args);
} else {
CH_GROUP(d, g_content, g_action);
/* CH_GROUP(d, g_content, g_action); */
}
break;
default:
/* run callback function */
if (d->active.type == g_content) {
if (d->active_el->g_type == g_content) {
new_args.element = d->g_content;
} else {
new_args.element = d->g_action;
@@ -178,67 +154,42 @@ void init_dialogue(dialogue_t *dialogue, const char title[], const char text[],
strcpy(dialogue->w.title, title);
t_size = strlen(text);
strcpy(dialogue->text, text);
init_d_arr_ptr(&(dialogue->id_map), MAX_IDS);
/* trim the last new line symbol */
if (t_size && dialogue->text[t_size-1] == '\n') dialogue->text[t_size-1] = '\0';
if (t_size && dialogue->text[t_size - 1] == '\n')
dialogue->text[t_size - 1] = '\0';
}
int group_init_active_id(group_t *g, dialogue_t *d) {
enum w_type wt;
for (int i = 0; i < g->count; i++) {
wt = g->elements[i].type;
if (wt == w_button || wt == w_input ||
wt == w_fs_file_list) { /* Add here new types */
d->active_el = g->elements + i;
return 1;
} else if (wt == w_group) {
group_t *child_g = g->elements[i].element;
return group_init_active_id(child_g, d);
}
}
return 0;
}
void dialogue_init_active_id(dialogue_t *dialogue) {
enum w_type widget_type;
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 ||
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;
return;
}
if (group_init_active_id(dialogue->g_content, dialogue)) {
return;
}
}
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 ||
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;
return;
}
if (group_init_active_id(dialogue->g_action, dialogue)) {
return;
}
}
}
// void dialogue_init_active_id(dialogue_t *dialogue) {
// enum w_type widget_type;
// 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 ||
// 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;
// break;
// }
// }
// } 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 ||
// 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;
// break;
// }
// }
// }
// }
#define DETECT_GROUP_SIZE(group, line_max_len, y, x) \
if (group) { \
group->w.m_y = y; \
@@ -259,7 +210,6 @@ int32_t draw_dialogue(dialogue_t *d) {
}
group_el_t *ae_ptr = NULL; /* active element */
uint32_t ae_idx; /* active element */
/* count dimensions */
uint32_t x = 1; /* when uses box */
uint32_t y = 1; /* when uses box */
@@ -317,33 +267,25 @@ int32_t draw_dialogue(dialogue_t *d) {
wattroff(d->win, A_REVERSE);
if (d->g_content != NULL) {
draw_group(d->win, d->g_content, d->active.id, &(d->w));
draw_group(d->win, d->g_content, d->active_el->id);
}
if (d->g_action != NULL) {
draw_group(d->win, d->g_action, d->active.id, &(d->w));
draw_group(d->win, d->g_action, d->active_el->id);
}
/* move cursor */
if (d->g_content != NULL) {
FIND_ACTIVE_ELEMENT(d->g_content, d->active.id, ae_ptr, ae_idx);
}
if (ae_ptr == NULL && d->g_action != NULL) {
FIND_ACTIVE_ELEMENT(d->g_action, d->active.id, ae_ptr, ae_idx);
}
if (ae_ptr != NULL && ae_ptr->id == d->active.id) {
if (ae_ptr->type == w_input) {
input_t *input = ae_ptr->element;
d->w.cur.y = input->w.cur.y;
d->w.cur.x = input->w.cur.x + input->value_len;
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(true);
}
} else {
curs_set(false);
if (d->active_el != NULL && d->active_el->type == w_input) {
input_t *input = d->active_el->element;
d->w.cur.y = input->w.cur.y;
d->w.cur.x = input->w.cur.x + input->value_len;
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(true);
}
} else {
curs_set(false);
}
d->needs_update = false;
+7 -8
View File
@@ -6,8 +6,9 @@
#include <ncurses.h>
#include <stdint.h>
#include <widget_core.h>
#include <utils.h>
#define MAX_IDS 64
enum g_type { g_content, g_action };
enum d_color_scheme { dc_normal, dc_alert };
typedef struct {
@@ -15,16 +16,14 @@ typedef struct {
WINDOW *win;
group_t *g_content;
group_t *g_action;
struct {
int32_t id;
enum g_type type;
} active;
group_el_t *active_el;
char text[DIALOGUE_TEXT];
uint32_t is_initiated : 1;
uint32_t needs_update : 1;
uint32_t needs_destroy : 1;
bool is_initiated;
bool needs_update;
bool needs_destroy;
coordinates_t *p_coordinates;
enum d_color_scheme color_scheme;
d_array_ptr_t id_map;
} dialogue_t;
void init_dialogue(dialogue_t *d, const char title[], const char text[],
+9 -2
View File
@@ -114,6 +114,8 @@ ui_file_list_t *init_file_list(WINDOW **win, WINDOW *const *info_win) {
fui->max_lines = getmaxy(parent_win) - 3; /* 2+1 (bottom info line) */
fui->active_search = false;
fui->search_key = bfromcstrrangealloc(12, 64, "");
fui->start = NULL;
fui->current = NULL;
return fui;
}
@@ -135,11 +137,16 @@ void draw_file_list(ui_file_list_t *fui) {
int32_t sz_y_f = sz_y - 2; /* TODO: можно заменить на поле max_lines */
p_y = 1;
p_x = 1;
fl_item_t *el = *(fui->start);
fl_item_t *active_el = *(fui->start);
fl_item_t *el = NULL;
fl_item_t *active_el = NULL;
int32_t cur_el_idx = 0;
curs_set(false);
if (fui->start != NULL) {
el = *(fui->start);
active_el = el;
}
if (fui->activate_last) {
fui->current_idx = fui->current_count - 1;
fui->activate_last = false;
+1 -1
View File
@@ -133,7 +133,7 @@ void fs_file_list_cb(callback_args_t *args) {
}
break;
case '\n':
select_item(fui, (int32_t *) args->resp_data);
select_item(fui, (int32_t *) args->resp_data.val.val.num);
break;
}
}
+63 -26
View File
@@ -1,37 +1,33 @@
#include "group.h"
#include "button.h"
#include "d_array.h"
#include "fs_file_list.h"
#include "input.h"
#include "progress_bar.h"
#include "widget_core.h"
#include <ncurses.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#define MAKE_RESPONSE_M1(args, resp_data, response) \
if (args->resp_data != NULL) { \
*response = -1; \
}
#include <utils.h>
void group_default_callback(callback_args_t *args) {
group_t *g = (group_t *)args->element;
int32_t key = *((int32_t *)args->data);
int32_t *response = (int32_t *)args->resp_data;
int64_t response = args->resp_data.val.val.num;
input_t *input;
widget_t *widget;
group_el_t *element_ptr;
int32_t element_idx = -1;
group_el_t *element_ptr = args->active_el;
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);
*response = element_idx;
args->resp_data.code = cbrp_val;
mempcpy(&(args->resp_data.val), &(element_ptr->val), sizeof(struct val_t));
break;
case KEY_BACKSPACE:
case KEY_DL:
FIND_ACTIVE_ELEMENT(g, args->active_id, element_ptr, element_idx);
if (element_ptr->type == w_input) {
input = (input_t *)element_ptr->element;
if (input->value_len) {
@@ -44,10 +40,9 @@ void group_default_callback(callback_args_t *args) {
}
}
}
MAKE_RESPONSE_M1(args, resp_data, response);
args->resp_data.code = cbrc_none;
break;
default:
FIND_ACTIVE_ELEMENT(g, args->active_id, element_ptr, element_idx);
if (element_ptr->type == w_input) {
input = (input_t *)element_ptr->element;
if (input->max_len > input->value_len) {
@@ -62,7 +57,8 @@ void group_default_callback(callback_args_t *args) {
}
}
} else {
widget = (widget_t *) element_ptr->element;
/* callback case */
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;
@@ -70,14 +66,22 @@ void group_default_callback(callback_args_t *args) {
break;
}
}
MAKE_RESPONSE_M1(args, resp_data, response);
args->resp_data.code = cbrc_none;
break;
}
}
union current_element {
group_t *group;
enum w_type type;
};
group_t *init_group(WINDOW **win, widget_t *w_parent, group_el_init_t *children,
enum g_direction direction) {
d_array_ptr_t *id_map, enum g_direction direction, enum g_type g_type) {
group_t *group = malloc(sizeof(group_t));
union current_element current;
group->parent_group = NULL;
current.type = w_end;
init_widget(&(group->w), w_parent, win, "");
/* count elements */
group->count = 0;
@@ -93,6 +97,9 @@ group_t *init_group(WINDOW **win, widget_t *w_parent, group_el_init_t *children,
for (int32_t i = 0; i < group->count; i++) {
elements[i].type = children[i].type;
elements[i].is_default = children[i].is_default;
elements[i].g_type = g_type;
elements[i].idx = i;
elements[i].val.type = val_nul;
}
/* init child elements */
@@ -101,12 +108,27 @@ group_t *init_group(WINDOW **win, widget_t *w_parent, group_el_init_t *children,
switch (elements[i].type) {
case w_button:
elements[i].element = init_button(win, &(group->w), children[i].label);
elements[i].val.type = val_num;
elements[i].val.val.num = children[i].val.num;
w = &(((button_t *)elements[i].element)->w);
break;
case w_box:
case w_group:
case w_end:
break;
case w_group:
elements[i].element = init_group(win, &(group->w), children[i].children,
id_map, children[i].direction, g_type);
w = &(((group_t *)elements[i].element)->w);
current.group = (group_t *)elements[i].element;
current.group->parent_group = group;
if (i == 0) {
group->first_id = current.group->first_id;
group->last_id = current.group->last_id;
} else {
group->last_id = current.group->last_id;
}
current.type = w_group;
break;
case w_input:
elements[i].element =
init_input(win, &(group->w), children[i].label, children[i].length,
@@ -122,28 +144,39 @@ group_t *init_group(WINDOW **win, widget_t *w_parent, group_el_init_t *children,
w = &(((ui_progress_bar_t *)elements[i].element)->w);
break;
}
if (current.type != w_group) {
if (i == 0) {
group->first_id = w->id;
group->last_id = w->id;
} else {
group->last_id = w->id;
}
}
/* set dimensions */
elements[i].id = w->id;
add_d_arr_ptr(id_map, elements + i, w->id);
if (direction == horizontal) {
w->m_x = group->w.m_x + 1 + group->w.x;
w->m_y = group->w.m_y;
group->w.x += w->x + 1;
if (group->w.y < w->y)
group->w.y = w->y;
}
if (i == 0) {
group->first_id = w->id;
group->last_id = w->id;
} else {
group->last_id = w->id;
w->m_x = group->w.m_x;
w->m_y = group->w.m_y + group->w.y;
group->w.y += w->y;
if (group->w.x < w->x)
group->w.x = w->x;
}
}
if (direction == vertical)
group->w.y++;
return group;
}
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) {
group_el_t *children = group->elements;
for (int i = 0; i < group->count; i++) {
group_el_t *el = &children[i];
@@ -151,8 +184,10 @@ void draw_group(WINDOW *win, group_t *group, int32_t active_id,
case w_button:
draw_button((button_t *)el->element, active_id);
break;
case w_box:
case w_group:
draw_group(win, (group_t *)el->element, active_id);
break;
case w_box:
case w_end:
break;
case w_input:
@@ -176,8 +211,10 @@ void destroy_group(group_t *group) {
case w_button:
destroy_button(el->element);
break;
case w_box:
case w_group:
destroy_group(el->element);
break;
case w_box:
case w_end:
break;
case w_input:
+14 -23
View File
@@ -2,44 +2,35 @@
#define GROUP_H
#include <stdint.h>
#include <utils.h>
#include <widget_core.h>
enum g_direction {
horizontal,
vertical,
};
typedef struct {
uint32_t id;
void *element;
typedef struct group_el_init_t {
enum w_type type;
uint32_t is_default : 1;
} group_el_t;
typedef struct {
enum w_type type;
uint32_t is_default : 1;
uint32_t is_hidden_value : 1;
bool is_default;
bool is_hidden_value;
char label[DIALOGUE_TITLE];
uint32_t length;
enum g_direction direction;
union {
int64_t num;
} val;
struct group_el_init_t *children;
} group_el_init_t;
typedef struct {
typedef struct group_t {
widget_t w;
group_el_t *elements;
enum g_direction direction;
uint32_t count;
uint32_t first_id, last_id;
struct group_t *parent_group;
} group_t;
#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);
d_array_ptr_t *id_map, enum g_direction dir,
enum g_type g_type);
void draw_group(WINDOW *win, group_t *group, int32_t active_id);
void destroy_group(group_t *group);
void group_default_callback(callback_args_t *args);
+24 -11
View File
@@ -4,16 +4,16 @@
#include <string.h>
#include "app.h"
#include <widget_core.h>
#include "input.h"
#include <widget_core.h>
input_t *init_input(WINDOW **win, widget_t *w_parent, char *label,
uint32_t length, uint32_t is_hidden_value) {
input_t *input = malloc(sizeof(input_t));
init_widget(&(input->w), w_parent, win, label);
input->is_disabled = 0;
input->w.y = 3; // with borders
input->w.x = length + 3; // with borders and extra space for the last element
input->w.y = 3; // with borders
input->w.x = length + 3; // with borders and extra space for the last element
uint32_t t_len = strlen(input->w.title) + 4; // with borders and space
if (input->w.x < t_len)
input->w.x = t_len;
@@ -29,16 +29,26 @@ input_t *init_input(WINDOW **win, widget_t *w_parent, char *label,
int32_t draw_input(input_t *input, uint32_t active_id) {
const char stars[] = "*******************";
WINDOW *win = *(input->w.parent_win);
uint32_t margin_y = input->w.m_y + input->w.w_parent->m_y;
uint32_t margin_x = input->w.m_x + input->w.w_parent->m_x;
uint32_t margin_y = input->w.m_y;
uint32_t margin_x = input->w.m_x;
wattrset(win, COLOR_PAIR(modal_color_pair));
/* counts margins of the ancestors of the same window */
widget_t *w_par = input->w.w_parent;
while (w_par->parent_win == input->w.parent_win) {
margin_y += w_par->m_y;
margin_x += w_par->m_x;
w_par = w_par->w_parent;
}
if (input->w.id == active_id) {
wattrset(win, COLOR_PAIR(3));
} else {
wattrset(win, COLOR_PAIR(0) | A_REVERSE | A_BOLD);
}
mvwhline(win, margin_y, margin_x, 0, input->w.x);
mvwhline(win, margin_y + 2, margin_x, 0, input->w.x);
mvwprintw(win, margin_y, margin_x + 1, " %s ", input->w.title);
// left
mvwvline(win, margin_y, margin_x, ACS_ULCORNER, 1);
mvwvline(win, margin_y + 1, margin_x, 0, 1);
@@ -48,6 +58,9 @@ int32_t draw_input(input_t *input, uint32_t active_id) {
mvwvline(win, margin_y + 1, margin_x + input->w.x - 1, 0, 1);
mvwvline(win, margin_y + 2, margin_x + input->w.x - 1, ACS_LRCORNER, 1);
wattrset(win, COLOR_PAIR(0) | A_REVERSE);
mvwprintw(win, margin_y, margin_x + 1, " %s ", input->w.title);
margin_x++;
if (input->w.id == active_id) {
@@ -57,11 +70,11 @@ int32_t draw_input(input_t *input, uint32_t active_id) {
}
if (input->is_hidden) {
mvwprintw(win, margin_y + 1, margin_x, "%.*s%*s", (int) input->value_len, stars,
input->w.x - input->value_len - 2, "");
mvwprintw(win, margin_y + 1, margin_x, "%.*s%*s", (int)input->value_len,
stars, (int)(input->w.x - input->value_len - 2), "");
} else {
mvwprintw(win, margin_y + 1, margin_x, "%s%*s", input->value,
input->w.x - input->value_len - 2, "");
(int)(input->w.x - input->value_len - 2), "");
}
input->w.cur.y = margin_y + 1;
+5 -5
View File
@@ -8,11 +8,11 @@
typedef struct {
widget_t w;
char value[INPUT_TEXT];
uint32_t cur_pos; /* is relative to the end of a string */
uint32_t value_len;
uint32_t max_len;
uint32_t is_disabled : 1;
uint32_t is_hidden : 1;
int64_t cur_pos; /* is relative to the end of a string */
int64_t value_len;
int64_t max_len;
bool is_disabled;
bool is_hidden;
} input_t;
input_t *init_input(WINDOW **win, widget_t *w_parent, char *label,
-1
View File
@@ -8,5 +8,4 @@
#include "group.h"
#include "input.h"
#include "progress_bar.h"
#endif
+52 -11
View File
@@ -5,6 +5,13 @@
#include <ncurses.h>
#include <stdint.h>
enum g_type { g_content, g_action };
enum g_direction {
horizontal,
vertical,
};
enum w_type {
w_end,
w_button,
@@ -15,12 +22,46 @@ enum w_type {
w_fs_file_list,
};
enum val_type {
val_num,
val_ptr,
val_nul,
};
struct val_t {
enum val_type type;
union {
void *ptr;
int64_t num;
} val;
};
typedef struct {
int64_t id;
int64_t idx; /* element index in the group */
void *element;
enum w_type type;
enum g_type g_type;
bool is_default;
struct val_t val;
} group_el_t;
enum cbrp_code {
cbrc_none, /* default */
cbrp_val,
cbrp_g_el, /* element of type group_el_t */
cbrp_err
};
typedef struct {
void *app;
void *element;
void *data;
void *resp_data;
uint32_t active_id;
struct {
enum cbrp_code code;
struct val_t val;
} resp_data;
void *active_el;
} callback_args_t;
enum rsize {
@@ -34,19 +75,18 @@ enum rsize {
};
typedef struct widget_t {
uint32_t id;
int64_t id;
char title[DIALOGUE_TITLE];
uint32_t x;
uint32_t y;
uint32_t m_x;
uint32_t m_y;
int64_t x;
int64_t y;
int64_t m_x;
int64_t m_y;
struct {
uint32_t y;
uint32_t x;
int64_t y;
int64_t x;
} cur;
WINDOW *const *parent_win;
struct widget_t *w_parent;
// enum rsize rsize;
void (*callback)(callback_args_t *args);
} widget_t;
@@ -59,7 +99,8 @@ enum pmt_attrs {
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,
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);
#endif