summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2024-12-21 15:58:24 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2024-12-21 15:58:24 +0330
commitdd493a56e5c014f7c71d79c14215b514c5aca06e (patch)
treeea68888cde0540063fa2f2fc518a8767b3b54822 /src
parentc59709cb7de9c8951362007313f0b45fe4e7fd79 (diff)
Added Padding and expandable rows
Diffstat (limited to 'src')
-rw-r--r--src/main.c35
-rw-r--r--src/ui/tui.c254
-rw-r--r--src/ui/tui.h24
3 files changed, 238 insertions, 75 deletions
diff --git a/src/main.c b/src/main.c
index 11884db..188330c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);