Browse Source

Work on cursor display.

Beoran 7 years ago
parent
commit
cf6a89836b
6 changed files with 159 additions and 68 deletions
  1. 27 4
      include/zori/zori.h
  2. 3 0
      include/zori/zori_page.h
  3. 2 2
      src/str.c
  4. 93 33
      src/zori/zori.c
  5. 0 4
      src/zori/zori_page.c
  6. 34 25
      src/zori/zori_screen.c

+ 27 - 4
include/zori/zori.h

@@ -52,6 +52,13 @@ typedef ALLEGRO_USTR zori_string;
 #define ZORI_ID_EINVAL    ((zori_id)(-3))
 
 
+/** Macro for the number of elements of an array .*/
+#define ZORI_ARRAY_AMOUNT(A) ((sizeof(A))/(sizeof(*A)))
+
+/** Macro that expands to the amount of elemnts in the array and the array 
+ * itself, in that order. */
+#define ZORI_AMOUNT_AND_ARRAY(A) ZORI_ARRAY_AMOUNT(A), (A) 
+ 
 
 /* Macro: ZORI_CONTAINER_OF(PTR, TYPE, MEMBER)
  This macro returns, for the given pointer, a pointer to a containing struct
@@ -68,7 +75,10 @@ typedef ALLEGRO_USTR zori_string;
 enum zori_custom_event_type {
   ZORI_EVENT_CUSTOM = ALLEGRO_GET_EVENT_TYPE('z', 'o', 'r', 'i'),
   ZORI_EVENT_UPDATE,
-  ZORI_EVENT_DRAW,
+  /** First draw pass. */
+  ZORI_EVENT_DRAW,  
+  /** Second draw pass for cursors. */
+  ZORI_EVENT_OVERDRAW,
   ZORI_EVENT_DONE,
   ZORI_EVENT_FREE,
   ZORI_EVENT_ACTION, 
@@ -195,12 +205,25 @@ struct zori_widget;
 
 /* Event handler results. */
 enum zori_handle_result {
-  ZORI_HANDLE_ERROR   = -1, 
-  ZORI_HANDLE_OK      = 0,
-  ZORI_HANDLE_IGNORE  = 1,
+  ZORI_HANDLE_ERROR   = -1, /* An error ocurred, stop propagating to children.*/ 
+  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.)*/
+  ZORI_HANDLE_IGNORE  = 1, /* Event wasn't handled, propagate to children. */
+  ZORI_HANDLE_PASS    = 2, /* Event was handled, but needs to be propagated.*/
 };
 
 
+/* Returns whether or not a even needds to be propagated based on the 
+ * result of a handler. */
+static int zori_propagate_event_p(enum zori_handle_result result) {
+  switch(result) {
+     case ZORI_HANDLE_ERROR:  return 0;
+     case ZORI_HANDLE_DONE:   return 0;
+     case ZORI_HANDLE_IGNORE: return !0;
+     case ZORI_HANDLE_PASS:   return !0;
+     default:                 return !0;
+   }
+}
+
 
 typedef enum zori_handle_result (zori_handler_func)(union zori_event * event);
 

+ 3 - 0
include/zori/zori_page.h

@@ -13,6 +13,9 @@ struct zori_page {
 };
 
 
+struct zori_page * zori_widget_to_page(struct zori_widget * widget);
+
+
 struct zori_page * zori_page_new(zori_id id, struct zori_widget * parent);
 
 zori_id zori_new_page(zori_id id, zori_id parent_id);

+ 2 - 2
src/str.c

@@ -427,8 +427,8 @@ USTR * ustrlist_joinwithustr(USTRList * self, USTR * sep) {
   return result;
 }
 
