summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2024-12-21 14:09:30 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2024-12-21 14:09:30 +0330
commitc59709cb7de9c8951362007313f0b45fe4e7fd79 (patch)
tree0243ba3df52a8007d2fffc4945f6536102203a55 /src/ui
parentbcde4724cdaa8becd27160d8e8733919ed726366 (diff)
Added Center widget
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/tui.c166
-rw-r--r--src/ui/tui.h18
2 files changed, 175 insertions, 9 deletions
diff --git a/src/ui/tui.c b/src/ui/tui.c
index ca87655..12d61d5 100644
--- a/src/ui/tui.c
+++ b/src/ui/tui.c
@@ -282,7 +282,7 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,
const int y = height;
const char c = metadata->text[inserted_index];
inserted_index += 1;
- if (c == '\n') {// do for other spaces
+ if (c == '\n') { // do for other spaces
height += 1;
j = 0;
goto START_OF_HORIZONTAL_LOOP;
@@ -381,6 +381,25 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,
*child_width = width_end;
*child_height = height_end;
} break;
+ 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, child_width, child_height);
+ const int horizontalPadding = width_end - *child_width;
+ 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;
+
+ _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);
@@ -388,6 +407,123 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,
}
}
+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) {
+ switch (widget->type) {
+ case WIDGET_TYPE_TEXT: {
+ const TEXT_METADATA *metadata = widget->metadata;
+ const int width_diff = width_end - width_begin;
+ const size_t text_len = strlen(metadata->text);
+ size_t inserted_index = 0;
+ int height = height_begin;
+ int max_width = width_begin;
+ for (; height < height_end; ++height) {
+ for (int j = 0; j < width_diff; ++j) {
+ START_OF_HORIZONTAL_LOOP:
+ if (inserted_index < text_len) {
+ const int x = width_begin + j;
+ const char c = metadata->text[inserted_index];
+ inserted_index += 1;
+ if (c == '\n') { // do for other spaces
+ height += 1;
+ j = 0;
+ goto START_OF_HORIZONTAL_LOOP;
+ } else {
+ if (max_width < x) {
+ max_width = x;
+ }
+ }
+ } else {
+ goto END_OF_TEXT;
+ }
+ }
+ }
+ END_OF_TEXT:
+ *width_height = height + 1;
+ *widget_width = max_width + 1;
+ } break;
+ 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);
+ }
+ } break;
+ case WIDGET_TYPE_COLUMN: {
+ const COLUMN_METADATA *metadata = widget->metadata;
+ *widget_width = width_begin;
+ *width_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);
+ if (width_temp > *widget_width) {
+ *widget_width = width_temp;
+ }
+ }
+ } break;
+ case WIDGET_TYPE_ROW: {
+ const ROW_METADATA *metadata = widget->metadata;
+ *widget_width = width_begin;
+ *width_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;
+ }
+ }
+ } break;
+ case WIDGET_TYPE_BOX: {
+ const BOX_METADATA *metadata = widget->metadata;
+
+ if (metadata->width != MIN_WIDTH && metadata->width != MAX_WIDTH) {
+ width_end = metadata->width + width_begin >= width_end
+ ? width_end
+ : metadata->width + width_begin;
+ }
+ if (metadata->height != MIN_HEIGHT && metadata->height != MAX_HEIGHT) {
+ height_end = metadata->height + height_begin >= height_end
+ ? height_end
+ : metadata->height + height_begin;
+ }
+
+ if (metadata->child != NULL) {
+ int temp_width, temp_height;
+ _tui_get_widget_size(metadata->child, width_begin, width_end,
+ height_begin, height_end, &temp_width,
+ &temp_height);
+ if (metadata->width == MIN_WIDTH) {
+ width_end = temp_width;
+ }
+ if (metadata->height == MIN_HEIGHT) {
+ height_end = temp_height;
+ }
+ }
+
+ *widget_width = width_end;
+ *width_height = height_end;
+ } break;
+ 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);
+ }
+ } break;
+
+ default:
+ fprintf(stderr, "widget type '%d' went wrong in %s %d", widget->type,
+ __FILE__, __LINE__);
+ exit(1);
+ }
+}
+
void _tui_move_to_start_in_str(char *str) { strcpy(str, "\033[;H"); }
int _tui_get_background_color_ascii(COLOR color) {
@@ -503,8 +639,14 @@ bool tui_widget_eqauls(const WIDGET *restrict left,
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 tui_delete_widget\n", left->type);
+ fprintf(stderr, "Type error '%d' in %s %d\n", left->type, __FILE__,
+ __LINE__);
exit(1);
}
@@ -521,7 +663,7 @@ int64_t nano_sleep(long int nano_seconds) {
}
long int nano_time() {
- struct timespec t = {0, 0}, tend = {0, 0};
+ struct timespec t = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &t);
return t.tv_sec * NANO_TO_SECOND + t.tv_nsec;
}
@@ -586,8 +728,12 @@ void tui_delete_widget(WIDGET *restrict widget) {
case WIDGET_TYPE_BOX:
_tui_delete_box(widget);
break;
+ case WIDGET_TYPE_CENTER:
+ _tui_delete_center(widget);
+ break;
default:
- fprintf(stderr, "Type error '%d' in tui_delete_widget\n", widget->type);
+ fprintf(stderr, "Type error '%d' in %s %d\n", widget->type, __FILE__,
+ __LINE__);
exit(1);
}
free(widget);
@@ -682,6 +828,18 @@ void _tui_delete_box(WIDGET *box) {
free(box->metadata);
}
+WIDGET *tui_make_center(WIDGET *restrict child) {
+ return tui_new_widget(WIDGET_TYPE_CENTER, _tui_make_center_metadata(child));
+}
+
+CENTER_METADATA *_tui_make_center_metadata(WIDGET *restrict child) {
+ return child;
+}
+
+void _tui_delete_center(WIDGET *restrict center) {
+ tui_delete_widget(center->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 86efa1d..09c7b8e 100644
--- a/src/ui/tui.h
+++ b/src/ui/tui.h
@@ -1,5 +1,4 @@
-#ifndef A404M_UI_TUI
-#define A404M_UI_TUI 1
+#pragma once
#include <stdint.h>
#include <stdlib.h>
@@ -70,6 +69,7 @@ typedef enum WIDGET_TYPE {
WIDGET_TYPE_COLUMN,
WIDGET_TYPE_ROW,
WIDGET_TYPE_BOX,
+ WIDGET_TYPE_CENTER,
} WIDGET_TYPE;
typedef struct WIDGET {
@@ -107,6 +107,8 @@ typedef struct BOX_METADATA {
COLOR color;
} BOX_METADATA;
+typedef WIDGET CENTER_METADATA;
+
typedef WIDGET *(*WIDGET_BUILDER)(TUI *tui);
extern TUI *tui_init();
@@ -125,7 +127,11 @@ extern void tui_start_app(TUI *tui, WIDGET_BUILDER widget_builder, int fps);
extern void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget,
int width_begin, int width_end,
int height_begin, int height_end,
- int *child_width, int *childHeight);
+ int *child_width, int *child_height);
+
+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);
extern bool tui_widget_eqauls(const WIDGET *restrict left,
const WIDGET *restrict right);
@@ -162,11 +168,13 @@ extern BOX_METADATA *_tui_make_box_metadata(WIDGET *restrict child, int width,
int height, COLOR color);
extern void _tui_delete_box(WIDGET *restrict box);
+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_ARRAY *tui_make_widget_array_raw(size_t size, ...);
extern void _tui_delete_widget_array(WIDGET_ARRAY *restrict widget_array);
#define tui_make_widget_array(...) \
tui_make_widget_array_raw( \
sizeof((WIDGET *[]){__VA_ARGS__}) / sizeof(WIDGET *), __VA_ARGS__)
-
-#endif