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];
+}