zori.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. #ifndef zori_H_INCLUDED
  2. #define zori_H_INCLUDED
  3. #include <stdbool.h>
  4. #include "eruta.h"
  5. #include "rebox.h"
  6. #include "miao.h"
  7. #include "str.h"
  8. /* Defines for C11/C99/C89 portability */
  9. #ifndef inline
  10. #define inline inline
  11. #endif
  12. /* Macros for possible later system library portability. */
  13. #define ZORI_EVENT_TYPE_IS_USER(T) ALLEGRO_EVENT_TYPE_IS_USER(T)
  14. #define ZORI_SYSTEM_EVENT_KEY_DOWN ALLEGRO_EVENT_KEY_DOWN
  15. #define ZORI_SYSTEM_EVENT_KEY_UP ALLEGRO_EVENT_KEY_UP
  16. #define ZORI_SYSTEM_EVENT_KEY_CHAR ALLEGRO_EVENT_KEY_CHAR
  17. #define ZORI_SYSTEM_EVENT_MOUSE_AXES ALLEGRO_EVENT_MOUSE_AXES
  18. /* Typedefs for possible later system library portability. */
  19. typedef ALLEGRO_COLOR zori_color;
  20. typedef ALLEGRO_BITMAP zori_bitmap;
  21. typedef ALLEGRO_FONT zori_font;
  22. typedef ALLEGRO_EVENT zori_system_event;
  23. typedef ALLEGRO_EVENT_TYPE zori_event_type;
  24. typedef ALLEGRO_DISPLAY zori_display;
  25. typedef Point zori_point;
  26. typedef Rebox zori_rebox;
  27. typedef int zori_id;
  28. typedef ALLEGRO_USTR zori_string;
  29. /* Macros for possible portability. */
  30. #define zori_font_lineheight(FONT) al_get_font_line_height(FONT)
  31. #define zori_font_drawstr(FONT, COLOR, X, Y, ATTR, TEXT) al_draw_ustr(FONT, COLOR, X, Y, ATTR, TEXT)
  32. /* Default sizes of a widget. */
  33. #define ZORI_WIDGET_DEFAULT_W 640
  34. #define ZORI_WIDGET_DEFAULT_H 480
  35. /* Zori ID's. */
  36. #define ZORI_ID_OK_P(ID) ((ID) > -1)
  37. #define ZORI_ID_OK ((zori_id)(0))
  38. #define ZORI_ID_ERROR ((zori_id)(-1))
  39. #define ZORI_ID_ENOMEM ((zori_id)(-2))
  40. #define ZORI_ID_EINVAL ((zori_id)(-3))
  41. /** Macro for the number of elements of an array .*/
  42. #define ZORI_ARRAY_AMOUNT(A) ((sizeof(A))/(sizeof(*A)))
  43. /** Macro that expands to the amount of elemnts in the array and the array
  44. * itself, in that order. */
  45. #define ZORI_AMOUNT_AND_ARRAY(A) ZORI_ARRAY_AMOUNT(A), (A)
  46. /* Macro: ZORI_CONTAINER_OF(PTR, TYPE, MEMBER)
  47. This macro returns, for the given pointer, a pointer to a containing struct
  48. of type TYPE, in which PTR is a member named MEMBER.
  49. This enables cool ways of type genericity and extension in plain C.
  50. It should not run afoul of strict aliasing since it passes over a char * pointer
  51. and a pointer of a containing struct or union.
  52. */
  53. #define ZORI_CONTAINER_OF(PTR, TYPE, MEMBER) \
  54. ((TYPE *)(((char *)(PTR)) - offsetof(TYPE, MEMBER)))
  55. /** Custom event types, used in conjunction with Allegro event types. */
  56. enum zori_custom_event_type {
  57. ZORI_EVENT_CUSTOM = ALLEGRO_GET_EVENT_TYPE('z', 'o', 'r', 'i'),
  58. ZORI_EVENT_UPDATE,
  59. /** First draw pass. */
  60. ZORI_EVENT_DRAW,
  61. /** Second draw pass for cursors. */
  62. ZORI_EVENT_OVERDRAW,
  63. ZORI_EVENT_DONE,
  64. ZORI_EVENT_FREE,
  65. ZORI_EVENT_ACTION,
  66. };
  67. struct zori_widget;
  68. /* Common fields for an event. */
  69. struct zori_any_event {
  70. /* Type of the event, possibly copied from sysev. */
  71. zori_event_type type;
  72. /* Widget the event is sent to. */
  73. struct zori_widget * widget;
  74. /* Data specified in the handler. */
  75. void * data;
  76. };
  77. /* System event, that is coming from the underlying library used, e.g. Allegro. */
  78. struct zori_sys_event {
  79. struct zori_any_event any;
  80. zori_system_event * ev;
  81. };
  82. /* Update event, when UI has to update (animations, etc). */
  83. struct zori_update_event {
  84. struct zori_any_event any;
  85. double dt;
  86. };
  87. /* Draw event when the UI has to draw itself. */
  88. struct zori_draw_event {
  89. struct zori_any_event any;
  90. };
  91. /* Cleanup event. */
  92. struct zori_done_event {
  93. struct zori_any_event any;
  94. };
  95. /* Cleanup event. */
  96. struct zori_free_event {
  97. struct zori_any_event any;
  98. };
  99. /* Action event. */
  100. struct zori_action_event {
  101. struct zori_any_event any;
  102. };
  103. /** An event that ZORI can handle. The union is cunningly overlaid so
  104. * that the type field and the any field can be used in all cases. */
  105. union zori_event {
  106. /* Type of the event, possibly copied from sysev. */
  107. zori_event_type type;
  108. struct zori_any_event any;
  109. struct zori_sys_event sys;
  110. struct zori_draw_event draw;
  111. struct zori_update_event update;
  112. struct zori_done_event done;
  113. struct zori_free_event free;
  114. struct zori_action_event action;
  115. };
  116. /* Helper functions to get widget from an event. */
  117. static inline struct zori_widget *
  118. zori_event_widget(union zori_event * event) {
  119. if (!event) return NULL;
  120. return event->any.widget;
  121. }
  122. /* Helper functions to get data from an event. */
  123. static inline void * zori_event_data(union zori_event * event) {
  124. if (!event) return NULL;
  125. return event->any.data;
  126. }
  127. /* Helper function that checks if an event is a sys_event. */
  128. static inline bool zori_event_is_sys_event(union zori_event * event) {
  129. if (!event) return false;
  130. return (!ALLEGRO_EVENT_TYPE_IS_USER(event->type));
  131. }
  132. /* Helper functions to get system event from an event. Type checks the type. */
  133. static inline zori_system_event * zori_event_system_event(union zori_event * event) {
  134. if (!event) return NULL;
  135. if (!zori_event_is_sys_event(event)) return NULL;
  136. return event->sys.ev;
  137. }
  138. /* Helper functions to set widget for an event. */
  139. static inline struct zori_widget *
  140. zori_event_set_widget(union zori_event * event, struct zori_widget * widget) {
  141. if (!event) return NULL;
  142. return event->any.widget = widget;
  143. }
  144. /* Helper functions to set data for an event. */
  145. static inline void * zori_event_set_data(union zori_event * event, void * data) {
  146. if (!event) return NULL;
  147. return event->any.data = data;
  148. }
  149. /* A style part is a color, image and font applied to a part of the GUI. */
  150. struct zori_stylepart {
  151. zori_color color;
  152. zori_bitmap * image;
  153. zori_font * font;
  154. };
  155. /* A style is a set of style parts for different parts of the GUI. */
  156. struct zori_style {
  157. struct zori_stylepart fore;
  158. struct zori_stylepart back;
  159. struct zori_stylepart text;
  160. struct zori_stylepart border;
  161. };
  162. struct zori_widget;
  163. /* Event handler results. */
  164. enum zori_handle_result {
  165. ZORI_HANDLE_ERROR = -1, /* An error ocurred, stop propagating to children.*/
  166. ZORI_HANDLE_DONE = 0, /* The event was handled and consumed, no need to propagate to children automatically (widget may re-send event manually to children.)*/
  167. ZORI_HANDLE_IGNORE = 1, /* Event wasn't handled, propagate to children. */
  168. ZORI_HANDLE_PASS = 2, /* Event was handled, but needs to be propagated.*/
  169. };
  170. /* Returns whether or not a even needds to be propagated based on the
  171. * result of a handler. */
  172. static int zori_propagate_event_p(enum zori_handle_result result) {
  173. switch(result) {
  174. case ZORI_HANDLE_ERROR: return 0;
  175. case ZORI_HANDLE_DONE: return 0;
  176. case ZORI_HANDLE_IGNORE: return !0;
  177. case ZORI_HANDLE_PASS: return !0;
  178. default: return !0;
  179. }
  180. }
  181. typedef enum zori_handle_result (zori_handler_func)(union zori_event * event);
  182. /* A single event handler */
  183. struct zori_handler {
  184. zori_event_type type;
  185. zori_handler_func * handler;
  186. void * data;
  187. };
  188. /* A dynamic array of event handlers event handlers. */
  189. struct zori_handlers miao_of_type(struct zori_handler);
  190. /* An entry in a widget registry. */
  191. struct zori_registry_entry {
  192. zori_id id;
  193. struct zori_widget * widget;
  194. };
  195. /* A widget registry as a dynamic array of entries. */
  196. struct zori_registry miao_of_type(struct zori_registry_entry);
  197. /* Generic flags for several zori structs. */
  198. enum zori_flag {
  199. /* The object is not visible, though it may still be interacted with.*/
  200. ZORI_FLAG_HIDDEN = 1 << 0,
  201. /* The object cannot be interacted with, though it is still visible. */
  202. ZORI_FLAG_DISABLED = 1 << 1,
  203. /* The object is both hidden and disabled. */
  204. ZORI_FLAG_DEACTIVATED = ZORI_FLAG_HIDDEN | ZORI_FLAG_DISABLED,
  205. };
  206. /* Mouse or keyboard/joystick cursor. */
  207. struct zori_cursor {
  208. zori_point p;
  209. struct zori_widget * hover;
  210. struct zori_widget * focus;
  211. zori_bitmap * bitmap;
  212. enum zori_flag flags;
  213. };
  214. /* Support multiple cursors... */
  215. struct zori_cursors {
  216. struct zori_cursor mouse;
  217. struct zori_cursor keyjoy;
  218. };
  219. /*
  220. on_enter
  221. on_enter(data = {})
  222. on_event(*args)
  223. on_event(*data)
  224. on_key_down(*args)
  225. on_leave(name=nil)
  226. on_mouse_axes(t, x, y, z, w, dx, dy, dz, dw)
  227. on_mouse_button_down(t, x, y, z, w, b)
  228. on_mouse_button_up(t, x, y, z, w, b)
  229. on_mouse_in(x, y, from)
  230. on_mouse_out(x, y, to)
  231. on_resize
  232. */
  233. struct zori_widget;
  234. struct zori_widget_list miao_of_type(struct zori_widget *);
  235. struct zori_widget {
  236. /* ID of the widget, used in most external API's. */
  237. zori_id id;
  238. /* Root level widget under which this widget is active. */
  239. struct zori_widget * root;
  240. /* Position and size of the widget. */
  241. zori_rebox box;
  242. /* Z ordering. */
  243. int z;
  244. /* Style. */
  245. struct zori_style style;
  246. /* Handlers. */
  247. struct zori_handlers handlers;
  248. /* Related widgets. */
  249. struct zori_widget * parent;
  250. struct zori_widget_list children;
  251. /* Flags. */
  252. enum zori_flag flags;
  253. };
  254. /* An array of widget pointers. */
  255. struct zori_widget_array miao_of_type(struct zori_widget *);
  256. /* forward declarations. */
  257. struct zori_screen;
  258. struct zori_console;
  259. /*
  260. * Root level widget, my spread out over several displays.
  261. * In Zori, there can only be a single root level widget active.
  262. * It's ID is always 0;
  263. */
  264. struct zori_root {
  265. /* A root is a widget. */
  266. struct zori_widget widget;
  267. /* Current active screen widget if any. */
  268. struct zori_screen * active_screen;
  269. /* Current active console if any. */
  270. struct zori_console * console;
  271. };
  272. /* Forward declaration of a page. */
  273. struct zori_page;
  274. struct zori_root * zori_get_root(void);
  275. /* Initializes Zori and creates a top level widget. Returns 0 on success
  276. * or negative on error. The style will be copied and set as default
  277. * if it is not NULL. Otherwise a built-in style will be used.
  278. * Not that ZORI will NOT clean up any images or fonts it uses by itself.
  279. */
  280. zori_id zori_start(struct zori_style * default_style);
  281. /* Shut down Zori and destroys all widgets. Return 0 on succes or
  282. * negative on error.
  283. */
  284. zori_id zori_shutdown();
  285. /* Creates a new screen widget. Normally this should be the first widget
  286. * you create after zori_start. */
  287. /* Activates the page on it's display. All other pages are dectivated and
  288. * hidden. */
  289. zori_id zori_activate_page(zori_id page);
  290. /* Creates a new generic widget on the given screen with the given
  291. * dimensions. */
  292. zori_id zori_new(zori_id screen, zori_rebox * box);
  293. /* Sets the flags of a widget. */
  294. zori_id zori_set_flags(zori_id widget, enum zori_flag flags);
  295. /* Sets the whole style of a widget. */
  296. zori_id zori_set_style(zori_id id, struct zori_style * style);
  297. /* Sets the background color of the widget. */
  298. zori_id zori_set_background_color(zori_id id, zori_color color);
  299. /* Sets the foreground color of the widget. */
  300. zori_id zori_set_foreground_color(zori_id id, zori_color color);
  301. /* Creates a new frame widget. */
  302. zori_id zori_new_frame_widget(zori_id parent, zori_rebox box);
  303. /* Creates a new (vertical) menu widget. */
  304. zori_id zori_new_menu_widget(zori_id parent, zori_rebox box, char * text);
  305. /* Creates a new button widget. */
  306. zori_id zori_new_button_widget(zori_id parent, zori_rebox box, char * text);
  307. /* Creates a new conversation widget. */
  308. zori_id zori_new_conversation_widget(zori_id parent, zori_rebox box, char * text);
  309. /* Draws the whole UI and all visible parts. */
  310. void zori_draw_all(void);
  311. /* Updates the state of the UI. Pass in the time passed since last update. */
  312. void zori_update(double dt);
  313. /* Registers an event handler for a widget. */
  314. zori_id zori_register(zori_id id, zori_event_type type, zori_handler_func handler, void * extra);
  315. int zori_registry_entry_compare(const void *v1, const void *v2);
  316. zori_id zori_registry_init(struct zori_registry *registry);
  317. zori_id zori_registry_add(struct zori_registry *registry, zori_id id, struct zori_widget *widget);
  318. struct zori_registry_entry *zori_registry_lookup_entry(struct zori_registry *registry, zori_id id);
  319. struct zori_widget *zori_registry_lookup(struct zori_registry *registry, zori_id id);
  320. zori_id zori_registry_remove(struct zori_registry *registry, zori_id id);
  321. int zori_handler_compare(const void *v1, const void *v2);
  322. struct zori_handler *zori_handlers_add(struct zori_handlers *me, zori_event_type type, zori_handler_func *handler, void *data);
  323. void zori_handlers_done(struct zori_handlers *me);
  324. void zori_handlers_init(struct zori_handlers *me);
  325. struct zori_handler *zori_handlers_search(struct zori_handlers *me, zori_event_type type);
  326. int zori_handlers_handle(struct zori_handlers *me, union zori_event *event);
  327. int zori_widget_raise_system_event(struct zori_widget *widget, zori_system_event *sysev);
  328. int zori_widget_raise_draw_event(struct zori_widget *widget);
  329. int zori_widget_raise_done_event(struct zori_widget *widget);
  330. int zori_widget_raise_free_event(struct zori_widget *widget);
  331. int zori_widget_raise_update_event(struct zori_widget *widget, double dt);
  332. int zori_widget_raise_action_event(struct zori_widget *widget);
  333. int zori_widget_compare(const void *v1, const void *v2);
  334. struct zori_widget *zori_get_widget(zori_id id);
  335. zori_id zori_get_unused_id(void);
  336. struct zori_handler *zori_widget_add_handler(struct zori_widget *widget, zori_event_type type, zori_handler_func *handler, void *data);
  337. struct zori_handler *zori_widget_add_handlers(struct zori_widget *widget, struct zori_handler *handlers, size_t amount);
  338. zori_id zori_start(struct zori_style *default_style);
  339. struct zori_widget *zori_widget_done(struct zori_widget *widget);
  340. void zori_widget_free(struct zori_widget *widget);
  341. struct zori_widget *zori_widget_add_child(struct zori_widget *parent, struct zori_widget *child);
  342. struct zori_widget *zori_widget_init(struct zori_widget *widget, zori_id id, struct zori_widget *parent, zori_rebox *box, struct zori_style *style);
  343. zori_id zori_shutdown(void);
  344. struct zori_widget *zori_widget_initall(struct zori_widget *widget, zori_id id, struct zori_widget *parent, zori_rebox *box, struct zori_style *style, size_t amount, struct zori_handler *handlers);
  345. void zori_draw_all(void);
  346. int zori_widget_visible(struct zori_widget *widget);
  347. int zori_widget_active(struct zori_widget *widget);
  348. int zori_widget_active_(struct zori_widget *widget, int set);
  349. void zori_update(double dt);
  350. zori_font *zori_widget_font(struct zori_widget *widget);
  351. zori_color zori_widget_forecolor(struct zori_widget *widget);
  352. zori_color zori_widget_backcolor(struct zori_widget *widget);
  353. int zori_widget_h(struct zori_widget *widget);
  354. int zori_widget_w(struct zori_widget *widget);
  355. int zori_widget_x(struct zori_widget *widget);
  356. int zori_widget_y(struct zori_widget *widget);
  357. void zori_widget_drawroundframe(struct zori_widget *self);
  358. typedef int (zori_console_command)(struct zori_widget *, const char * command, void * data);
  359. /* A console is a console for command-line interaction and error display. When it's active it captures all input (as long as it's active) */
  360. struct zori_console {
  361. struct zori_widget widget;
  362. USTRList text;
  363. int count;
  364. int max;
  365. int start;
  366. int charw;
  367. int cursor;
  368. char * buf;
  369. USTR * input;
  370. zori_console_command * command; // called when a command has been entered, if set.
  371. void * command_data; // command data.
  372. };
  373. struct zori_console *zori_widget_console(struct zori_widget *widget);
  374. int zori_console_docommand(struct zori_console *self, const char *text);
  375. int zori_console_addstr(struct zori_console *self, const char *str);
  376. int zori_console_addustr(struct zori_console *self, const ALLEGRO_USTR *ustr);
  377. int zori_console_puts(struct zori_console *self, const char *str);
  378. int zori_console_vprintf(struct zori_console *self, const char *format, va_list args);
  379. int zori_console_printf(struct zori_console *self, const char *format, ...);
  380. int zori_console_draw(union zori_event *zevent);
  381. void zori_console_active_(struct zori_console *self, int active);
  382. int zori_console_active(struct zori_console *self);
  383. int zori_console_scroll(struct zori_console *self, int direction);
  384. int zori_console_handle_keychar(union zori_event *zevent);
  385. int zori_console_handle_keydown(union zori_event *zevent);
  386. int zori_console_handle_mouseaxes(union zori_event *zevent);
  387. int zori_console_handle_ignore(union zori_event *zevent);
  388. int zori_console_handle(struct zori_widget *widget, zori_system_event *sevent);
  389. int zori_console_done(struct zori_widget *widget);
  390. int zori_console_free(struct zori_widget *widget);
  391. struct zori_console *zori_console_alloc(void);
  392. struct zori_console *zori_console_initall(struct zori_console *self, int id, zori_rebox *bounds, struct zori_style *style);
  393. struct zori_console *zori_console_new(int id, zori_rebox *bounds, struct zori_style *style);
  394. int zori_handle_system_event(zori_system_event * sysev);
  395. #endif