foxygit / doom Log in
commit 5e303c43dab6c433bc3b59dd34d4672317c5f4e1
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Thu Aug 31 18:11:26 2006 +0000
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Thu Aug 31 18:11:26 2006 +0000

    Add window listener functions to allow spying on keys and mouse buttons
    received by windows. Emit a 'closed' signal when a window is closed.
    Allow windows to have no action buttons.

    Subversion-branch: /trunk/chocolate-doom
    Subversion-revision: 576
---
 textscreen/txt_window.c | 111 ++++++++++++++++++++++++++++++++++++++----------
 textscreen/txt_window.h |  20 +++++++++
 2 files changed, 109 insertions(+), 22 deletions(-)

diff --git a/textscreen/txt_window.c b/textscreen/txt_window.c
index d9a3abca..2cb9ffc4 100644
--- a/textscreen/txt_window.c
+++ b/textscreen/txt_window.c
@@ -62,6 +62,8 @@ txt_window_t *TXT_NewWindow(char *title)
     win->y = TXT_SCREEN_H / 2;
     win->horiz_align = TXT_HORIZ_CENTER;
     win->vert_align = TXT_VERT_CENTER;
+    win->key_listener = NULL;
+    win->mouse_listener = NULL;

     TXT_AddWidget(win, TXT_NewSeparator(NULL));

@@ -82,6 +84,8 @@ void TXT_CloseWindow(txt_window_t *window)
 {
     int i;

+    TXT_EmitSignal(window, "closed");
+
     free(window->title);

     // Destroy all actions
@@ -143,7 +147,7 @@ static void LayoutActionArea(txt_window_t *window)
         TXT_CalcWidgetSize(widget);

         widget->x = window->window_x + 2;
-        widget->y = window->window_y + window->window_h - 2;
+        widget->y = window->window_y + window->window_h - widget->h - 1;
     }

     // Draw the center action
@@ -155,7 +159,7 @@ static void LayoutActionArea(txt_window_t *window)
         TXT_CalcWidgetSize(widget);

         widget->x = window->window_x + (window->window_w - widget->w - 2) / 2;
-        widget->y = window->window_y + window->window_h - 2;
+        widget->y = window->window_y + window->window_h - widget->h - 1;
     }

     // Draw the right action
@@ -167,7 +171,7 @@ static void LayoutActionArea(txt_window_t *window)
         TXT_CalcWidgetSize(widget);

         widget->x = window->window_x + window->window_w - 2 - widget->w;
-        widget->y = window->window_y + window->window_h - 2;
+        widget->y = window->window_y + window->window_h - widget->h - 1;
     }
 }

@@ -184,13 +188,13 @@ static void DrawActionArea(txt_window_t *window)
     }
 }

-static int ActionAreaWidth(txt_window_t *window)
+static void CalcActionAreaSize(txt_window_t *window, int *w, int *h)
 {
     txt_widget_t *widget;
-    int w;
     int i;

-    w = 1;
+    *w = 1;
+    *h = 0;

     // Calculate the width of all the action widgets and use this
     // to create an overall min. width of the action area
@@ -202,11 +206,14 @@ static int ActionAreaWidth(txt_window_t *window)
         if (widget != NULL)
         {
             TXT_CalcWidgetSize(widget);
-            w += widget->w + 1;
+            *w += widget->w + 1;
+
+            if (widget->h > *h)
+            {
+                *h = widget->h;
+            }
         }
     }
-
-    return w;
 }

 // Sets size and position of all widgets in a window
@@ -215,7 +222,7 @@ void TXT_LayoutWindow(txt_window_t *window)
 {
     txt_widget_t *widgets = (txt_widget_t *) window;
     int widgets_w;
-    int actionarea_w;
+    int actionarea_w, actionarea_h;

     // Calculate size of table

@@ -227,7 +234,7 @@ void TXT_LayoutWindow(txt_window_t *window)
     // Calculate the size of the action area
     // Make window wide enough to action area

-    actionarea_w = ActionAreaWidth(window);
+    CalcActionAreaSize(window, &actionarea_w, &actionarea_h);

     if (actionarea_w > widgets_w)
         widgets_w = actionarea_w;
@@ -235,7 +242,7 @@ void TXT_LayoutWindow(txt_window_t *window)
     // Set the window size based on widgets_w

     window->window_w = widgets_w + 2;
-    window->window_h = widgets->h + 3;
+    window->window_h = widgets->h + 1;

     // If the window has a title, add an extra two lines

@@ -244,6 +251,13 @@ void TXT_LayoutWindow(txt_window_t *window)
         window->window_h += 2;
     }

+    // If the window has an action area, add extra lines
+
+    if (actionarea_h > 0)
+    {
+        window->window_h += actionarea_h + 1;
+    }
+
     // Use the x,y position as the centerpoint and find the location to
     // draw the window.

