diff options
| author | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2024-12-24 01:23:24 +0330 | 
|---|---|---|
| committer | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2024-12-24 01:23:24 +0330 | 
| commit | 55d29d0df8681efe01e88e0475c8512c44ec4bc4 (patch) | |
| tree | 2b07ab80b17c8bb6b20837e104aa863854f7ccff | |
| parent | 217e7d18dbaa260a15f5612d9670105b04cd455f (diff) | |
fixed some bugs
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | src/main.c | 30 | ||||
| -rw-r--r-- | src/ui/color.h | 11 | ||||
| -rw-r--r-- | src/ui/tui.c | 105 | ||||
| -rw-r--r-- | src/ui/tui.h | 17 | 
5 files changed, 112 insertions, 53 deletions
@@ -14,7 +14,7 @@ NC := \033[0m  INC_DIRS := $(SRC_DIR)  INC_FLAGS := $(addprefix -I,$(INC_DIRS)) -CFLAGS := $(INC_FLAGS) -Wall -Wextra -std=gnu23 -Ofast +CFLAGS := $(INC_FLAGS) -Wall -Wextra -std=gnu23 -Ofast -march=native  EXEC_FILE := $(BUILD_DIR)/atui @@ -5,6 +5,10 @@  #include "ui/color.h"  #include "ui/tui.h" +constexpr COLOR BACKGROUND_COLOR = color_hex(0xFF2B2A33); +constexpr COLOR COLOR_FPS_BACK = color_hex(0xFFCCCCCC); +constexpr COLOR COLOR_FPS_TEXT = color_hex(0xFF000000); +  WIDGET *search_box() {    return tui_make_padding(        tui_make_box(MAX_WIDTH, 1, @@ -18,19 +22,29 @@ WIDGET *search_box() {        1, 1, 10, 10);  } -WIDGET *search_header() {} +// WIDGET *search_header() {} + +WIDGET *fps_counter(uint64_t last_frame) { +  char fps_text[3 + 1 + 20 + 1]; +  sprintf(fps_text, "fps %ld", +          (last_frame == 0) ? 0 : (NANO_TO_SECOND / last_frame)); +  return tui_make_padding( +      tui_make_box(MIN_WIDTH, 1, tui_make_text(fps_text, COLOR_FPS_TEXT), +                   COLOR_FPS_BACK), +      0, 0, 2, 2); +}  WIDGET *ui_build(TUI *tui) {    return tui_make_box(        MAX_WIDTH, MAX_HEIGHT,        tui_make_column(tui_make_widget_array( -          search_box(), -          tui_make_row(tui_make_widget_array(tui_make_center( -              tui_make_box(MIN_WIDTH, 3, -                           tui_make_center(tui_make_text( -                               "Hi here", color_init(0xFF0000FF))), -                           color_init(0xFFFFFFFF))))))), -      color_init(0xFF2B2A33)); +          fps_counter(tui->last_frame), search_box(), +          tui_make_row(tui_make_widget_array(tui_make_center(tui_make_box( +              MIN_WIDTH, MIN_HEIGHT, +              tui_make_padding(tui_make_text("Hi here", color_init(0xFF0000FF)), +                               2, 2, 2, 2), +              color_init(0xFFFFFFFF))))))), +      BACKGROUND_COLOR);  }  int main() { diff --git a/src/ui/color.h b/src/ui/color.h index 43005a6..75df571 100644 --- a/src/ui/color.h +++ b/src/ui/color.h @@ -6,11 +6,12 @@ typedef struct COLOR {    uint8_t b, g, r, a;  } COLOR; -#define color_hex(value) \ -  (uint8_t)((uint32_t)value >> 3), \ -  (uint8_t)((uint32_t)value >> 2), \ -  (uint8_t)((uint32_t)value >> 1), \ -  (uint8_t)((uint32_t)value >> 0) \ +#define color_hex(value) { \ +  (uint8_t)(((uint32_t)value >> 8*0)&0xFF), \ +  (uint8_t)(((uint32_t)value >> 8*1)&0xFF), \ +  (uint8_t)(((uint32_t)value >> 8*2)&0xFF), \ +  (uint8_t)(((uint32_t)value >> 8*3)&0xFF), \ +}  constexpr COLOR COLOR_NO_COLOR = {      .a = 0, diff --git a/src/ui/tui.c b/src/ui/tui.c index 62eb585..901cbc1 100644 --- a/src/ui/tui.c +++ b/src/ui/tui.c @@ -20,12 +20,14 @@ const int MIN_HEIGHT = -2;  const int FRAME_UNLIMITED = 0;  void _tui_clear_cells(TUI *tui) { -  const TERMINAL_CELL empty = {.c = ' ', -                               .color = COLOR_NO_COLOR, -                               .background_color = COLOR_NO_COLOR, -                               .on_click_callback = NULL}; +  constexpr TERMINAL_CELL EMPTY_CELL = { +      .c = ' ', +      .color = COLOR_NO_COLOR, +      .background_color = COLOR_NO_COLOR, +      .on_click_callback = NULL, +  };    for (size_t i = 0; i < tui->cells_length; ++i) { -    tui->cells[i] = empty; +    tui->cells[i] = EMPTY_CELL;    }  } @@ -184,26 +186,6 @@ void tui_handle_mouse_action(TUI *tui, const MOUSE_ACTION *mouse_action) {    }  } -/* -int tui_change_terminal_text_color(COLOR color) { -  if (color_equals(color, COLOR_NO_COLOR)) { -    return 0; -  } else if (color == COLOR_RESET) { -    return printf("\033[%dm", COLOR_RESET); -  } -  return printf("\033[%dm", color + 30); -} - -int tui_change_terminal_background_color(COLOR color) { -  if (color == COLOR_NO_COLOR) { -    return 0; -  } else if (color == COLOR_RESET) { -    return printf("\033[%dm", COLOR_RESET); -  } -  return printf("\033[%dm", color + 40); -} -*/ -  bool handle_input(TUI *tui) {    unsigned char buff[6];    read(STDIN_FILENO, &buff, 1); @@ -418,12 +400,12 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,        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 bottomPadding = verticalPadding / 2; -        const int topPadding = verticalPadding - bottomPadding; +        const uint horizontalPadding = width_end - *child_width; +        const uint verticalPadding = height_end - *child_height; +        const uint leftPadding = horizontalPadding / 2; +        const uint rightPadding = horizontalPadding - leftPadding; +        const uint bottomPadding = verticalPadding / 2; +        const uint topPadding = verticalPadding - bottomPadding;          _tui_draw_widget_to_cells(              tui, metadata, width_begin + leftPadding, width_end - rightPadding, @@ -440,6 +422,14 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,              width_end - metadata->padding_right,              height_begin + metadata->padding_top,              height_end - metadata->padding_bottom, child_width, child_height); +        *child_width += metadata->padding_left + metadata->padding_right; +        *child_height += metadata->padding_top + metadata->padding_bottom; +        if (*child_width > width_end) { +          *child_width = width_end; +        } +        if (*child_height > height_end) { +          *child_height = height_end; +        }        }      }        return; @@ -579,6 +569,7 @@ void _tui_get_widget_size(const WIDGET *widget, int width_begin, int width_end,            *widget_height = height_end;          }        } +      return;    }    fprintf(stderr, "widget type '%d' went wrong in %s %d", widget->type,            __FILE_NAME__, __LINE__); @@ -591,6 +582,7 @@ bool _tui_is_max_width(const WIDGET *widget) {    }    switch (widget->type) {      case WIDGET_TYPE_TEXT: +    case WIDGET_TYPE_TEXT_INPUT:        return false;      case WIDGET_TYPE_BUTTON:        return _tui_is_max_width(((BUTTON_METADATA *)widget->metadata)->child); @@ -762,32 +754,43 @@ bool tui_widget_eqauls(const WIDGET *restrict left,               left_data->padding_left == right_data->padding_left &&               left_data->padding_right == right_data->padding_right;      } +    case WIDGET_TYPE_TEXT_INPUT: { +      const TEXT_INPUT_METADATA *left_data = left->metadata; +      const TEXT_INPUT_METADATA *right_data = right->metadata; +      return color_equals(left_data->color, right_data->color) && +             strcmp(left_data->text, right_data->text) == 0 && +             left_data->on_text_input == right_data->on_text_input; +    }    }    fprintf(stderr, "Type error '%d' in %s %d\n", left->type, __FILE__, __LINE__);    exit(1);  } -const int NANO_TO_SECOND = 1000000000; - -int64_t nano_sleep(long int nano_seconds) { +int64_t nano_sleep(uint64_t nano_seconds) {    struct timespec remaining,        request = {nano_seconds / NANO_TO_SECOND, nano_seconds % NANO_TO_SECOND};    nanosleep(&request, &remaining); -  return remaining.tv_sec * NANO_TO_SECOND + remaining.tv_nsec; +  int64_t ret = remaining.tv_sec * NANO_TO_SECOND + remaining.tv_nsec; +  if (ret < 0 || ret > NANO_TO_SECOND) {  // TODO: fix later +    return 0; +  } else { +    return ret; +  }  } -long int nano_time() { +int64_t nano_time() {    struct timespec t = {0, 0};    clock_gettime(CLOCK_MONOTONIC, &t);    return t.tv_sec * NANO_TO_SECOND + t.tv_nsec;  } +uint64_t frame_count = 0;  void tui_main_loop(TUI *tui, WIDGET_BUILDER widget_builder, int fps) { -  const long int frame_nano = +  const uint64_t frame_nano =        (fps == FRAME_UNLIMITED) ? 0 : NANO_TO_SECOND / fps;    int64_t last_remaining = 0;    while (1) { -    const long int start = nano_time(); +    const int64_t start = nano_time();      tui_save_cursor();      tui_refresh(tui);      WIDGET *root_widget = widget_builder(tui); @@ -803,10 +806,11 @@ void tui_main_loop(TUI *tui, WIDGET_BUILDER widget_builder, int fps) {      /*printf("%ld\t%ld", last_frame_time, frame_nano);*/      tui_restore_cursor();      if (fps != FRAME_UNLIMITED) { -      const long int diff = nano_time() - start; +      const int64_t diff = nano_time() - start;        last_remaining = nano_sleep(frame_nano - diff + last_remaining);      }      tui->last_frame = nano_time() - start; +    ++frame_count;      if (kbhit()) {        if (handle_input(tui)) {          return; @@ -848,6 +852,9 @@ void tui_delete_widget(WIDGET *restrict widget) {      case WIDGET_TYPE_PADDING:        _tui_delete_padding(widget);        goto RETURN_SUCCESS; +    case WIDGET_TYPE_TEXT_INPUT: +      _tui_delete_input_text(widget); +      goto RETURN_SUCCESS;    }    fprintf(stderr, "Type error '%d' in %s %d\n", widget->type, __FILE__,            __LINE__); @@ -983,6 +990,26 @@ void _tui_delete_padding(WIDGET *restrict padding) {    free(padding->metadata);  } +extern WIDGET *tui_make_text_input(char *restrict text, COLOR color, +                                   ON_TEXT_INPUT on_text_input) { +  return tui_new_widget( +      WIDGET_TYPE_TEXT_INPUT, +      _tui_make_text_input_metadata(text, color, on_text_input)); +} +extern TEXT_INPUT_METADATA *_tui_make_text_input_metadata( +    char *restrict text, COLOR color, ON_TEXT_INPUT on_text_input) { +  TEXT_INPUT_METADATA *metadata = malloc(sizeof(*metadata)); +  metadata->text = malloc(strlen(text) + 1); +  strcpy(metadata->text, text); +  metadata->color = color; +  metadata->on_text_input = on_text_input; +  return metadata; +} +extern void _tui_delete_input_text(WIDGET *restrict text_input) { +  free(((TEXT_INPUT_METADATA *)text_input->metadata)->text); +  free(text_input->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 8678804..605376f 100644 --- a/src/ui/tui.h +++ b/src/ui/tui.h @@ -52,6 +52,8 @@ typedef struct TUI {    uint64_t last_frame;  // in nanoseconds  } TUI; +constexpr int64_t NANO_TO_SECOND = 1000000000; +  typedef enum WIDGET_TYPE {    WIDGET_TYPE_TEXT,    WIDGET_TYPE_BUTTON, @@ -60,6 +62,7 @@ typedef enum WIDGET_TYPE {    WIDGET_TYPE_BOX,    WIDGET_TYPE_CENTER,    WIDGET_TYPE_PADDING, +  WIDGET_TYPE_TEXT_INPUT,  } WIDGET_TYPE;  typedef struct WIDGET { @@ -107,6 +110,14 @@ typedef struct PADDING_METADATA {    int padding_right;  } PADDING_METADATA; +typedef void (*ON_TEXT_INPUT)(char c); + +typedef struct TEXT_INPUT_METADATA { +  char *text; +  COLOR color; +  ON_TEXT_INPUT on_text_input; +} TEXT_INPUT_METADATA; +  typedef WIDGET *(*WIDGET_BUILDER)(TUI *tui);  extern TUI *tui_init(); @@ -173,6 +184,12 @@ 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_text_input(char *restrict text, COLOR color, +                                   ON_TEXT_INPUT on_text_input); +extern TEXT_INPUT_METADATA *_tui_make_text_input_metadata( +    char *restrict text, COLOR color, ON_TEXT_INPUT on_text_input); +extern void _tui_delete_input_text(WIDGET *restrict text_input); +  extern WIDGET *tui_make_padding(WIDGET *restrict child, int padding_top,                                  int padding_bottom, int padding_left,                                  int padding_right);  |