/* Magic comment for runcprotoall: @generate_cproto@ */ #include "zori.h" #include "zori_registry.h" #include "zori_style.h" #include "zori_widget.h" #include "zori_console.h" #include "zori_screen.h" #include "miao.h" #include #include "str.h" #include "draw.h" #include "monolog.h" /* * Pardon the pun name, but Zori is the submodule that handles the user * interface and the menus. */ /** Handler functionality */ int zori_handler_compare(const void * v1, const void * v2) { const struct zori_handler * h1 = v1; const struct zori_handler * h2 = v2; if (h1->type < h2->type) return -1; if (h1->type > h2->type) return 1; return 0; } struct zori_handler * zori_handlers_add(struct zori_handlers * me, zori_event_type type, zori_handler_func * handler, void * data) { struct zori_handler * result = NULL; result = miao_push_ptr(me); if (result) { result->type = type; result->handler = handler; result->data = data; } miao_qsort(me, zori_handler_compare); return result; } void zori_handlers_done(struct zori_handlers * me) { miao_done(me); } void zori_handlers_init(struct zori_handlers * me) { miao_init(me); } struct zori_handler * zori_handlers_search(struct zori_handlers * me, zori_event_type type) { struct zori_handler * result; struct zori_handler key; key.type = type; key.handler = NULL; key.data = NULL; if (!me) return NULL; result = miao_bsearch(me, zori_handler_compare, &key); return result; } int zori_handlers_handle(struct zori_handlers * me, union zori_event * event) { struct zori_handler * handler = zori_handlers_search(me, event->type); if (!handler) return ZORI_HANDLE_IGNORE; event->any.data = handler->data; return handler->handler(event); } static struct zori_root * the_zori_root = NULL; struct zori_root * zori_get_root(void) { return the_zori_root; } struct zori_widget * zori_get_root_widget(void) { if (!the_zori_root) { return NULL; } return &the_zori_root->widget; } struct zori_widget * zori_get_widget(zori_id id) { struct zori_registry * registry = zori_get_registry(); if (!registry) return NULL; return zori_registry_lookup(registry, id); } zori_id zori_get_unused_id(void) { zori_id id = -1; struct zori_widget * found; do { id++; if (id == INT_MAX) { return ZORI_ID_ERROR; } found = zori_get_widget(id); } while(found); return id; } zori_id zori_initialize_root(void) { if (the_zori_root) return ZORI_ID_OK; the_zori_root = calloc(1, sizeof(*the_zori_root)); if (!the_zori_root) return ZORI_ID_ENOMEM; return ZORI_ID_OK; } zori_id zori_start(struct zori_style * default_style) { zori_id res; struct zori_root * root = NULL; root = zori_get_root(); if (root) return ZORI_ID_OK; res = zori_initialize_default_style(); if (!ZORI_ID_OK_P(res)) return res; res = zori_initialize_registry(); if (!ZORI_ID_OK_P(res)) return res; res = zori_initialize_root(); if (!ZORI_ID_OK_P(res)) return res; root = zori_get_root(); if (default_style) { root->widget.style = *default_style; } else { root->widget.style = *zori_get_default_style(); } root->widget.id = 0; zori_registry_add(zori_get_registry(), the_zori_root->widget.id, &the_zori_root->widget); return the_zori_root->widget.id; } zori_id zori_set_margins(zori_id id, int left, int top, int right, int bottom) { struct zori_widget * widget = zori_get_widget(id); return zori_widget_margins_(widget, left, top, right, bottom); } zori_id zori_set_margin(zori_id id, int size) { struct zori_widget * widget = zori_get_widget(id); return zori_widget_margin_(widget, size); } zori_id zori_set_paddings(zori_id id, int left, int top, int right, int bottom) { struct zori_widget * widget = zori_get_widget(id); return zori_widget_paddings_(widget, left, top, right, bottom); } zori_id zori_set_padding(zori_id id, int size) { struct zori_widget * widget = zori_get_widget(id); return zori_widget_padding_(widget, size); } zori_font * zori_text_font(zori_id id) { struct zori_widget * widget = zori_get_widget(id); return zori_widget_text_font(widget); } /** Destroy the Zori root widget */ void zori_destroy_root(void) { if (the_zori_root) { zori_widget_free(&the_zori_root->widget); } /* free(the_zori_root); is not needed, as it is cleaned up a sa widget */ the_zori_root = NULL; } /* Shut down Zori and destroys all widgets. Return 0 on succes or * negative on error. */ zori_id zori_shutdown() { zori_destroy_root(); zori_destroy_default_style(); zori_destroy_registry(); return ZORI_ID_OK; } /* Creates a new screen widget. Normally this should be the first widget * you create after zori_start. */ zori_id zori_new_screen(zori_id id, zori_display * display); /* Creates a new page widget on the given screen. The page is not * made the active page, unless if it is the first one created. */ zori_id zori_new_page(zori_id id, zori_id screen); /* Activates the page on it's display. All other pages are dectivated and * hidden. */ zori_id zori_activate_page(zori_id page); /* Creates a new generic widget on the given screen with the given * dimensions. */ zori_id zori_new(zori_id screen, zori_rebox * box); /* Sets the flags of a widget. */ zori_id zori_set_flags(zori_id widget, enum zori_flag flags); /* Sets the whole style of a widget. */ zori_id zori_set_style(zori_id id, struct zori_style * style) { struct zori_widget * widget = zori_get_widget(id); if ((!widget) || (!style)) return ZORI_ID_ERROR; widget->style = *style; return widget->id; } /* Gets the whole style of a widget. */ zori_id zori_get_style(zori_id id, struct zori_style * style) { struct zori_widget * widget = zori_get_widget(id); if ((!widget) || (!style)) return ZORI_ID_ERROR; *style = widget->style; return widget->id; } /* Sets the background color of the widget. */ zori_id zori_set_background_color(zori_id id, zori_color color) { struct zori_widget * widget = zori_get_widget(id); if (!widget) return ZORI_ID_ERROR; widget->style.back.color = color; return widget->id; } /* Sets the background bitmap of the widget. */ zori_id zori_set_background_bitmap(zori_id id, zori_bitmap * bitmap) { struct zori_widget * widget = zori_get_widget(id); if (!widget) return ZORI_ID_ERROR; widget->style.back.image = bitmap; return widget->id; } /* Sets the border color of the widget. */ zori_id zori_set_border_color(zori_id id, zori_color color) { struct zori_widget * widget = zori_get_widget(id); if (!widget) return ZORI_ID_ERROR; widget->style.border.color = color; return widget->id; } /* Sets the border bitmap of the widget. */ zori_id zori_set_border_bitmap(zori_id id, zori_bitmap * bitmap) { struct zori_widget * widget = zori_get_widget(id); if (!widget) return ZORI_ID_ERROR; widget->style.border.image = bitmap; return widget->id; } /* Sets the text font of the widget. */ zori_id zori_set_text_font(zori_id id, zori_font * font) { struct zori_widget * widget = zori_get_widget(id); if (!widget) return ZORI_ID_ERROR; widget->style.text.font = font; return widget->id; } /* Sets the text font flags of the widget. */ zori_id zori_set_text_font_flags(zori_id id, int flags) { struct zori_widget * widget = zori_get_widget(id); if (!widget) return ZORI_ID_ERROR; widget->style.text.flags = flags; return widget->id; } /* Creates a new frame widget. */ zori_id zori_new_frame_widget(zori_id parent, zori_rebox box); /* Creates a new (vertical) menu widget. */ zori_id zori_new_menu_widget(zori_id parent, zori_rebox box, char * text); /* Creates a new button widget. */ zori_id zori_new_button_widget(zori_id parent, zori_rebox box, char * text); /* Creates a new conversation widget. */ zori_id zori_new_conversation_widget(zori_id parent, zori_rebox box, char * text); /* Draws the whole UI and all visible parts. */ void zori_draw_all(void) { zori_widget_raise_draw_event(&the_zori_root->widget); zori_widget_raise_overdraw_event(&the_zori_root->widget); } /* Dispatches system events throughout the GUI. */ int zori_handle_system_event(zori_system_event * sysev) { /* All events are passed on to the console regardless if it is active. * Otherwise, theget events go into the system. */ if (!the_zori_root) { return ZORI_ID_EINVAL; } if (the_zori_root && the_zori_root->console) { if (zori_console_active(the_zori_root->console)) { int res = zori_widget_raise_system_event(&the_zori_root->console->widget, sysev); if (!zori_propagate_event_p(res)) return res; } } return zori_widget_raise_system_event(&the_zori_root->widget, sysev); } /* Updates the state of the UI. Pass in the time passed since last update. */ void zori_update(double dt) { struct zori_root * root = zori_get_root(); zori_widget_raise_update_event(&root->widget, dt); } /** Returns the "result" of a widget. 0 if no result was available * because the widget was not "ready" or not "clicked" yet. * Result will be negative if the widget was closed. */ int zori_result(zori_id id) { int result = 0; struct zori_widget * widget = zori_get_widget(id); if (widget) { if (widget->result.ready) { switch (widget->result.type) { case ZORI_RESULT_TYPE_INTEGER: result = widget->result.value.integer; break; default: result = - widget->result.type; break; } widget->result.ready = 0; } } return result; } /** Returns the "result" of a widget. 0 if no result was available * because the widget was not "ready" or not "clicked" yet. */ int zori_get_result(zori_id id, struct zori_result * result) { struct zori_widget * widget = zori_get_widget(id); if (widget && result) { if (widget->result.ready) { (*result) = widget->result; widget->result.ready = 0; return result->ready; } } return 0; } int zori_result_int(zori_id id, int * result); int zori_result_string(zori_id id, char ** result, size_t * size); int zori_result_buffer(zori_id id, char ** result, size_t * size);