Commit c6aeb37e by beoran

Reorganize Zori GUI code and clean up a few memory leaks.

parent 32fdae82
......@@ -85,6 +85,8 @@ set(ERUTA_SRC_FILES
......@@ -36,8 +36,7 @@ struct ui_state {
void ui_setup(void);
void ui_state_init(struct ui_state * ui);
void ui_state_init(struct ui_state * ui, zori_display * display, zori_font * font);
......@@ -17,7 +17,7 @@
* In ZORI, there is only one top-level widget, the root, however, every widget
* can contain any amount of child widgets. One level below the root widget are
* the screen widgets which are intent to handle the GUI on one physical screen
* or display. Every GUI page can have different "pages", but only one page
* or display. Every GUI screen can have different "pages", but only one page
* should be active per screen. The idea is that a GUI page represents a single
* GUI mode such as the main menu, the settings menu, the in game menu, etc,
* where you definitely want only one to be active at any given time.
......@@ -447,6 +447,11 @@ struct zori_widget {
/* Generic "result", of last operation on widget, normally zero. */
int result;
/* Cannot easily use the handers for destroying the widget, so in stead
* provide a destructor. */
void (*destroy)(struct zori_widget * widget);
......@@ -603,8 +608,38 @@ int zori_result(int zori_id);
int zori_mark_widget(struct zori_widget * widget);
int zori_registry_entry_compare(const void *v1, const void *v2);
zori_id zori_registry_init(struct zori_registry *registry);
zori_id zori_registry_add(struct zori_registry *registry, zori_id id, struct zori_widget *widget);
struct zori_registry_entry *zori_registry_lookup_entry(struct zori_registry *registry, zori_id id);
struct zori_widget *zori_registry_lookup(struct zori_registry *registry, zori_id id);
zori_id zori_registry_remove(struct zori_registry *registry, zori_id id);
int zori_handler_compare(const void *v1, const void *v2);
struct zori_handler *zori_handlers_add(struct zori_handlers *me, zori_event_type type, zori_handler_func *handler, void *data);
void zori_handlers_done(struct zori_handlers *me);
void zori_handlers_init(struct zori_handlers *me);
struct zori_handler *zori_handlers_search(struct zori_handlers *me, zori_event_type type);
int zori_handlers_handle(struct zori_handlers *me, union zori_event *event);
struct zori_root *zori_get_root(void);
struct zori_widget *zori_get_widget(zori_id id);
zori_id zori_get_unused_id(void);
zori_id zori_start(struct zori_style *default_style);
zori_id zori_set_margins(zori_id id, int left, int top, int right, int bottom);
zori_id zori_set_margin(zori_id id, int size);
zori_id zori_set_paddings(zori_id id, int left, int top, int right, int bottom);
zori_id zori_set_padding(zori_id id, int size);
zori_font *zori_text_font(zori_id id);
zori_id zori_shutdown(void);
void zori_draw_all(void);
int zori_handle_system_event(zori_system_event *sysev);
void zori_update(double dt);
int zori_result(zori_id id);
#ifndef zori_widget_H_INCLUDED
#define zori_widget_H_INCLUDED
void zori_widget_draw_background(struct zori_widget * widget);
struct zori_widget;
void zori_widget_cleanup_widget_only(struct zori_widget * widget);
void zori_widget_destroy_widget_only(struct zori_widget * widget);
void zori_widget_call_destructor_and_destroy(struct zori_widget * widget);
void zori_widget_destroy(struct zori_widget * widget);
int zori_widget_accepts_event(struct zori_widget *widget, union zori_event *event);
int zori_widget_self_raise_event(struct zori_widget *widget, union zori_event *event);
int zori_widget_raise_event(struct zori_widget *widget, union zori_event *event);
int zori_widget_raise_system_event(struct zori_widget *widget, zori_system_event *sysev);
int zori_widget_raise_draw_event(struct zori_widget *widget);
int zori_widget_raise_overdraw_event(struct zori_widget *widget);
int zori_widget_raise_done_event(struct zori_widget *widget);
int zori_widget_raise_free_event(struct zori_widget *widget);
int zori_widget_raise_update_event(struct zori_widget *widget, double dt);
int zori_widget_raise_action_event(struct zori_widget *widget);
int zori_widget_raise_close_event(struct zori_widget *widget, struct zori_widget *from);
int zori_widget_compare(const void *v1, const void *v2);
struct zori_handler *zori_widget_add_handler(struct zori_widget *widget, zori_event_type type, zori_handler_func *handler, void *data);
struct zori_handler *zori_widget_add_handlers(struct zori_widget *widget, struct zori_handler *handlers, size_t amount);
struct zori_widget *zori_widget_done(struct zori_widget *widget);
void zori_widget_free(struct zori_widget *widget);
struct zori_widget *zori_widget_add_child(struct zori_widget *parent, struct zori_widget *child);
zori_id zori_widget_margins_(struct zori_widget *widget, int left, int top, int right, int bottom);
zori_id zori_widget_margin_(struct zori_widget *widget, int size);
void zori_widget_draw_background(struct zori_widget *widget);
int zori_widget_visible(struct zori_widget *widget);
int zori_widget_active(struct zori_widget *widget);
int zori_widget_active_(struct zori_widget *widget, int set);
int zori_widget_visible_(struct zori_widget *widget, int set);
int zori_widget_hover(struct zori_widget *widget);
int zori_widget_hover_(struct zori_widget *widget, int set);
int zori_widget_marked(struct zori_widget *widget);
int zori_widget_marked_(struct zori_widget *widget, int set);
int zori_xy_inside_widget_p(struct zori_widget *widget, double x, double y);
zori_font *zori_widget_font(struct zori_widget *widget);
zori_color zori_widget_forecolor(struct zori_widget *widget);
zori_color zori_widget_backcolor(struct zori_widget *widget);
int zori_widget_h(struct zori_widget *widget);
int zori_widget_w(struct zori_widget *widget);
int zori_widget_x(struct zori_widget *widget);
int zori_widget_y(struct zori_widget *widget);
int zori_widget_count_children(struct zori_widget *widget);
struct zori_widget *zori_widget_get_child(struct zori_widget *widget, int index);
zori_id zori_widget_paddings_(struct zori_widget *widget, int left, int top, int right, int bottom);
zori_id zori_widget_padding_(struct zori_widget *widget, int size);
zori_font *zori_widget_text_font(struct zori_widget *widget);
struct zori_widget *zori_widget_init(struct zori_widget *widget, zori_widget_type type, zori_id id, struct zori_widget *parent, zori_rebox *box, struct zori_style *style);
struct zori_widget *zori_widget_initall(struct zori_widget *widget, zori_widget_type type, int id, struct zori_widget *parent, zori_rebox *box, struct zori_style *style, struct zori_handler *handlers, size_t amount);
void zori_widget_handle_event(struct zori_widget *widget, union zori_event *event);
struct zori_widget *zori_widget_find_parent(struct zori_widget *widget, _Bool (*predicate)(struct zori_widget *parent, void *extra), void *extra);
bool zori_widget_is_type(struct zori_widget * widget, zori_widget_type type);
_Bool zori_widget_is_type_predicate(struct zori_widget *widget, void *extra);
struct zori_widget *zori_widget_get_parent_of_type(struct zori_widget *widget, zori_widget_type type);
struct zori_screen *zori_widget_get_screen(struct zori_widget *widget);
int zori_mark_widget(struct zori_widget *widget);
......@@ -238,18 +238,20 @@ void state_free(State * self) {
self->area = NULL;
/* Disable the active tile map */
state_active_map_id_(self, -1);
/* Disable console immediately. */
self->console = NULL;
/* Disable gui. */
/* Clean up scripting state. */
self->console = NULL; /* disable console immediately. */
/* Deallocate stored objects. */
// font_free(self->font);
/* Clean up alegro. */
/* End logging. */
......@@ -500,7 +502,8 @@ int state_initjoystick(State * self) {
/* Initialize the GUI for the Eruta engine. */
State * state_init_gui(State * self, BOOL fullscreen) {
ui_state_init(&self->ui, self->display, self->font);
return self;
......@@ -7,6 +7,7 @@
#include "zori_button.h"
#include "zori_page.h"
#include "zori_menu.h"
#include "monolog.h"
#include "ui.h"
......@@ -38,52 +39,59 @@ char INTRO_TEXT2[] = "Something happened, and I was changed!";
zori_id ui_state_make_sub_menu(zori_id parent, int x, int y, int w, int bh);
void ui_state_init(struct ui_state * ui) { }
#ifdef COMMENT_
/* Set up Zori GUI. */
void ui_state_init(struct ui_state * ui, zori_displkay * display) {
void ui_state_init(struct ui_state * ui,
zori_display * display,
zori_font * font
) {
struct zori_style style;
Rebox box;
memset(&style, 0, sizeof(style));
style.text.font = self->font;
style.text.font = font;
style.text.color = color_rgb(255,255,255);
style.back.color = color_rgba(64,0,0, 191);
if ( !ZORI_ID_OK_P(zori_start(&style)) ) {
return state_errmsg_(self, "Out of memory when allocating GUI.");
LOG_ERROR( "Out of memory when allocating GUI.");
if (zori_start(&style) != ZORI_ID_OK) {
LOG_ERROR( "Cannot set up ZORI UI screen.");
self->ui.screen = zori_new_screen(-1, self->display);
ui->screen = zori_new_screen(-1, display);
if(!ZORI_ID_OK_P(self->ui.screen)) {
return state_errmsg_(self, "Could not init GUI screen.\n");
if(!ZORI_ID_OK_P(ui->screen)) {
LOG_ERROR( "Cannot set up main screen.");
self->ui.main_page = zori_new_page(-1, self->ui.screen);
LOG_NOTE("Main page: %d\n", self->ui.main_page);
ui-> = zori_new_page(-1, ui->screen);
LOG_NOTE("Main page: %d\n", ui->;
box = rebox_make(280, 80, 140, 240);
self->ui.main_menu = zori_new_menu(-1, main_page, &box);
ui-> = zori_new_menu(-1, ui->, &box);
LOG_NOTE("Main menu: %d\n", self->ui.main_menu);
LOG_NOTE("Main menu: %d\n", ui->;
Rebox box = rebox_make(300, 100, 100, 60);
self->ui.continue_button = zori_new_button(-1, main_menu, &box, "Continue");
LOG_NOTE("Button: %d\n", self->ui.continue_button);
ui->main.button.resume = zori_new_button(-1, ui->, &box, "Continue");
LOG_NOTE("Button: %d\n", ui->main.button.resume);
Rebox box = rebox_make(300, 200, 100, 60);
self->ui.new_button = zori_new_button(-1, main_menu, &box, "New");
LOG_NOTE("Button: %d\n", self->ui.new_button);
ui-> = zori_new_button(-1, ui->, &box, "New");
LOG_NOTE("Button: %d\n", ui->;
#ifdef COMMENT_
#include "monolog.h"
#include "zori.h"
#include "zori_widget.h"
#include "zori_caption.h"
#include "zori_button.h"
struct zori_button * zori_widget_to_button(struct zori_widget * widget) {
if (!zori_widget_is_type(widget, ZORI_WIDGET_TYPE_BUTTON)) return NULL;
return ZORI_CONTAINER_OF(widget, struct zori_button, widget);
......@@ -73,10 +75,18 @@ zori_button_text_(struct zori_button * button, zori_string * text) {
return button;
void zori_button_destroy(struct zori_widget * widget) {
struct zori_button * button = zori_widget_to_button(widget);
if (button) {
struct zori_button *
zori_button_init(struct zori_button * button,const char * text) {
if (button) {
zori_caption_init(&button->caption, text);
button->widget.destroy = zori_button_destroy;
return button;
#include <assert.h>
#include "zori.h"
#include "zori_widget.h"
#include "zori_console.h"
#include "draw.h"
struct zori_console * zori_widget_to_console(struct zori_widget * widget) {
if (!zori_widget_is_type(widget, ZORI_WIDGET_TYPE_CONSOLE)) return NULL;
return ZORI_CONTAINER_OF(widget, struct zori_console, widget);
/* Helper struct that keeps track of the BYTE positions within
a c string or USTR where a line or word starts or ends with a given maxwidth. */
......@@ -454,6 +459,13 @@ struct zori_console * zori_console_alloc() {
return calloc(1 , sizeof(struct zori_console));
/** Destructor for console. */
void zori_console_destroy(struct zori_widget * widget) {
struct zori_console * console = zori_widget_to_console(widget);
/* Amount of lines of display the console hat o keep track of. */
#define ZORI_CONSOLE_MAX 200
......@@ -462,6 +474,7 @@ struct zori_console * zori_console_initall(struct zori_console * self, int id, z
struct zori_root * root = zori_get_root();
if(!self) return NULL;
/* Allow only a single console. */
if (root->console) return NULL;
if(!zori_widget_initall(&self->widget, ZORI_WIDGET_TYPE_CONSOLE, id, &root->widget, bounds, style, ZORI_ARRAY_AND_AMOUNT(zori_console_actions) ) ) {
......@@ -486,6 +499,8 @@ struct zori_console * zori_console_initall(struct zori_console * self, int id, z
self->command_data = NULL;
/* Ony one console may be active. */
root->console = self;
self->widget.destroy = zori_console_destroy;
return self;
#include "monolog.h"
#include "zori.h"
#include "zori_widget.h"
#include "zori_caption.h"
#include "zori_longtext.h"
......@@ -8,6 +10,7 @@
struct zori_longtext * zori_widget_to_longtext(struct zori_widget * widget) {
if (!zori_widget_is_type(widget, ZORI_WIDGET_TYPE_LONGTEXT)) return NULL;
return ZORI_CONTAINER_OF(widget, struct zori_longtext, widget);
#include "zori.h"
#include "zori_widget.h"
#include "zori_caption.h"
#include "zori_menu.h"
struct zori_menu * zori_widget_to_menu(struct zori_widget * widget) {
if (!widget) return NULL;
if (!zori_widget_is_type(widget, ZORI_WIDGET_TYPE_MENU)) return NULL;
return ZORI_CONTAINER_OF(widget, struct zori_menu, widget);
#include "zori.h"
#include "zori_widget.h"
#include "zori_caption.h"
#include "zori_page.h"
struct zori_page * zori_widget_to_page(struct zori_widget * widget) {
if (!zori_widget_is_type(widget, ZORI_WIDGET_TYPE_PAGE)) return NULL;
return ZORI_CONTAINER_OF(widget, struct zori_page, widget);
#include "zori.h"
#include "zori_widget.h"
#include "zori_caption.h"
#include "zori_page.h"
#include "zori_screen.h"
struct zori_screen * zori_widget_to_screen(struct zori_widget * widget) {
if (!zori_widget_is_type(widget, ZORI_WIDGET_TYPE_SCREEN)) return NULL;
return ZORI_CONTAINER_OF(widget, struct zori_screen, widget);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment