Add a signals architecture to allow callbacks on GUI events.

Make all widget classes initialise widgets by calling TXT_InitWidget.

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 501
This commit is contained in:
Simon Howard 2006-05-22 00:20:48 +00:00
parent d90a63ed26
commit 283f71d0f5
9 changed files with 138 additions and 18 deletions

View file

@ -22,16 +22,23 @@ int radiobutton_value;
txt_window_t *firstwin;
int checkbox_value;
void CloseWindow(txt_widget_t *widget, void *user_data)
{
TXT_CloseWindow(firstwin);
}
void SetupWindow(void)
{
txt_window_t *window;
txt_table_t *table;
txt_table_t *leftpane, *rightpane;
txt_button_t *button;
char buf[100];
int i;
window = TXT_NewWindow("Window test");
TXT_AddWidget(window, TXT_NewSeparator("Main section"));
table = TXT_NewTable(3);
TXT_AddWidget(window, TXT_NewLabel(" This is a multiline label.\n"
@ -66,6 +73,11 @@ void SetupWindow(void)
TXT_AddWidget(rightpane, TXT_NewRadioButton("Snake", &radiobutton_value,
RADIO_VALUE_SNAKE));
button = TXT_NewButton("Close Window");
TXT_AddWidget(window, button);
TXT_SignalConnect(button, "pressed", CloseWindow, NULL);
firstwin = window;
}

View file

@ -1,6 +1,8 @@
#include <string.h>
#include "doomkeys.h"
#include "txt_button.h"
#include "txt_io.h"
#include "txt_main.h"
@ -44,11 +46,15 @@ static void TXT_ButtonDestructor(txt_widget_t *widget)
txt_button_t *button = (txt_button_t *) widget;
free(button->label);
free(button);
}
static int TXT_ButtonKeyPress(txt_widget_t *widget, int key)
{
if (key == KEY_ENTER)
{
TXT_EmitSignal(widget, "pressed");
}
return 0;
}
@ -66,9 +72,7 @@ txt_button_t *TXT_NewButton(char *label)
button = malloc(sizeof(txt_button_t));
button->widget.widget_class = &txt_button_class;
button->widget.selectable = 1;
button->widget.visible = 1;
TXT_InitWidget(button, &txt_button_class);
button->label = strdup(label);
return button;

View file

@ -91,9 +91,7 @@ txt_checkbox_t *TXT_NewCheckBox(char *label, int *variable)
checkbox = malloc(sizeof(txt_checkbox_t));
checkbox->widget.widget_class = &txt_checkbox_class;
checkbox->widget.selectable = 1;
checkbox->widget.visible = 1;
TXT_InitWidget(checkbox, &txt_checkbox_class);
checkbox->label = strdup(label);
checkbox->variable = variable;

View file

@ -39,7 +39,6 @@ static void TXT_LabelDestructor(txt_widget_t *widget)
free(label->label);
free(label->lines);
free(label);
}
txt_widget_class_t txt_label_class =
@ -98,9 +97,8 @@ txt_label_t *TXT_NewLabel(char *text)
label = malloc(sizeof(txt_label_t));
label->widget.widget_class = &txt_label_class;
TXT_InitWidget(label, &txt_label_class);
label->widget.selectable = 0;
label->widget.visible = 1;
label->label = strdup(text);
TXT_SplitLabel(label);

View file

@ -91,9 +91,7 @@ txt_radiobutton_t *TXT_NewRadioButton(char *label, int *variable, int value)
radiobutton = malloc(sizeof(txt_radiobutton_t));
radiobutton->widget.widget_class = &txt_radiobutton_class;
radiobutton->widget.selectable = 1;
radiobutton->widget.visible = 1;
TXT_InitWidget(radiobutton, &txt_radiobutton_class);
radiobutton->label = strdup(label);
radiobutton->variable = variable;
radiobutton->value = value;

View file

