~ruther/CTU-FEE-B0B35APO-Semestral-project

a9a15fd4c8b0151159e7f97d058703f4dc83bada — František Boháček 4 years ago d9704d2
feat: add base gui functions
A lib-pheripherals/src/direction.c => lib-pheripherals/src/direction.c +18 -0
@@ 0,0 1,18 @@
#include "direction.h"

void direction_move_xy(direction_t direction, int32_t *x, int32_t *y, int16_t amount) {
  switch (direction) {
  case LEFT:
    *x -= amount;
    break;
  case RIGHT:
    *x += amount;
    break;
  case UP:
    *y -= amount;
    break;
  case DOWN:
    *y += amount;
    break;
  }
}

A text-viewer/include/gui.h => text-viewer/include/gui.h +148 -0
@@ 0,0 1,148 @@
#ifndef __GUI_H__
#define __GUI_H__

#include "display_utils.h"
#include "font.h"
#include "input.h"
#include "logger.h"
#include "mzapo_pheripherals.h"

typedef struct renderer_t renderer_t;
typedef struct component_t component_t;
typedef struct gui_t gui_t;
typedef struct container_t container_t;

typedef void (*render_function)(container_t *container, component_t *component,
                                gui_t *gui);
typedef void (*update_function)(container_t *container, component_t *component,
                                gui_t *gui);

struct component_t {
  int16_t x;
  int16_t y;

  uint16_t width;
  uint16_t height;

  render_function render;
  update_function update;

  bool focusable;
  bool focused;

  void *state;
};

typedef enum {
  CONT_TABLE,
  CONT_GROUP,
  CONT_ONE,
} container_type_t;

typedef struct {
  // items
  // scroll
} list_container_t;

typedef struct {
  component_t *components;
  uint16_t size;
  uint16_t count;
} group_container_t;

typedef struct {
  component_t component;
  bool set;
} one_container_t;

typedef union {
  list_container_t list;
  group_container_t group;
  one_container_t one;
} container_inner_t;

struct container_t {
  container_type_t type;
  container_inner_t inner;

  bool focusable;
  bool focused;

  int16_t x;
  int16_t y;

  uint16_t width;
  uint16_t height;
};

typedef struct {
  container_t *containers;
  uint16_t containers_size;
  uint16_t containers_count;
} window_t;

struct gui_t {
  window_t *active_window;
  commands_t *commands;
  renderer_t *renderer;
  mzapo_pheripherals_t *pheripherals;
  logger_t *logger;

  size2d_t size;
};

gui_t gui_create(logger_t *logger, commands_t *commands,
                 renderer_t *renderer, mzapo_pheripherals_t *pheripherals);

void gui_render(gui_t *gui);
void gui_update(gui_t *gui);

void gui_set_active_window(gui_t *gui, window_t *window);

// gui_window.c
window_t gui_window_create(container_t *containers, uint16_t size);
container_t *gui_window_add_container(window_t *window, container_t container);

// gui_container.c
void gui_container_render(gui_t *gui, container_t *container);
void gui_container_update(gui_t *gui, container_t *container);

// gui_component.c
component_t gui_component_create(int16_t x, int16_t y, uint16_t w, uint16_t h, render_function render, update_function update);

bool gui_is_component_visible(gui_t *gui, container_t *container,
                              component_t *component);

void gui_component_render(gui_t *gui, container_t *container,
                          component_t *component);

void gui_component_update(gui_t *gui, container_t *container,
                          component_t *component);

coords_t gui_component_get_absolute_position(container_t *container,
                                             component_t *component);
coords_t gui_component_get_screen_position(container_t *container,
                                          component_t *component);

// gui_one_container.c
container_t gui_one_container_create(int16_t x, int16_t y);

component_t *gui_one_container_set_component(container_t *container,
                                     component_t component);
component_t *gui_one_container_get_component(container_t *container);

void gui_one_container_render(gui_t *gui, container_t *container);
void gui_one_container_update(gui_t *gui, container_t *container);

// gui_group_container.c
container_t gui_group_container_create(int16_t x, int16_t y, component_t *components, uint16_t components_size);

component_t *gui_group_container_add_component(container_t *container,
                                       component_t component);

void gui_group_container_render(gui_t *gui, container_t *container);
void gui_group_container_update(gui_t *gui, container_t *container);

// handle commands

#endif // __GUI_H__

A text-viewer/src/gui.c => text-viewer/src/gui.c +56 -0
@@ 0,0 1,56 @@
#include "gui.h"
#include "input.h"
#include "logger.h"
#include "renderer.h"
#include <jpeglib.h>

gui_t gui_create(logger_t *logger, commands_t *commands, renderer_t *renderer,
                 mzapo_pheripherals_t *pheripherals) {
  gui_t gui = {
      .pheripherals = pheripherals,
      .renderer = renderer,
      .active_window = NULL,
      .commands = commands,
      .logger = logger,
      .size = {.x = DISPLAY_WIDTH, .y = DISPLAY_HEIGHT},
  };

  return gui;
}

void gui_render(gui_t *gui) {
  renderer_clear(gui->renderer);
  window_t *window = gui->active_window;
  if (window == NULL) {
    logger_warn(gui->logger, __FILE__, __FUNCTION__, __LINE__,
                "No active window");
    return;
  }

  for (int i = 0; i < window->containers_count; i++) {
    gui_container_render(gui, &window->containers[i]);
  }

  renderer_render(gui->renderer);
}

component_t *gui_one_container_get_component(container_t *container) {
  return &container->inner.one.component;
}

void gui_update(gui_t *gui) {
  window_t *window = gui->active_window;
  if (window == NULL) {
    logger_warn(gui->logger, __FILE__, __FUNCTION__, __LINE__,
                "No active window");
    return;
  }

  for (int i = 0; i < window->containers_count; i++) {
    gui_container_update(gui, &window->containers[i]);
  }
}

