diff options
| author | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2024-12-21 14:09:30 +0330 | 
|---|---|---|
| committer | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2024-12-21 14:09:30 +0330 | 
| commit | c59709cb7de9c8951362007313f0b45fe4e7fd79 (patch) | |
| tree | 0243ba3df52a8007d2fffc4945f6536102203a55 | |
| parent | bcde4724cdaa8becd27160d8e8733919ed726366 (diff) | |
Added Center widget
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | Makefile | 45 | ||||
| -rwxr-xr-x | project | 29 | ||||
| -rw-r--r-- | src/main.c | 37 | ||||
| -rw-r--r-- | src/ui/tui.c | 166 | ||||
| -rw-r--r-- | src/ui/tui.h | 18 | 
6 files changed, 254 insertions, 43 deletions
@@ -1 +1,3 @@  build/ +.cache/ +compile_commands.json diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..772c3b8 --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +CC := gcc + +BUILD_DIR := ./build +SRC_DIR := ./src + +SRCS := $(shell find $(SRC_DIR) -name "*.c") +OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) + +RED := \033[0;31m +GREEN := \033[0;32m +NC := \033[0m + +# INC_DIRS := $(shell find $(SRC_DIRS) -type d) +INC_DIRS := $(SRC_DIR) +INC_FLAGS := $(addprefix -I,$(INC_DIRS)) + +CFLAGS := $(INC_FLAGS) -Wall -Wextra -std=gnu23 -Ofast -lcurl + +EXEC_FILE := $(BUILD_DIR)/atui + +all: $(EXEC_FILE) + +$(EXEC_FILE): $(OBJS) +	$(CC) $(CFLAGS) $(OBJS) -o $@ $(LDFLAGS) + +$(BUILD_DIR)/%.c.o: %.c +	mkdir -p $(dir $@) +	$(CC) $(CFLAGS) -c $< -o $@ + +lsp-files: clean +	bear -- make all + +.PHONY: clean +clean: +	rm -rf $(BUILD_DIR) + +run: $(EXEC_FILE) +	$(EXEC_FILE) $(args) + +val-run: $(EXEC_FILE) +	valgrind --leak-check=full --track-origins=yes --show-leak-kinds=all -s $(EXEC_FILE) $(args) + +# $@ = left hand of : +# $< = right hand of : first one of them +# $^ = right hand of : all diff --git a/project b/project deleted file mode 100755 index c1daf50..0000000 --- a/project +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -project_name="atui" - -function compile(){ -  if [ ! -d build ]; then -    if [ $(mkdir build) ]; then # if error -      echo "cannot make 'build' dir" -      exit -    fi -  fi - -  gcc -Wall -Wextra -O3 src/main.c src/ui/tui.c -o "build/$project_name" -} - -function run(){ -  compile && "./build/$project_name" "$@" -  echo -  echo "$?" -} - -function clear(){ -  rm -r ./build/ -} - -function_name="$1" -shift - -$function_name "$@" @@ -10,13 +10,13 @@ void on_button_click(const MOUSE_ACTION *mouse_action) {    is_clicked = !is_clicked;  } -WIDGET *ui_build(TUI *tui) { +WIDGET *ui_build0(TUI *tui) {    if (is_clicked) { -    char frame[20+4+1]; -    const uint64_t fps = 1000000000/tui->last_frame; +    char frame[20 + 4 + 1]; +    const uint64_t fps = 1000000000 / tui->last_frame;      sprintf(frame, "%ldfps\n", fps);      return tui_make_box( -        -1, -1, +        MAX_WIDTH, MAX_HEIGHT,          tui_make_column(tui_make_widget_array(              tui_make_box(0, 12, NULL, COLOR_NO_COLOR),              tui_make_row(tui_make_widget_array( @@ -31,7 +31,7 @@ WIDGET *ui_build(TUI *tui) {          COLOR_MAGENTA);    } else {      return tui_make_box( -        -1, -1, +        MAX_WIDTH, MAX_HEIGHT,          tui_make_column(tui_make_widget_array(              tui_make_box(0, 12, NULL, COLOR_NO_COLOR),              tui_make_row(tui_make_widget_array( @@ -45,6 +45,33 @@ WIDGET *ui_build(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); +} + +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))))), +      COLOR_MAGENTA); +} +  int main() {    TUI *tui = tui_init(); 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  |