ref: 5e303c43dab6c433bc3b59dd34d4672317c5f4e1
parent: b20f94345cd4eb779acf08f3017d02d56aaad9a6
author: Simon Howard <fraggle@gmail.com>
date: Thu Aug 31 14:11:26 EDT 2006
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
--- a/textscreen/txt_window.c
+++ b/textscreen/txt_window.c
@@ -62,6 +62,8 @@
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 @@
{
int i;
+ TXT_EmitSignal(window, "closed");
+
free(window->title);
// Destroy all actions
@@ -143,7 +147,7 @@
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 @@
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 @@
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 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 @@
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 @@
{
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 @@
// 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 @@
// 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 @@
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,8 +268,13 @@
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
LayoutActionArea(window);
@@ -281,16 +300,21 @@
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 @@
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,14 +389,28 @@
// 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))
{
return;
@@ -374,5 +426,20 @@
return;
}
}
+}
+
+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;
}
--- a/textscreen/txt_window.h
+++ b/textscreen/txt_window.h
@@ -31,6 +31,13 @@
#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 @@
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 @@
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 */