diff options
-rw-r--r-- | src/main.c | 35 | ||||
-rw-r--r-- | src/ui/tui.c | 254 | ||||
-rw-r--r-- | src/ui/tui.h | 24 |
3 files changed, 238 insertions, 75 deletions
@@ -46,29 +46,30 @@ WIDGET *ui_build0(TUI *tui) { } WIDGET *search_box() { - return tui_make_box( - MAX_WIDTH, 1, - tui_make_center(tui_make_row(tui_make_widget_array( - tui_make_box(100, 1, NULL, COLOR_BLUE), - tui_make_box(10, 1, - tui_make_center(tui_make_text("Search", COLOR_BLUE)), - COLOR_GREEN)))), - COLOR_NO_COLOR); + return tui_make_padding( + tui_make_box( + MAX_WIDTH, 1, + tui_make_center(tui_make_row(tui_make_widget_array( + tui_make_box(MAX_WIDTH, 1, NULL, COLOR_BLUE), + tui_make_box(10, 1, + tui_make_center(tui_make_text("Search", COLOR_BLUE)), + COLOR_GREEN) + ))), + COLOR_NO_COLOR), + 1, 1, 10, 10); } WIDGET *ui_build(TUI *tui) { return tui_make_box( MAX_WIDTH, MAX_HEIGHT, tui_make_column(tui_make_widget_array( - tui_make_box(0, 2, NULL, COLOR_NO_COLOR), search_box(), - tui_make_box(0, 2, NULL, COLOR_NO_COLOR), - tui_make_row(tui_make_widget_array( - tui_make_box(50, 0, NULL, COLOR_NO_COLOR), - tui_make_button( - tui_make_box(MIN_WIDTH, MIN_HEIGHT, - tui_make_text("\nClick here\n", COLOR_BLUE), - COLOR_WHITE), - on_button_click))))), + search_box(), + tui_make_row(tui_make_widget_array(tui_make_center(tui_make_button( + tui_make_box( + MIN_WIDTH, 3, + tui_make_center(tui_make_text("Click here", COLOR_BLUE)), + COLOR_WHITE), + on_button_click)))))), COLOR_MAGENTA); } diff --git a/src/ui/tui.c b/src/ui/tui.c index 12d61d5..02e3079 100644 --- a/src/ui/tui.c +++ b/src/ui/tui.c @@ -301,7 +301,8 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin, END_OF_TEXT: *child_height = height + 1; *child_width = max_width + 1; - } break; + } + return; case WIDGET_TYPE_BUTTON: { const BUTTON_METADATA *metadata = widget->metadata; if (metadata->child != NULL) { @@ -314,7 +315,8 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin, } } } - } break; + } + return; case WIDGET_TYPE_COLUMN: { const COLUMN_METADATA *metadata = widget->metadata; *child_width = width_begin; @@ -329,22 +331,47 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin, *child_width = width_temp; } } - } break; + } + return; case WIDGET_TYPE_ROW: { const ROW_METADATA *metadata = widget->metadata; + + int remaining_width = width_end - width_begin; + int inf_num = 0; + + for (size_t i = 0; i < metadata->children->size; ++i) { + const WIDGET *child = metadata->children->widgets[i]; + if (_tui_is_max_width(child)) { + inf_num += 1; + } else { + int temp_width, temp_height; + _tui_get_widget_size(child, width_begin, width_end, height_begin, + height_end, &temp_width, &temp_height); + + remaining_width -= temp_width - width_begin; + } + } + *child_width = width_begin; *child_height = height_begin; for (size_t i = 0; i < metadata->children->size; ++i) { const WIDGET *child = metadata->children->widgets[i]; + int current_width_end; + if (_tui_is_max_width(child)) { + current_width_end = *child_width + remaining_width / inf_num; + } else { + current_width_end = width_end; + } int height_temp; - _tui_draw_widget_to_cells(tui, child, *child_width, width_end, + _tui_draw_widget_to_cells(tui, child, *child_width, current_width_end, height_begin, height_end, child_width, &height_temp); if (height_temp > *child_height) { *child_height = height_temp; } } - } break; + } + return; case WIDGET_TYPE_BOX: { const BOX_METADATA *metadata = widget->metadata; @@ -380,7 +407,8 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin, *child_width = width_end; *child_height = height_end; - } break; + } + return; case WIDGET_TYPE_CENTER: { const CENTER_METADATA *metadata = widget->metadata; if (metadata != NULL) { @@ -390,26 +418,36 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin, const int verticalPadding = height_end - *child_height; const int leftPadding = horizontalPadding / 2; const int rightPadding = horizontalPadding - leftPadding; - const int topPadding = verticalPadding / 2; - const int bottomPadding = verticalPadding - topPadding; + const int bottomPadding = verticalPadding / 2; + const int topPadding = verticalPadding - bottomPadding; _tui_draw_widget_to_cells( tui, metadata, width_begin + leftPadding, width_end - rightPadding, height_begin + topPadding, height_end - bottomPadding, child_width, child_height); } - } break; - - default: - fprintf(stderr, "widget type '%d' went wrong in _tui_draw_widget", - widget->type); - exit(1); + } + return; + case WIDGET_TYPE_PADDING: { + const PADDING_METADATA *metadata = widget->metadata; + if (metadata != NULL) { + _tui_draw_widget_to_cells( + tui, metadata->child, width_begin + metadata->padding_left, + width_end - metadata->padding_right, + height_begin + metadata->padding_top, + height_end - metadata->padding_bottom, child_width, child_height); + } + } + return; } + fprintf(stderr, "widget type '%d' went wrong in %s %d\n", widget->type, + __FILE_NAME__, __LINE__); + exit(1); } void _tui_get_widget_size(const WIDGET *widget, int width_begin, int width_end, int height_begin, int height_end, int *widget_width, - int *width_height) { + int *widget_height) { switch (widget->type) { case WIDGET_TYPE_TEXT: { const TEXT_METADATA *metadata = widget->metadata; @@ -440,45 +478,49 @@ void _tui_get_widget_size(const WIDGET *widget, int width_begin, int width_end, } } END_OF_TEXT: - *width_height = height + 1; + *widget_height = height + 1; *widget_width = max_width + 1; - } break; + } + return; case WIDGET_TYPE_BUTTON: { const BUTTON_METADATA *metadata = widget->metadata; if (metadata->child != NULL) { _tui_get_widget_size(metadata->child, width_begin, width_end, height_begin, height_end, widget_width, - width_height); + widget_height); } - } break; + } + return; case WIDGET_TYPE_COLUMN: { const COLUMN_METADATA *metadata = widget->metadata; *widget_width = width_begin; - *width_height = height_begin; + *widget_height = height_begin; for (size_t i = 0; i < metadata->children->size; ++i) { const WIDGET *child = metadata->children->widgets[i]; int width_temp; - _tui_get_widget_size(child, width_begin, width_end, *width_height, - height_end, &width_temp, width_height); + _tui_get_widget_size(child, width_begin, width_end, *widget_height, + height_end, &width_temp, widget_height); if (width_temp > *widget_width) { *widget_width = width_temp; } } - } break; + } + return; case WIDGET_TYPE_ROW: { const ROW_METADATA *metadata = widget->metadata; *widget_width = width_begin; - *width_height = height_begin; + *widget_height = height_begin; for (size_t i = 0; i < metadata->children->size; ++i) { const WIDGET *child = metadata->children->widgets[i]; int height_temp; _tui_get_widget_size(child, *widget_width, width_end, height_begin, height_end, widget_width, &height_temp); - if (height_temp > *width_height) { - *width_height = height_temp; + if (height_temp > *widget_height) { + *widget_height = height_temp; } } - } break; + } + return; case WIDGET_TYPE_BOX: { const BOX_METADATA *metadata = widget->metadata; @@ -507,21 +549,85 @@ void _tui_get_widget_size(const WIDGET *widget, int width_begin, int width_end, } *widget_width = width_end; - *width_height = height_end; - } break; + *widget_height = height_end; + } + return; case WIDGET_TYPE_CENTER: { const CENTER_METADATA *metadata = widget->metadata; if (metadata != NULL) { _tui_get_widget_size(metadata, width_begin, width_end, height_begin, - height_end, widget_width, width_height); + height_end, widget_width, widget_height); } - } break; + } + return; + case WIDGET_TYPE_PADDING: + const PADDING_METADATA *metadata = widget->metadata; + if (metadata != NULL) { + _tui_get_widget_size(metadata->child, width_begin, width_end, + height_begin, height_end, widget_width, + widget_height); + *widget_width += metadata->padding_left + metadata->padding_right; + *widget_height += metadata->padding_top + metadata->padding_bottom; + if (*widget_width > width_end) { + *widget_width = width_end; + } + if (*widget_height > height_end) { + *widget_height = height_end; + } + } + } + fprintf(stderr, "widget type '%d' went wrong in %s %d", widget->type, + __FILE_NAME__, __LINE__); + exit(1); +} - default: - fprintf(stderr, "widget type '%d' went wrong in %s %d", widget->type, - __FILE__, __LINE__); - exit(1); +bool _tui_is_max_width(const WIDGET *widget) { + if (widget == NULL) { + return false; } + switch (widget->type) { + case WIDGET_TYPE_TEXT: + return false; + case WIDGET_TYPE_BUTTON: + return _tui_is_max_width(((BUTTON_METADATA *)widget->metadata)->child); + case WIDGET_TYPE_COLUMN: { + const WIDGET_ARRAY *children = + ((COLUMN_METADATA *)widget->metadata)->children; + for (size_t i = 0; i < children->size; ++i) { + if (!_tui_is_max_width(children->widgets[i])) { + return true; + } + } + return false; + } + case WIDGET_TYPE_ROW: { + const WIDGET_ARRAY *children = + ((ROW_METADATA *)widget->metadata)->children; + for (size_t i = 0; i < children->size; ++i) { + if (_tui_is_max_width(children->widgets[i])) { + return true; + } + } + return false; + } + case WIDGET_TYPE_BOX: { + const BOX_METADATA *metadata = widget->metadata; + if (metadata->width == MAX_WIDTH) { + return true; + } else if (metadata->width == MIN_WIDTH) { + return _tui_is_max_width(metadata->child); + }else{ + return false; + } + } + case WIDGET_TYPE_CENTER: + return _tui_is_max_width((CENTER_METADATA *)widget->metadata); + case WIDGET_TYPE_PADDING: + return _tui_is_max_width(((PADDING_METADATA *)widget->metadata)->child); + } + fprintf(stderr, "widget type '%d' went wrong in %s %d\n", widget->type, + __FILE_NAME__, __LINE__); + exit(1); } void _tui_move_to_start_in_str(char *str) { strcpy(str, "\033[;H"); } @@ -614,23 +720,23 @@ bool tui_widget_eqauls(const WIDGET *restrict left, const TEXT_METADATA *right_data = right->metadata; return left_data->color == right_data->color && strcmp(left_data->text, right_data->text) == 0; - } break; + } case WIDGET_TYPE_BUTTON: { const BUTTON_METADATA *left_data = left->metadata; const BUTTON_METADATA *right_data = right->metadata; return left_data->callback == right_data->callback && tui_widget_eqauls(left_data->child, right_data->child); - } break; + } case WIDGET_TYPE_COLUMN: { const COLUMN_METADATA *left_data = left->metadata; const COLUMN_METADATA *right_data = right->metadata; return tui_widget_array_eqauls(left_data->children, right_data->children); - } break; + } case WIDGET_TYPE_ROW: { const ROW_METADATA *left_data = left->metadata; const ROW_METADATA *right_data = right->metadata; return tui_widget_array_eqauls(left_data->children, right_data->children); - } break; + } case WIDGET_TYPE_BOX: { const BOX_METADATA *left_data = left->metadata; const BOX_METADATA *right_data = right->metadata; @@ -638,19 +744,24 @@ bool tui_widget_eqauls(const WIDGET *restrict left, left_data->height == right_data->height && left_data->color == right_data->color && tui_widget_eqauls(left_data->child, right_data->child); - } break; + } case WIDGET_TYPE_CENTER: { const CENTER_METADATA *left_data = left->metadata; const CENTER_METADATA *right_data = right->metadata; return tui_widget_eqauls(left_data, right_data); - } break; - default: - fprintf(stderr, "Type error '%d' in %s %d\n", left->type, __FILE__, - __LINE__); - exit(1); + } + case WIDGET_TYPE_PADDING: { + const PADDING_METADATA *left_data = left->metadata; + const PADDING_METADATA *right_data = right->metadata; + return tui_widget_eqauls(left_data->child, right_data->child) && + left_data->padding_top == right_data->padding_top && + left_data->padding_bottom == right_data->padding_bottom && + left_data->padding_left == right_data->padding_left && + left_data->padding_right == right_data->padding_right; + } } - - return true; + fprintf(stderr, "Type error '%d' in %s %d\n", left->type, __FILE__, __LINE__); + exit(1); } const int NANO_TO_SECOND = 1000000000; @@ -715,27 +826,30 @@ void tui_delete_widget(WIDGET *restrict widget) { switch (widget->type) { case WIDGET_TYPE_TEXT: _tui_delete_text(widget); - break; + goto RETURN_SUCCESS; case WIDGET_TYPE_BUTTON: _tui_delete_button(widget); - break; + goto RETURN_SUCCESS; case WIDGET_TYPE_COLUMN: _tui_delete_column(widget); - break; + goto RETURN_SUCCESS; case WIDGET_TYPE_ROW: _tui_delete_row(widget); - break; + goto RETURN_SUCCESS; case WIDGET_TYPE_BOX: _tui_delete_box(widget); - break; + goto RETURN_SUCCESS; case WIDGET_TYPE_CENTER: _tui_delete_center(widget); - break; - default: - fprintf(stderr, "Type error '%d' in %s %d\n", widget->type, __FILE__, - __LINE__); - exit(1); + goto RETURN_SUCCESS; + case WIDGET_TYPE_PADDING: + _tui_delete_padding(widget); + goto RETURN_SUCCESS; } + fprintf(stderr, "Type error '%d' in %s %d\n", widget->type, __FILE__, + __LINE__); + exit(1); +RETURN_SUCCESS: free(widget); } @@ -840,6 +954,32 @@ void _tui_delete_center(WIDGET *restrict center) { tui_delete_widget(center->metadata); } +WIDGET *tui_make_padding(WIDGET *restrict child, int padding_top, + int padding_bottom, int padding_left, + int padding_right) { + return tui_new_widget( + WIDGET_TYPE_PADDING, + _tui_make_padding_metadata(child, padding_top, padding_bottom, + padding_left, padding_right)); +} +PADDING_METADATA *_tui_make_padding_metadata(WIDGET *restrict child, + int padding_top, + int padding_bottom, + int padding_left, + int padding_right) { + PADDING_METADATA *metadata = malloc(sizeof(*metadata)); + metadata->child = child; + metadata->padding_top = padding_top; + metadata->padding_bottom = padding_bottom; + metadata->padding_left = padding_left; + metadata->padding_right = padding_right; + return metadata; +} +void _tui_delete_padding(WIDGET *restrict padding) { + tui_delete_widget(((PADDING_METADATA *)padding->metadata)->child); + free(padding->metadata); +} + WIDGET_ARRAY *tui_make_widget_array_raw(size_t size, ...) { va_list arg_pointer; va_start(arg_pointer, size); diff --git a/src/ui/tui.h b/src/ui/tui.h index 09c7b8e..eda55ac 100644 --- a/src/ui/tui.h +++ b/src/ui/tui.h @@ -70,6 +70,7 @@ typedef enum WIDGET_TYPE { WIDGET_TYPE_ROW, WIDGET_TYPE_BOX, WIDGET_TYPE_CENTER, + WIDGET_TYPE_PADDING, } WIDGET_TYPE; typedef struct WIDGET { @@ -109,6 +110,14 @@ typedef struct BOX_METADATA { typedef WIDGET CENTER_METADATA; +typedef struct PADDING_METADATA { + WIDGET *child; + int padding_top; + int padding_bottom; + int padding_left; + int padding_right; +} PADDING_METADATA; + typedef WIDGET *(*WIDGET_BUILDER)(TUI *tui); extern TUI *tui_init(); @@ -131,7 +140,10 @@ extern void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, extern void _tui_get_widget_size(const WIDGET *widget, int width_begin, int width_end, int height_begin, - int height_end, int *widget_width, int *widget_height); + int height_end, int *widget_width, + int *widget_height); + +extern bool _tui_is_max_width(const WIDGET *widget); extern bool tui_widget_eqauls(const WIDGET *restrict left, const WIDGET *restrict right); @@ -172,6 +184,16 @@ extern WIDGET *tui_make_center(WIDGET *restrict child); extern CENTER_METADATA *_tui_make_center_metadata(WIDGET *restrict child); extern void _tui_delete_center(WIDGET *restrict center); +extern WIDGET *tui_make_padding(WIDGET *restrict child, int padding_top, + int padding_bottom, int padding_left, + int padding_right); +extern PADDING_METADATA *_tui_make_padding_metadata(WIDGET *restrict child, + int padding_top, + int padding_bottom, + int padding_left, + int padding_right); +extern void _tui_delete_padding(WIDGET *restrict padding); + extern WIDGET_ARRAY *tui_make_widget_array_raw(size_t size, ...); extern void _tui_delete_widget_array(WIDGET_ARRAY *restrict widget_array); |