diff options
| author | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2024-12-21 15:58:24 +0330 | 
|---|---|---|
| committer | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2024-12-21 15:58:24 +0330 | 
| commit | dd493a56e5c014f7c71d79c14215b514c5aca06e (patch) | |
| tree | ea68888cde0540063fa2f2fc518a8767b3b54822 | |
| parent | c59709cb7de9c8951362007313f0b45fe4e7fd79 (diff) | |
Added Padding and expandable rows
| -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);  |