@ -71,9 +71,8 @@ txt_separator_t *TXT_NewSeparator(char *label)
separator = malloc(sizeof(txt_separator_t));
separator->widget.widget_class = &txt_separator_class;
TXT_InitWidget(separator, &txt_separator_class);
separator->widget.selectable = 0;
separator->widget.visible = 1;
if (label != NULL)
{

View file

@ -408,12 +408,10 @@ txt_widget_class_t txt_table_class =
void TXT_InitTable(txt_table_t *table, int columns)
{
TXT_InitWidget(table, &txt_table_class);
table->columns = columns;
table->widgets = NULL;
table->num_widgets = 0;
table->widget.widget_class = &txt_table_class;
table->widget.visible = 1;
table->widget.selectable = 1;
table->selected_x = 0;
table->selected_y = 0;
}

View file

@ -1,7 +1,111 @@
#include <stdlib.h>
#include <string.h>
#include "txt_widget.h"
typedef struct
{
char *signal_name;
TxtWidgetSignalFunc func;
void *user_data;
} txt_callback_t;
struct txt_callback_table_s
{
txt_callback_t *callbacks;
int num_callbacks;
};
txt_callback_table_t *TXT_NewCallbackTable(void)
{
txt_callback_table_t *table;
table = malloc(sizeof(txt_callback_table_t));
table->callbacks = NULL;
table->num_callbacks = 0;
return table;
}
void TXT_DestroyCallbackTable(txt_callback_table_t *table)
{
int i;
for (i=0; i<table->num_callbacks; ++i)
{
free(table->callbacks[i].signal_name);
}
free(table->callbacks);
free(table);
}
void TXT_InitWidget(void *uncast_widget, txt_widget_class_t *widget_class)
{
txt_widget_t *widget = (txt_widget_t *) uncast_widget;
widget->widget_class = widget_class;
widget->callback_table = TXT_NewCallbackTable();
// Default values: visible and selectable
widget->selectable = 1;
widget->visible = 1;
}
void TXT_SignalConnect(txt_widget_t *widget,
char *signal_name,
TxtWidgetSignalFunc func,
void *user_data)
{
txt_callback_table_t *table;
txt_callback_t *callback;
int i;
table = widget->callback_table;
for (i=0; i<table->num_callbacks; ++i)
{
if (!strcmp(signal_name, table->callbacks[i].signal_name))
{
// Replace existing signal
table->callbacks[i].func = func;
table->callbacks[i].user_data = user_data;
break;
}
}
// Add a new callback to the table
table->callbacks
= realloc(table->callbacks,
sizeof(txt_callback_t) * (table->num_callbacks + 1));
callback = &table->callbacks[table->num_callbacks];
++table->num_callbacks;
callback->signal_name = strdup(signal_name);
callback->func = func;
callback->user_data = user_data;
}
void TXT_EmitSignal(txt_widget_t *widget, char *signal_name)
{
txt_callback_table_t *table;
int i;
table = widget->callback_table;
for (i=0; i<table->num_callbacks; ++i)
{
if (!strcmp(table->callbacks[i].signal_name, signal_name))
{
table->callbacks[i].func(widget, table->callbacks[i].user_data);
break;
}
}
}
void TXT_CalcWidgetSize(txt_widget_t *widget, int *w, int *h)
{
return widget->widget_class->size_calc(widget, w, h);
@ -15,6 +119,8 @@ void TXT_DrawWidget(txt_widget_t *widget, int w, int selected)
void TXT_DestroyWidget(txt_widget_t *widget)
{
widget->widget_class->destructor(widget);
TXT_DestroyCallbackTable(widget->callback_table);
free(widget);
}
int TXT_WidgetKeyPress(txt_widget_t *widget, int key)

View file

@ -29,11 +29,13 @@
typedef struct txt_widget_class_s txt_widget_class_t;
typedef struct txt_widget_s txt_widget_t;
typedef struct txt_callback_table_s txt_callback_table_t;
typedef void (*TxtWidgetSizeCalc)(txt_widget_t *widget, int *w, int *h);
typedef void (*TxtWidgetDrawer)(txt_widget_t *widget, int w, int selected);
typedef void (*TxtWidgetDestroy)(txt_widget_t *widget);
typedef int (*TxtWidgetKeyPress)(txt_widget_t *widget, int key);
typedef void (*TxtWidgetSignalFunc)(txt_widget_t *widget, void *user_data);
struct txt_widget_class_s
{
@ -46,12 +48,17 @@ struct txt_widget_class_s
struct txt_widget_s
{
txt_widget_class_t *widget_class;
txt_callback_table_t *callback_table;
int selectable;
int visible;
};
void TXT_InitWidget(void *widget, txt_widget_class_t *widget_class);
void TXT_CalcWidgetSize(txt_widget_t *widget, int *w, int *h);
void TXT_DrawWidget(txt_widget_t *widget, int w, int selected);
void TXT_SignalConnect(txt_widget_t *widget, char *signal_name,
TxtWidgetSignalFunc func, void *user_data);
void TXT_EmitSignal(txt_widget_t *widget, char *signal_name);
int TXT_WidgetKeyPress(txt_widget_t *widget, int key);
void TXT_DestroyWidget(txt_widget_t *widget);