-/* Retruns drom the list the node reached after skipping skip nodes from head. 
-* Returns NULL if there sis no such node or on other failures.
+/* Returns the list the node reached after skipping skip nodes from head. 
+* Returns NULL if there is no such node or on other failures.
 */
 USTRListNode * ustrlist_skipnode(USTRList * self, int skip) { 
   USTRListNode * now ;

+ 93 - 33
src/zori/zori.c

@@ -120,39 +120,97 @@ struct zori_handler * zori_handlers_search(struct zori_handlers * me,  zori_even
 
 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 0;
+  if (!handler) return ZORI_HANDLE_IGNORE;
   event->any.data = handler->data;
   return handler->handler(event);
 }
 
+
+/** Returns whether or not a widget will even handle an event in the first place.
+ * For example, a hidden widget won't draw, and a disabled widget won't 
+ * accept any system events, and a NULL event doesn't accept events at all.. */
+int zori_widget_accepts_event(struct zori_widget * widget, union zori_event * event) {
+  if (!widget) return 0;
+  switch(event->any.type) {
+    case ZORI_EVENT_DRAW:
+      return zori_widget_visible(widget);
+    default:
+      return zori_widget_active(widget);
+  }
+}   
+
+
+/** Raises an event on the widget itself only. */
+int zori_widget_self_raise_event(struct zori_widget * widget, 
+union zori_event * event) {
+  enum zori_handle_result result;
+  if (zori_widget_accepts_event(widget, event)) { 
+    event->any.widget = widget;
+    return zori_handlers_handle(&widget->handlers, event);
+  }
+  /* If the event is not accepted, it is passed on to the child widgets. */
+  return ZORI_HANDLE_PASS;
+}
+
+/* Raises an event on the widget, and if necessary, propagates it on to it's 
+ * children automatically and recursively. */
+int 
+zori_widget_raise_event(struct zori_widget * widget, union zori_event * event) {
+  enum zori_handle_result result = 
+  zori_widget_self_raise_event(widget, event);
+  
+  if (zori_propagate_event_p(result)) {
+    enum zori_handle_result sub;
+    size_t index;
+    for (index = 0; index < miao_size(&widget->children); index++) {
+      struct zori_widget * child = miao_unsafe_get(&widget->children, index);
+      event->any.widget = child;
+      sub = zori_widget_raise_event(child, event);
+      if (sub == ZORI_HANDLE_DONE) {
+        result = ZORI_HANDLE_DONE;
+        break;
+      }
+    }
+  }
+  return result;
+}
+
 int zori_widget_raise_system_event
 (struct zori_widget * widget, zori_system_event * sysev) {
   union zori_event event;
   event.sys.any.type   = sysev->type;
   event.sys.any.widget = widget;
   event.sys.ev         = sysev;
-  return zori_handlers_handle(&widget->handlers, &event);
+  return zori_widget_raise_event(widget, &event);
 }
 
 int zori_widget_raise_draw_event(struct zori_widget * widget) {
   union zori_event event;
   event.draw.any.type   = ZORI_EVENT_DRAW;
   event.draw.any.widget = widget; 
-  return zori_handlers_handle(&widget->handlers, &event);
+  return zori_widget_raise_event(widget, &event);
 }
 
+int zori_widget_raise_overdraw_event(struct zori_widget * widget) {
+  union zori_event event;
+  event.draw.any.type   = ZORI_EVENT_OVERDRAW;
+  event.draw.any.widget = widget; 
+  return zori_widget_raise_event(widget, &event);
+}
+
+
 int zori_widget_raise_done_event(struct zori_widget * widget) {
   union zori_event event;
   event.done.any.type   = ZORI_EVENT_DONE;
   event.done.any.widget = widget; 
-  return zori_handlers_handle(&widget->handlers, &event);
+  return zori_widget_raise_event(widget, &event);
 }
 
 int zori_widget_raise_free_event(struct zori_widget * widget) {
   union zori_event event;
   event.free.any.type   = ZORI_EVENT_FREE;
   event.free.any.widget = widget; 
-  return zori_handlers_handle(&widget->handlers, &event);
+  return zori_widget_raise_event(widget, &event);
 }
 
 int zori_widget_raise_update_event
@@ -161,7 +219,7 @@ int zori_widget_raise_update_event
   event.update.any.type   = ZORI_EVENT_DONE;
   event.update.any.widget = widget;
   event.update.dt         = dt; 
-  return zori_handlers_handle(&widget->handlers, &event);
+  return zori_widget_raise_event(widget, &event);
 }
 
 int zori_widget_raise_action_event
@@ -169,7 +227,7 @@ int zori_widget_raise_action_event
   union zori_event event;
   event.action.any.type   = ZORI_EVENT_ACTION;
   event.action.any.widget = widget;
-  return zori_handlers_handle(&widget->handlers, &event);
+  return zori_widget_raise_event(widget, &event);
 }
 
 