@@ -254,7 +268,12 @@ void TXT_LayoutWindow(txt_window_t *window)
     widgets->w = widgets_w - 2;
     // widgets->h        (already set)
     widgets->x = window->window_x + 2;
-    widgets->y = window->window_y + window->window_h - widgets->h - 3;
+    widgets->y = window->window_y;
+
+    if (window->title != NULL)
+    {
+        widgets->y += 2;
+    }

     // Layout the table and action area

@@ -281,16 +300,21 @@ void TXT_DrawWindow(txt_window_t *window, int selected)

     TXT_DrawWidget(window, selected);

-    // Separator for action area
+    // Draw an action area, if we have one

-    widgets = (txt_widget_t *) window;
+    if (widgets->y + widgets->h < window->window_y + window->window_h - 1)
+    {
+        // Separator for action area

-    TXT_DrawSeparator(window->window_x, widgets->y + widgets->h,
-                      window->window_w);
+        widgets = (txt_widget_t *) window;

-    // Action area at the window bottom
+        TXT_DrawSeparator(window->window_x, widgets->y + widgets->h,
+                          window->window_w);

-    DrawActionArea(window);
+        // Action area at the window bottom
+
+        DrawActionArea(window);
+    }
 }

 void TXT_SetWindowPosition(txt_window_t *window,
@@ -319,6 +343,20 @@ static void MouseButtonPress(txt_window_t *window, int b)

     TXT_GetMousePosition(&x, &y);

+    // Try the mouse button listener
+    // This happens whether it is in the window range or not
+
+    if (window->mouse_listener != NULL)
+    {
+        // Mouse listener can eat button presses
+
+        if (window->mouse_listener(window, x, y, b,
+                                   window->mouse_listener_data))
+        {
+            return;
+        }
+    }
+
     // Is it within the table range?

     widgets = (txt_widget_t *) window;
@@ -351,13 +389,27 @@ void TXT_WindowKeyPress(txt_window_t *window, int c)

     // Is this a mouse button ?

-    if (c == TXT_MOUSE_LEFT)
+    if (c == TXT_MOUSE_LEFT
+     || c == TXT_MOUSE_MIDDLE
+     || c == TXT_MOUSE_RIGHT)
     {
         MouseButtonPress(window, c);
         return;
     }
-
-    // Send to the currently selected widget first
+
+    // Try the window key spy
+
+    if (window->key_listener != NULL)
+    {
+        // key listener can eat keys
+
+        if (window->key_listener(window, c, window->key_listener_data))
+        {
+            return;
+        }
+    }
+
+    // Send to the currently selected widget

     if (TXT_WidgetKeyPress(window, c))
     {
@@ -376,3 +428,18 @@ void TXT_WindowKeyPress(txt_window_t *window, int c)
     }
 }

+void TXT_SetKeyListener(txt_window_t *window, TxtWindowKeyPress key_listener,
+                        void *user_data)
+{
+    window->key_listener = key_listener;
+    window->key_listener_data = user_data;
+}
+
+void TXT_SetMouseListener(txt_window_t *window,
+                          TxtWindowMousePress mouse_listener,
+                          void *user_data)
+{
+    window->mouse_listener = mouse_listener;
+    window->mouse_listener_data = user_data;
+}
+
diff --git a/textscreen/txt_window.h b/textscreen/txt_window.h
index 5e01a16d..a71307ae 100644
--- a/textscreen/txt_window.h
+++ b/textscreen/txt_window.h
@@ -31,6 +31,13 @@ typedef struct txt_window_s txt_window_t;
 #include "txt_table.h"
 #include "txt_window_action.h"

+// Callback function for window key presses
+
+typedef int (*TxtWindowKeyPress)(txt_window_t *window, int key, void *user_data);
+typedef int (*TxtWindowMousePress)(txt_window_t *window,
+                                   int x, int y, int b,
+                                   void *user_data);
+
 struct txt_window_s
 {
     // Base class: all windows are tables with one column.
@@ -51,6 +58,13 @@ struct txt_window_s

     txt_window_action_t *actions[3];

+    // Callback functions to invoke when keys/mouse buttons are pressed
+
+    TxtWindowKeyPress key_listener;
+    void *key_listener_data;
+    TxtWindowMousePress mouse_listener;
+    void *mouse_listener_data;
+
     // These are set automatically when the window is drawn

     int window_x, window_y;
@@ -65,6 +79,12 @@ void TXT_SetWindowPosition(txt_window_t *window,
                            int x, int y);
 void TXT_SetWindowAction(txt_window_t *window, txt_horiz_align_t position,
                          txt_window_action_t *action);
+void TXT_SetKeyListener(txt_window_t *window,
+                        TxtWindowKeyPress key_listener,
+                        void *user_data);
+void TXT_SetMouseListener(txt_window_t *window,
+                          TxtWindowMousePress mouse_listener,
+                          void *user_data);

 #endif /* #ifndef TXT_WINDOW_T */