void gui_set_active_window(gui_t *gui, window_t *window) {
  gui->active_window = window;
}

A text-viewer/src/gui_component.c => text-viewer/src/gui_component.c +56 -0
@@ 0,0 1,56 @@
#include "gui.h"

component_t gui_component_create(int16_t x, int16_t y, uint16_t w, uint16_t h,
                                 render_function render,
                                 update_function update) {
  component_t component = {
    .x = x,
    .y = y,
    .width = w,
    .height = h,
    .render = render,
    .update = update,
    .focused = false,
    .focusable = false,
    .state = NULL
  };

  return component;
}

bool gui_is_component_visible(gui_t *gui, container_t *container,
                              component_t *component) {
  coords_t pos = gui_component_get_screen_position(container, component);

  bool visible_x = (pos.x >= 0 && pos.x < gui->size.x) ||
                   (pos.x < 0 && pos.x + component->width > 0);
  bool visible_y = (pos.y >= 0 && pos.y < gui->size.y) ||
                   (pos.y < 0 && pos.y + component->height > 0);

  return visible_x && visible_y;
}

void gui_component_render(gui_t *gui, container_t *container,
                          component_t *component) {
  component->render(container, component, gui);
}

void gui_component_update(gui_t *gui, container_t *container,
                          component_t *component) {
  component->update(container, component, gui);
}

coords_t gui_component_get_absolute_position(container_t *container,
                                             component_t *component) {
  coords_t pos = {
    .x = container->x + component->x,
    .y = container->y + component->y
  };

  return pos;
}

coords_t gui_component_get_screen_position(container_t *container,
                                          component_t *component) {
  return gui_component_get_absolute_position(container, component);
}

A text-viewer/src/gui_container.c => text-viewer/src/gui_container.c +35 -0
@@ 0,0 1,35 @@
#include "gui.h"
#include "renderer.h"

void gui_container_render(gui_t *gui, container_t *container) {
  renderer_translate(gui->renderer, container->x, container->y);
  renderer_set_draw_area(gui->renderer, container->width, container->height);

  switch (container->type) {
  case CONT_TABLE:
    // TODO: implement
    break;
  case CONT_GROUP:
    gui_group_container_render(gui, container);
    break;
  case CONT_ONE:
    gui_one_container_render(gui, container);
    break;
  }

  renderer_clear_translate(gui->renderer);
}

void gui_container_update(gui_t *gui, container_t *container) {
  switch (container->type) {
  case CONT_TABLE:
    // TODO: implement
    break;
  case CONT_GROUP:
    gui_group_container_update(gui, container);
    break;
  case CONT_ONE:
    gui_one_container_update(gui, container);
    break;
  }
}

A text-viewer/src/gui_group_container.c => text-viewer/src/gui_group_container.c +40 -0
@@ 0,0 1,40 @@
#include "gui.h"

component_t *gui_group_container_add_component(container_t *container,
                                       component_t component) {
  group_container_t group = container->inner.group;
  if (group.count >= group.size) {
    return false;
  }

  group.components[group.count++] = component;
  container->inner.group = group;
  return &group.components[group.count - 1];
}

void gui_group_container_render(gui_t *gui, container_t *container) {
  group_container_t group = container->inner.group;
  for (int i = 0; i < group.size; i++) {
    gui_component_render(gui, container, &group.components[i]);
  }
}

void gui_group_container_update(gui_t *gui, container_t *container) {
  group_container_t group = container->inner.group;
  for (int i = 0; i < group.size; i++) {
    gui_component_update(gui, container, &group.components[i]);
  }
  container->inner.group = group;
}

container_t gui_group_container_create(int16_t x, int16_t y, component_t *components, uint16_t components_size) {
  container_t container = {.x = x,
                           .y = y,
                           .type = CONT_GROUP,
                           .focusable = false,
                           .focused = false,
                           .inner = {.group = {.components = components,
                                               .size = components_size,
                                               .count = 0}}};
  return container;
}

A text-viewer/src/gui_one_container.c => text-viewer/src/gui_one_container.c +37 -0
@@ 0,0 1,37 @@
#include "gui.h"

component_t* gui_one_container_set_component(container_t *container,
                                     component_t component) {
  container->inner.one.component = component;
  container->inner.one.set = true;

  return &container->inner.one.component;
}

void gui_one_container_render(gui_t *gui, container_t *container) {
  if (container->inner.one.set) {
    gui_component_render(gui, container, &container->inner.one.component);
  }
}

void gui_one_container_update(gui_t *gui, container_t *container) {
  if (container->inner.one.set) {
    gui_component_update(gui, container, &container->inner.one.component);

    if (container->inner.one.component.focusable) {
      container->inner.one.component.focused = container->focused;
    }
  }
}

container_t gui_one_container_create(int16_t x, int16_t y) {
  container_t container = {.x = x,
                           .y = y,
                           .type = CONT_ONE,
                           .focusable = false,
                           .focused = false,
                           .inner = {.one = {
                                         .set = false,
                                     }}};
  return container;
}

A text-viewer/src/gui_window.c => text-viewer/src/gui_window.c +20 -0
@@ 0,0 1,20 @@
#include "gui.h"

window_t gui_window_create(container_t *containers, uint16_t size) {
  window_t window = {
    .containers = containers,
    .containers_size = size,
    .containers_count = 0,
  };

  return window;
}

container_t *gui_window_add_container(window_t *window, container_t container) {
  if (window->containers_count >= window->containers_size) {
    return NULL;
  }

  window->containers[window->containers_count++] = container;
  return &window->containers[window->containers_count - 1];
}

Do not follow this link