@@ -241,6 +299,8 @@ zori_id zori_start(struct zori_style * default_style) {
   the_default_style->text.color     = al_color_name("white");  
   the_default_style->border.color   = al_color_name("white");  
   the_default_style->back.color     = al_color_name("green");
+  the_default_style->fore.color     = al_color_name("white");  
+
   
   if (default_style) {
     the_zori_root->widget.style = *default_style;
@@ -393,23 +453,23 @@ 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 widget and it's children recursively. */
-void zori_draw_widget(struct zori_widget * widget) {
-  size_t index;
-  if (widget && zori_widget_visible(widget)) {
-    zori_widget_raise_draw_event(widget);
-    for (index = 0; index < miao_size(&widget->children); index++) {
-      struct zori_widget * child = miao_unsafe_get(&widget->children, index);
-      zori_draw_widget(child);
-    }
-  }
+
+/* Lets the widget handle an event and bubbles it on to it's children 
+ * recursively depending on the need to do that. */
+void zori_widget_handle_event(struct zori_widget * widget, union zori_event * event) {
+  zori_widget_raise_event(widget, event);
 }
 
 /* Draws the whole UI and all visible parts. */
 void zori_draw_all(void) {
-  zori_draw_widget(&the_zori_root->widget);
+  zori_widget_raise_draw_event(&the_zori_root->widget);
+  zori_widget_raise_overdraw_event(&the_zori_root->widget);
 }
 
+
+
+
+
 int zori_widget_visible(struct zori_widget * widget)  {
   return widget && ((widget->flags & ZORI_FLAG_HIDDEN) != ZORI_FLAG_HIDDEN);
 }
@@ -437,7 +497,6 @@ int zori_widget_visible_(struct zori_widget * widget, int set)  {
 }
 
 
-
 /* Updates the state of the UI. Pass in the time passed since last update. */
 void zori_update(double dt) 
 {
@@ -448,7 +507,6 @@ void zori_update(double dt)
 zori_id zori_register(zori_id id,  zori_event_type type, zori_handler_func handler, void * extra);
 
 
-
 zori_font * zori_widget_font(struct zori_widget * widget) {
   return widget->style.text.font;
 }
@@ -753,8 +811,8 @@ int zori_console_draw(union zori_event * zevent) {
   y           = zori_widget_y(widget) -  5;
   linehigh    = zori_font_lineheight(font);
   
-  now         = ustrlist_head(&self->text);
-  // skip start lines (to allow scrolling backwards) 
+  /* now         = ustrlist_head(&self->text); */
+  /* skip start lines (to allow scrolling backwards) */
   now         = ustrlist_skipnode(&self->text, self->start);
   
   for (index = high-(linehigh*2); index > 0; index -= linehigh) {
@@ -767,14 +825,16 @@ int zori_console_draw(union zori_event * zevent) {
     now = ustrlistnode_next(now);
   }
   // draw input string
-  zori_font_drawstr(font, color, x, y + high - linehigh, 0, self->input);
+  if (self->input) { 
+    zori_font_drawstr(font, color, x, y + high - linehigh, 0, self->input);
+  }
   // Draw cursor
   linew = al_get_ustr_width(font, self->input);
   al_draw_line(x + linew, y + high - linehigh, x + linew, y + high, color, 1);
   // draw start for debugging
   al_draw_textf(font, color, x, y, 0, "start: %d, size: %d", self->start, 
                 ustrlist_size(&self->text));
-  return ZORI_HANDLE_OK;
+  return ZORI_HANDLE_PASS;
 }
 
 /** Activates or deactivates the console. */
@@ -797,7 +857,7 @@ int zori_console_scroll(struct zori_console * self, int direction) {
   if(direction > 0) self->start++;
   /* Clamp start between 0 and size of list. */
   self->start = bad_clampi(self->start, 0, ustrlist_size(&self->text));
-  return ZORI_HANDLE_OK;
+  return ZORI_HANDLE_DONE;
 }
 
 
@@ -812,13 +872,13 @@ int zori_console_handle_keychar(union zori_event * zevent) {
     // ignore the start-console key
     case ALLEGRO_KEY_F1:
     case ALLEGRO_KEY_F3:
-      return ZORI_HANDLE_OK;
+      return ZORI_HANDLE_DONE;
     case ALLEGRO_KEY_PGUP: return zori_console_scroll(self, 1);
     case ALLEGRO_KEY_PGDN: return zori_console_scroll(self, -1);
     case ALLEGRO_KEY_BACKSPACE:
       // remove last character typed.
       ustr_remove_chr(self->input, ustr_offset(self->input, -1));
-      return ZORI_HANDLE_OK;
+      return ZORI_HANDLE_DONE;
     break;    
     case ALLEGRO_KEY_ENTER: {
       const char * command = ustr_c(self->input);
@@ -829,14 +889,14 @@ int zori_console_handle_keychar(union zori_event * zevent) {
       }
       ustr_truncate(self->input, 0);
       // empty string by truncating it
-      return ZORI_HANDLE_OK;
+      return ZORI_HANDLE_DONE;
       }
     default:
     break;
   }
   
   ustr_appendch(self->input, ch);
-  return ZORI_HANDLE_OK;
+  return ZORI_HANDLE_DONE;
 }
 
 
@@ -853,7 +913,7 @@ int zori_console_handle_keydown(union zori_event * zevent) {
       /* disable console if F1 is pressed. 
        * Note: this shouldnever happen if react is set up well.
        */ 
-      return ZORI_HANDLE_OK;
+      return ZORI_HANDLE_DONE;
     default:
     break;
   }
@@ -869,7 +929,7 @@ int zori_console_handle_mouseaxes(union zori_event * zevent) {
   if(z == 0) return ZORI_HANDLE_IGNORE;
   if(z < 0) return zori_console_scroll(self, -1);
   if(z > 0) return zori_console_scroll(self, +1);
-  return ZORI_HANDLE_OK;
+  return ZORI_HANDLE_DONE;
 }
 
 int zori_console_handle_ignore(union zori_event * zevent) { 
@@ -909,7 +969,7 @@ int zori_console_done(struct zori_widget * widget) {
   ustr_free(self->input);
   self->input   = NULL;
   ustrlist_done(&self->text);
-  return ZORI_HANDLE_OK;
+  return ZORI_HANDLE_DONE;
 }
 
 
@@ -918,7 +978,7 @@ int zori_console_free(struct zori_widget * widget) {
   struct zori_console * self = zori_widget_console(widget);
   zori_console_done(&self->widget);
   free(self);
-  return ZORI_HANDLE_OK;
+  return ZORI_HANDLE_DONE;
 }
 
 /** Allocates a console. */

+ 0 - 4
src/zori/zori_page.c

@@ -6,10 +6,6 @@ struct zori_page * zori_widget_to_page(struct zori_widget * widget) {
   return ZORI_CONTAINER_OF(widget, struct zori_page, widget);
 }
 
-struct zori_page * zori_page_new(zori_id id, struct zori_widget * parent);
-
-zori_id zori_new_page(zori_id id, zori_id parent_id);
-
 struct zori_page * zori_page_new(zori_id id, struct zori_widget * parent) {
   struct zori_page * page = NULL;
   if (!parent) return NULL;

+ 34 - 25
src/zori/zori_screen.c

@@ -7,19 +7,29 @@ struct zori_screen * zori_widget_to_screen(struct zori_widget * widget) {
 }
 
 
-int zori_screen_on_sysevent(union zori_event * event) { 
+/** Handles a mouse axis event and then pass it on to the active page. */
+int zori_screen_on_mouse_axes(union zori_event * event) { 
     struct zori_screen * screen = zori_widget_to_screen(event->any.widget);
 
-    /* Move the mouse cursor before passing on the event to the active page, if any. */
-    if (event->any.type == ALLEGRO_EVENT_MOUSE_AXES) {
-      screen->cursors.mouse.p.x = event->sys.ev->mouse.x;
-      screen->cursors.mouse.p.y = event->sys.ev->mouse.y;
-    }
+    screen->cursors.mouse.p.x = event->sys.ev->mouse.x;
+    screen->cursors.mouse.p.y = event->sys.ev->mouse.y;
     
     if (screen->active_page) {
-      return zori_widget_raise_sys_event(&screen->active_page->widget, &event->sys);
+      return zori_widget_raise_system_event(&screen->active_page->widget, 
+        event->sys.ev);
+    }
+    return ZORI_HANDLE_DONE;
+}
+
+/** Handles a system event by passing it on to the active page.  */
+int zori_screen_on_sysevent(union zori_event * event) { 
+    struct zori_screen * screen = zori_widget_to_screen(event->any.widget);
+  
+    if (screen->active_page) {
+      return zori_widget_raise_system_event(&screen->active_page->widget, 
+        event->sys.ev);
     }
-    return ZORI_HANDLE_OK;
+    return ZORI_HANDLE_DONE;
 }
  
 
@@ -30,11 +40,12 @@ void zori_draw_cursor(const struct zori_cursor * cursor, const struct zori_style
     float x1, x2, x3, y1, y2, y3;
     x1 = cursor->p.x;
     y1 = cursor->p.y;
-    x2 = x1 + 5;
-    y2 = y1 + 10;
-    x3 = x1 + 3;
-    y3 = y1 + 12;  
+    x2 = x1 + 24 + 8;
+    y2 = y1 + 24 - 8;
+    x3 = x1 + 24 - 8;
+    y3 = y1 + 24 + 8;  
     al_draw_filled_triangle(x1, y1, x2, y2, x3, y3, style->fore.color);
+    al_draw_triangle(x1, y1, x2, y2, x3, y3, style->back.color, 1.0);
   }
 };
 
@@ -44,24 +55,22 @@ void zori_draw_cursors(const struct zori_cursors * cursors, const struct zori_st
   zori_draw_cursor(&cursors->mouse, style);
 };
  
-int zori_screen_on_draw(union zori_event * event) {
+int zori_screen_on_overdraw(union zori_event * event) {
   struct zori_screen * screen = zori_widget_to_screen(event->any.widget);
   zori_draw_cursors(&screen->cursors, &screen->widget.style);
-  return ZORI_HANDLE_OK;
+  return ZORI_HANDLE_PASS;
 }
 
-/*
+
 struct zori_handler zori_screen_handlers[] = {
-  { ZORI_SYSTEM_EVENT_KEY_DOWN  , zori_console_handle_keydown   , NULL }, 
-  { ZORI_SYSTEM_EVENT_KEY_UP    , zori_console_handle_ignore    , NULL },
-  { ZORI_SYSTEM_EVENT_KEY_CHAR  , zori_console_handle_keychar   , NULL },
-  { ZORI_EVENT_ _MOUSE_AXES, zori_console_handle_mouseaxes , NULL },
-  { ZORI_EVENT_DRAW             , zori_console_draw             , NULL },
-  { ZORI_EVENT_DONE             , zori_console_handle_ignore    , NULL },
-  { ZORI_EVENT_FREE             , zori_console_handle_ignore    , NULL },
+  { ZORI_SYSTEM_EVENT_KEY_DOWN  , zori_screen_on_sysevent       , NULL }, 
+  { ZORI_SYSTEM_EVENT_KEY_UP    , zori_screen_on_sysevent       , NULL },
+  { ZORI_SYSTEM_EVENT_KEY_CHAR  , zori_screen_on_sysevent       , NULL },
+  { ZORI_SYSTEM_EVENT_MOUSE_AXES, zori_screen_on_mouse_axes     , NULL },
+  { ZORI_EVENT_OVERDRAW         , zori_screen_on_overdraw       , NULL },
   { -1, NULL, NULL }
 };
-*/
+
 
 struct zori_screen * 
 zori_screen_init(struct zori_screen * screen, zori_display * display) {
@@ -81,7 +90,7 @@ struct zori_screen * zori_screen_new(zori_id id, zori_display * display) {
   box.size.x = al_get_display_width(display);
   box.size.y = al_get_display_height(display);
   zori_widget_initall(&screen->widget, id, &zori_get_root()->widget, 
-                      &box, NULL, 0, NULL); 
+                      &box, NULL, ZORI_AMOUNT_AND_ARRAY(zori_screen_handlers)); 
   if (!zori_screen_init(screen, display)) {
     free(screen);
     screen = NULL;
@@ -98,7 +107,7 @@ zori_id zori_new_screen(zori_id id, zori_display * display) {
 
 
 zori_id zori_active_page(zori_id screen_id) {
-  struct zori_screen * screen = zori_widget_to_page(zori_get_widget(screen_id));
+  struct zori_screen * screen = zori_widget_to_screen(zori_get_widget(screen_id));
   if (!screen) {
     return ZORI_ID_EINVAL;
   }