ref: 517af9477b7269564f3ba8c0ccc6ef53c78a7abb
parent: b3e5170bbba1c3048da86a5291cd45524abfeac2
author: Simon Howard <[email protected]>
date: Fri Jun 2 15:29:24 EDT 2006
textscreen: Rejig how the entire drawing process works. Add a recursive layout method that assigns the position and size of widgets for the whole window before drawing. Add another method that responds to mouse button presses. Allow windows to have no title bar by specifying NULL as the title. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 547
--- a/textscreen/txt_button.c
+++ b/textscreen/txt_button.c
@@ -9,20 +9,23 @@
#include "txt_main.h"
#include "txt_window.h"
-static void TXT_ButtonSizeCalc(TXT_UNCAST_ARG(button), int *w, int *h)
+static void TXT_ButtonSizeCalc(TXT_UNCAST_ARG(button))
{
TXT_CAST_ARG(txt_button_t, button);
// Minimum width is the string length + two spaces for padding
- *w = strlen(button->label) + 2;
- *h = 1;
+ button->widget.w = strlen(button->label) + 2;
+ button->widget.h = 1;
}
-static void TXT_ButtonDrawer(TXT_UNCAST_ARG(button), int w, int selected)
+static void TXT_ButtonDrawer(TXT_UNCAST_ARG(button), int selected)
{
TXT_CAST_ARG(txt_button_t, button);
int i;
+ int w;
+
+ w = button->widget.w;
TXT_BGColor(TXT_COLOR_BLUE, 0);
TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
--- a/textscreen/txt_checkbox.c
+++ b/textscreen/txt_checkbox.c
@@ -9,20 +9,23 @@
#include "txt_main.h"
#include "txt_window.h"
-static void TXT_CheckBoxSizeCalc(TXT_UNCAST_ARG(checkbox), int *w, int *h)
+static void TXT_CheckBoxSizeCalc(TXT_UNCAST_ARG(checkbox))
{
TXT_CAST_ARG(txt_checkbox_t, checkbox);
// Minimum width is the string length + two spaces for padding
- *w = strlen(checkbox->label) + 6;
- *h = 1;
+ checkbox->widget.w = strlen(checkbox->label) + 6;
+ checkbox->widget.h = 1;
}
-static void TXT_CheckBoxDrawer(TXT_UNCAST_ARG(checkbox), int w, int selected)
+static void TXT_CheckBoxDrawer(TXT_UNCAST_ARG(checkbox), int selected)
{
TXT_CAST_ARG(txt_checkbox_t, checkbox);
int i;
+ int w;
+
+ w = checkbox->widget.w;
TXT_BGColor(TXT_COLOR_BLUE, 0);
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
--- a/textscreen/txt_gui.c
+++ b/textscreen/txt_gui.c
@@ -1,7 +1,7 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
-// $Id: txt_gui.c 487 2006-05-20 15:45:36Z fraggle $
+// $Id: txt_gui.c 547 2006-06-02 19:29:24Z fraggle $
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005 Simon Howard
@@ -140,7 +140,7 @@
// draw a box around the title.
by = y1 == y ? 0 :
- y1 == y + 2 ? 2 :
+ y1 == y + 2 && title != NULL ? 2 :
y1 == y + h - 1 ? 3 : 1;
for (x1=x; x1<x+w; ++x1)
@@ -158,18 +158,21 @@
// Draw the title
- TXT_GotoXY(x + 1, y + 1);
- TXT_BGColor(TXT_COLOR_GREY, 0);
- TXT_FGColor(TXT_COLOR_BLUE);
-
- for (x1=0; x1<w-2; ++x1)
+ if (title != NULL)
{
- TXT_DrawString(" ");
+ TXT_GotoXY(x + 1, y + 1);
+ TXT_BGColor(TXT_COLOR_GREY, 0);
+ TXT_FGColor(TXT_COLOR_BLUE);
+
+ for (x1=0; x1<w-2; ++x1)
+ {
+ TXT_DrawString(" ");
+ }
+
+ TXT_GotoXY(x + (w - strlen(title)) / 2, y + 1);
+ TXT_DrawString(title);
}
- TXT_GotoXY(x + (w - strlen(title)) / 2, y + 1);
- TXT_DrawString(title);
-
// Draw the window's shadow.
TXT_DrawShadow(x + 2, y + h, w, 1);
@@ -178,9 +181,12 @@
void TXT_DrawSeparator(int x, int y, int w)
{
+ unsigned char *data;
int x1;
- int c;
+ int b;
+ data = TXT_GetScreenData();
+
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
TXT_BGColor(TXT_COLOR_BLUE, 0);
@@ -189,18 +195,29 @@
return;
}
+ data += (y * TXT_SCREEN_W + x) * 2;
+
for (x1=x; x1<x+w; ++x1)
{
TXT_GotoXY(x1, y);
- c = x1 == x ? borders[2][0] :
- x1 == x + w - 1 ? borders[2][3] :
- borders[2][1];
+ b = x1 == x ? 0 :
+ x1 == x + w - 1 ? 3 :
+ 1;
if (VALID_X(x1))
{
- TXT_PutChar(c);
+ // Read the current value from the screen
+ // Check that it matches what the window should look like if
+ // there is no separator, then apply the separator
+
+ if (*data == borders[1][b])
+ {
+ TXT_PutChar(borders[2][b]);
+ }
}
+
+ data += 2;
}
}
--- a/textscreen/txt_inputbox.c
+++ b/textscreen/txt_inputbox.c
@@ -12,21 +12,24 @@
static void SetBufferFromValue(txt_inputbox_t *inputbox);
-static void TXT_InputBoxSizeCalc(TXT_UNCAST_ARG(inputbox), int *w, int *h)
+static void TXT_InputBoxSizeCalc(TXT_UNCAST_ARG(inputbox))
{
TXT_CAST_ARG(txt_inputbox_t, inputbox);
// Enough space for the box + cursor
- *w = inputbox->size + 1;
- *h = 1;
+ inputbox->widget.w = inputbox->size + 1;
+ inputbox->widget.h = 1;
}
-static void TXT_InputBoxDrawer(TXT_UNCAST_ARG(inputbox), int w, int selected)
+static void TXT_InputBoxDrawer(TXT_UNCAST_ARG(inputbox), int selected)
{
TXT_CAST_ARG(txt_inputbox_t, inputbox);
int i;
int chars;
+ int w;
+
+ w = inputbox->widget.w;
// Select the background colour based on whether we are currently
// editing, and if not, whether the widget is selected.
--- a/textscreen/txt_label.c
+++ b/textscreen/txt_label.c
@@ -7,20 +7,23 @@
#include "txt_main.h"
#include "txt_window.h"
-static void TXT_LabelSizeCalc(TXT_UNCAST_ARG(label), int *w, int *h)
+static void TXT_LabelSizeCalc(TXT_UNCAST_ARG(label))
{
TXT_CAST_ARG(txt_label_t, label);
- *w = label->w;
- *h = label->h;
+ label->widget.w = label->w;
+ label->widget.h = label->h;
}
-static void TXT_LabelDrawer(TXT_UNCAST_ARG(label), int w, int selected)
+static void TXT_LabelDrawer(TXT_UNCAST_ARG(label), int selected)
{
TXT_CAST_ARG(txt_label_t, label);
int x, y;
int origin_x, origin_y;
int align_indent;
+ int w;
+
+ w = label->widget.w;
TXT_BGColor(label->bgcolor, 0);
TXT_FGColor(label->fgcolor);
--- a/textscreen/txt_main.c
+++ b/textscreen/txt_main.c
@@ -1,7 +1,7 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
-// $Id: txt_main.c 533 2006-05-26 19:15:05Z fraggle $
+// $Id: txt_main.c 547 2006-06-02 19:29:24Z fraggle $
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005 Simon Howard
@@ -183,6 +183,14 @@
void TXT_UpdateScreen(void)
{
TXT_UpdateScreenArea(0, 0, TXT_SCREEN_W, TXT_SCREEN_H);
+}
+
+void TXT_GetMousePosition(int *x, int *y)
+{
+ SDL_GetMouseState(x, y);
+
+ *x /= CHAR_W;
+ *y /= CHAR_H;
}
//
--- a/textscreen/txt_main.h
+++ b/textscreen/txt_main.h
@@ -1,7 +1,7 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
-// $Id: txt_main.h 513 2006-05-23 00:04:27Z fraggle $
+// $Id: txt_main.h 547 2006-06-02 19:29:24Z fraggle $
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005 Simon Howard
@@ -100,6 +100,10 @@
// provided buffer.
void TXT_GetKeyDescription(int key, char *buf);
+
+// Retrieve the current position of the mouse
+
+void TXT_GetMouseState(int *x, int *y);
#endif /* #ifndef TXT_MAIN_H */
--- a/textscreen/txt_radiobutton.c
+++ b/textscreen/txt_radiobutton.c
@@ -9,20 +9,23 @@
#include "txt_main.h"
#include "txt_window.h"
-static void TXT_RadioButtonSizeCalc(TXT_UNCAST_ARG(radiobutton), int *w, int *h)
+static void TXT_RadioButtonSizeCalc(TXT_UNCAST_ARG(radiobutton))
{
TXT_CAST_ARG(txt_radiobutton_t, radiobutton);
// Minimum width is the string length + two spaces for padding
- *w = strlen(radiobutton->label) + 6;
- *h = 1;
+ radiobutton->widget.w = strlen(radiobutton->label) + 6;
+ radiobutton->widget.h = 1;
}
-static void TXT_RadioButtonDrawer(TXT_UNCAST_ARG(radiobutton), int w, int selected)
+static void TXT_RadioButtonDrawer(TXT_UNCAST_ARG(radiobutton), int selected)
{
TXT_CAST_ARG(txt_radiobutton_t, radiobutton);
int i;
+ int w;
+
+ w = radiobutton->widget.w;
TXT_BGColor(TXT_COLOR_BLUE, 0);
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
--- a/textscreen/txt_separator.c
+++ b/textscreen/txt_separator.c
@@ -7,7 +7,7 @@
#include "txt_main.h"
#include "txt_window.h"
-static void TXT_SeparatorSizeCalc(TXT_UNCAST_ARG(separator), int *w, int *h)
+static void TXT_SeparatorSizeCalc(TXT_UNCAST_ARG(separator))
{
TXT_CAST_ARG(txt_separator_t, separator);
@@ -15,21 +15,24 @@
{
// Minimum width is the string length + two spaces for padding
- *w = strlen(separator->label) + 2;
+ separator->widget.w = strlen(separator->label) + 2;
}
else
{
- *w = 0;
+ separator->widget.w = 0;
}
- *h = 1;
+ separator->widget.h = 1;
}
-static void TXT_SeparatorDrawer(TXT_UNCAST_ARG(separator), int w, int selected)
+static void TXT_SeparatorDrawer(TXT_UNCAST_ARG(separator), int selected)
{
TXT_CAST_ARG(txt_separator_t, separator);
int i;
int x, y;
+ int w;
+
+ w = separator->widget.w;
TXT_GetXY(&x, &y);
--- a/textscreen/txt_strut.c
+++ b/textscreen/txt_strut.c
@@ -9,17 +9,17 @@
#include "txt_main.h"
#include "txt_window.h"
-static void TXT_StrutSizeCalc(TXT_UNCAST_ARG(strut), int *w, int *h)
+static void TXT_StrutSizeCalc(TXT_UNCAST_ARG(strut))
{
TXT_CAST_ARG(txt_strut_t, strut);
// Minimum width is the string length + two spaces for padding
- *w = strut->width;
- *h = strut->height;
+ strut->widget.w = strut->width;
+ strut->widget.h = strut->height;
}
-static void TXT_StrutDrawer(TXT_UNCAST_ARG(strut), int w, int selected)
+static void TXT_StrutDrawer(TXT_UNCAST_ARG(strut), int selected)
{
// Nothing is drawn for a strut.
}
--- a/textscreen/txt_table.c
+++ b/textscreen/txt_table.c
@@ -65,7 +65,6 @@
int table_height;
int x, y;
int rows;
- int ww, wh;
txt_widget_t *widget;
rows = TableRows(table);
@@ -83,27 +82,21 @@
widget = table->widgets[y * table->columns + x];
+ // NULL represents an empty spacer
+
if (widget != NULL)
{
- TXT_CalcWidgetSize(widget, &ww, &wh);
+ TXT_CalcWidgetSize(widget);
+ if (widget->h > row_heights[y])
+ row_heights[y] = widget->h;
+ if (widget->w > col_widths[x])
+ col_widths[x] = widget->w;
}
- else
- {
- // Empty spacer if widget is NULL
-
- ww = 0;
- wh = 0;
- }
-
- if (wh > row_heights[y])
- row_heights[y] = wh;
- if (ww > col_widths[x])
- col_widths[x] = ww;
}
}
}
-static void TXT_CalcTableSize(TXT_UNCAST_ARG(table), int *w, int *h)
+static void TXT_CalcTableSize(TXT_UNCAST_ARG(table))
{
TXT_CAST_ARG(txt_table_t, table);
int *column_widths;
@@ -118,18 +111,18 @@
CalcRowColSizes(table, row_heights, column_widths);
- *w = 0;
+ table->widget.w = 0;
for (x=0; x<table->columns; ++x)
{
- *w += column_widths[x];
+ table->widget.w += column_widths[x];
}
- *h = 0;
+ table->widget.h = 0;
for (y=0; y<rows; ++y)
{
- *h += row_heights[y];
+ table->widget.h += row_heights[y];
}
free(row_heights);
@@ -354,68 +347,64 @@
}
}
-static void DrawCell(txt_table_t *table, int x, int y,
- int draw_x, int draw_y, int w, int selected)
+static void LayoutCell(txt_table_t *table, int x, int y, int col_width,
+ int draw_x, int draw_y)
{
txt_widget_t *widget;
- int cw, ch;
widget = table->widgets[y * table->columns + x];
+ // Adjust x position based on alignment property
+
switch (widget->align)
{
case TXT_HORIZ_LEFT:
+ widget->w = col_width;
break;
case TXT_HORIZ_CENTER:
- TXT_CalcWidgetSize(widget, &cw, &ch);
+ TXT_CalcWidgetSize(widget);
// Separators are always drawn left-aligned.
if (widget->widget_class != &txt_separator_class)
{
- draw_x += (w - cw) / 2;
- w = cw;
+ draw_x += (col_width - widget->w) / 2;
}
break;
case TXT_HORIZ_RIGHT:
- TXT_CalcWidgetSize(widget, &cw, &ch);
+ TXT_CalcWidgetSize(widget);
if (widget->widget_class != &txt_separator_class)
{
- draw_x += w - cw;
- w = cw;
+ draw_x += col_width - widget->w;
}
break;
}
- TXT_GotoXY(draw_x, draw_y);
+ // Set the position for this widget
- TXT_DrawWidget(widget, w, selected && x == table->selected_x
- && y == table->selected_y);
+ widget->x = draw_x;
+ widget->y = draw_y;
+
+ // Recursively lay out any widgets contained in the widget
+
+ TXT_LayoutWidget(widget);
}
-static void TXT_TableDrawer(TXT_UNCAST_ARG(table), int w, int selected)
+static void TXT_TableLayout(TXT_UNCAST_ARG(table))
{
TXT_CAST_ARG(txt_table_t, table);
int *column_widths;
int *row_heights;
- int origin_x, origin_y;
int draw_x, draw_y;
int x, y;
int i;
int rows;
- // Check the table's current selection points at something valid before
- // drawing.
-
- CheckValidSelection(table);
-
- TXT_GetXY(&origin_x, &origin_y);
-
// Work out the column widths and row heights
rows = TableRows(table);
@@ -431,16 +420,16 @@
if (table->columns == 1)
{
- column_widths[0] = w;
+ column_widths[0] = table->widget.w;
}
// Draw all cells
- draw_y = origin_y;
+ draw_y = table->widget.y;
for (y=0; y<rows; ++y)
{
- draw_x = origin_x;
+ draw_x = table->widget.x;
for (x=0; x<table->columns; ++x)
{
@@ -451,8 +440,8 @@
if (table->widgets[i] != NULL)
{
- DrawCell(table, x, y, draw_x, draw_y,
- column_widths[x], selected);
+ LayoutCell(table, x, y, column_widths[x],
+ draw_x, draw_y);
}
draw_x += column_widths[x];
@@ -464,7 +453,76 @@
free(row_heights);
free(column_widths);
}
-
+
+static void TXT_TableDrawer(TXT_UNCAST_ARG(table), int selected)
+{
+ TXT_CAST_ARG(txt_table_t, table);
+ txt_widget_t *widget;
+ int selected_cell;
+ int i;
+
+ // Check the table's current selection points at something valid before
+ // drawing.
+
+ CheckValidSelection(table);
+
+ // Find the index of the currently-selected widget.
+
+ selected_cell = table->selected_y * table->columns + table->selected_x;
+
+ // Draw all cells
+
+ for (i=0; i<table->num_widgets; ++i)
+ {
+ widget = table->widgets[i];
+
+ if (widget != NULL)
+ {
+ TXT_GotoXY(widget->x, widget->y);
+ TXT_DrawWidget(widget, selected && i == selected_cell);
+ }
+ }
+}
+
+// Responds to mouse presses
+
+static void TXT_TableMousePress(TXT_UNCAST_ARG(table), int x, int y, int b)
+{
+ TXT_CAST_ARG(txt_table_t, table);
+ txt_widget_t *widget;
+ int i;
+
+ for (i=0; i<table->num_widgets; ++i)
+ {
+ widget = table->widgets[i];
+
+ // NULL widgets are spacers
+
+ if (widget != NULL)
+ {
+ if (x >= widget->x && x < widget->x + widget->w
+ && y >= widget->y && y < widget->y + widget->h)
+ {
+ // This is the widget that was clicked!
+
+ // Select the cell if the widget is selectable
+
+ if (widget->selectable)
+ {
+ table->selected_x = i % table->columns;
+ table->selected_y = i / table->columns;
+ }
+
+ // Propagate click
+
+ TXT_WidgetMousePress(widget, x, y, b);
+
+ break;
+ }
+ }
+ }
+}
+
txt_widget_class_t txt_table_class =
{
TXT_CalcTableSize,
@@ -471,6 +529,8 @@
TXT_TableDrawer,
TXT_TableKeyPress,
TXT_TableDestructor,
+ TXT_TableMousePress,
+ TXT_TableLayout,
};
void TXT_InitTable(txt_table_t *table, int columns)
--- a/textscreen/txt_widget.c
+++ b/textscreen/txt_widget.c
@@ -112,18 +112,24 @@
}
}
-void TXT_CalcWidgetSize(TXT_UNCAST_ARG(widget), int *w, int *h)
+void TXT_CalcWidgetSize(TXT_UNCAST_ARG(widget))
{
TXT_CAST_ARG(txt_widget_t, widget);
- return widget->widget_class->size_calc(widget, w, h);
+ widget->widget_class->size_calc(widget);
}
-void TXT_DrawWidget(TXT_UNCAST_ARG(widget), int w, int selected)
+void TXT_DrawWidget(TXT_UNCAST_ARG(widget), int selected)
{
TXT_CAST_ARG(txt_widget_t, widget);
- widget->widget_class->drawer(widget, w, selected);
+ // For convenience...
+
+ TXT_GotoXY(widget->x, widget->y);
+
+ // Call drawer method
+
+ widget->widget_class->drawer(widget, selected);
}
void TXT_DestroyWidget(TXT_UNCAST_ARG(widget))
@@ -154,4 +160,23 @@
widget->align = horiz_align;
}
+void TXT_WidgetMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b)
+{
+ TXT_CAST_ARG(txt_widget_t, widget);
+
+ if (widget->widget_class->mouse_press != NULL)
+ {
+ widget->widget_class->mouse_press(widget, x, y, b);
+ }
+}
+
+void TXT_LayoutWidget(TXT_UNCAST_ARG(widget))
+{
+ TXT_CAST_ARG(txt_widget_t, widget);
+
+ if (widget->widget_class->layout != NULL)
+ {
+ widget->widget_class->layout(widget);
+ }
+}
--- a/textscreen/txt_widget.h
+++ b/textscreen/txt_widget.h
@@ -48,11 +48,13 @@
typedef struct txt_widget_s txt_widget_t;
typedef struct txt_callback_table_s txt_callback_table_t;
-typedef void (*TxtWidgetSizeCalc)(TXT_UNCAST_ARG(widget), int *w, int *h);
-typedef void (*TxtWidgetDrawer)(TXT_UNCAST_ARG(widget), int w, int selected);
+typedef void (*TxtWidgetSizeCalc)(TXT_UNCAST_ARG(widget));
+typedef void (*TxtWidgetDrawer)(TXT_UNCAST_ARG(widget), int selected);
typedef void (*TxtWidgetDestroy)(TXT_UNCAST_ARG(widget));
typedef int (*TxtWidgetKeyPress)(TXT_UNCAST_ARG(widget), int key);
typedef void (*TxtWidgetSignalFunc)(TXT_UNCAST_ARG(widget), void *user_data);
+typedef void (*TxtMousePressFunc)(TXT_UNCAST_ARG(widget), int x, int y, int b);
+typedef void (*TxtWidgetLayoutFunc)(TXT_UNCAST_ARG(widget));
struct txt_widget_class_s
{
@@ -60,6 +62,8 @@
TxtWidgetDrawer drawer;
TxtWidgetKeyPress key_press;
TxtWidgetDestroy destructor;
+ TxtMousePressFunc mouse_press;
+ TxtWidgetLayoutFunc layout;
};
struct txt_widget_s
@@ -69,17 +73,25 @@
int selectable;
int visible;
txt_horiz_align_t align;
+
+ // These are set automatically when the window is drawn and should
+ // not be set manually.
+
+ int x, y;
+ int w, h;
};
void TXT_InitWidget(TXT_UNCAST_ARG(widget), txt_widget_class_t *widget_class);
-void TXT_CalcWidgetSize(TXT_UNCAST_ARG(widget), int *w, int *h);
-void TXT_DrawWidget(TXT_UNCAST_ARG(widget), int w, int selected);
+void TXT_CalcWidgetSize(TXT_UNCAST_ARG(widget));
+void TXT_DrawWidget(TXT_UNCAST_ARG(widget), int selected);
void TXT_SignalConnect(TXT_UNCAST_ARG(widget), char *signal_name,
TxtWidgetSignalFunc func, void *user_data);
void TXT_EmitSignal(TXT_UNCAST_ARG(widget), char *signal_name);
int TXT_WidgetKeyPress(TXT_UNCAST_ARG(widget), int key);
+void TXT_WidgetMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b);
void TXT_DestroyWidget(TXT_UNCAST_ARG(widget));
void TXT_SetWidgetAlign(TXT_UNCAST_ARG(widget), txt_horiz_align_t horiz_align);
+void TXT_LayoutWidget(TXT_UNCAST_ARG(widget));
#endif /* #ifndef TXT_WIDGET_H */
--- a/textscreen/txt_window.c
+++ b/textscreen/txt_window.c
@@ -1,11 +1,3 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// $Id$
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2006 Simon Howard
-//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
@@ -64,7 +56,15 @@
TXT_InitTable(&win->table, 1);
- win->title = strdup(title);
+ if (title == NULL)
+ {
+ win->title = NULL;
+ }
+ else
+ {
+ win->title = strdup(title);
+ }
+
win->x = TXT_SCREEN_W / 2;
win->y = TXT_SCREEN_H / 2;
win->horiz_align = TXT_HORIZ_CENTER;
@@ -111,20 +111,18 @@
TXT_RemoveDesktopWindow(window);
}
-static void CalcWindowPosition(txt_window_t *window,
- int *x, int *y,
- int w, int h)
+static void CalcWindowPosition(txt_window_t *window)
{
switch (window->horiz_align)
{
case TXT_HORIZ_LEFT:
- *x = window->x;
+ window->window_x = window->x;
break;
case TXT_HORIZ_CENTER:
- *x = window->x - (w / 2);
+ window->window_x = window->x - (window->window_w / 2);
break;
case TXT_HORIZ_RIGHT:
- *x = window->x - (w - 1);
+ window->window_x = window->x - (window->window_w - 1);
break;
}
@@ -131,29 +129,31 @@
switch (window->vert_align)
{
case TXT_VERT_TOP:
- *y = window->y;
+ window->window_y = window->y;
break;
case TXT_VERT_CENTER:
- *y = window->y - (h / 2);
+ window->window_y = window->y - (window->window_h / 2);
break;
case TXT_VERT_BOTTOM:
- *y = window->y - (h - 1);
+ window->window_y = window->y - (window->window_h - 1);
break;
}
}
-static void DrawActionArea(txt_window_t *window,
- int window_x, int window_y,
- int window_w, int window_h)
+static void LayoutActionArea(txt_window_t *window)
{
- int ww, wh;
+ txt_widget_t *widget;
- // Draw the left action
+ // Left action
if (window->actions[TXT_HORIZ_LEFT] != NULL)
{
- TXT_GotoXY(window_x + 2, window_y + window_h - 2);
- TXT_DrawWidget(window->actions[TXT_HORIZ_LEFT], 0, 0);
+ widget = (txt_widget_t *) window->actions[TXT_HORIZ_LEFT];
+
+ TXT_CalcWidgetSize(widget);
+
+ widget->x = window->window_x + 2;
+ widget->y = window->window_y + window->window_h - 2;
}
// Draw the center action
@@ -160,9 +160,12 @@
if (window->actions[TXT_HORIZ_CENTER] != NULL)
{
- TXT_CalcWidgetSize(window->actions[TXT_HORIZ_CENTER], &ww, &wh);
- TXT_GotoXY(window_x + (window_w - ww - 2) / 2, window_y + window_h - 2);
- TXT_DrawWidget(window->actions[TXT_HORIZ_CENTER], 0, 0);
+ widget = (txt_widget_t *) window->actions[TXT_HORIZ_CENTER];
+
+ TXT_CalcWidgetSize(widget);
+
+ widget->x = window->window_x + (window->window_w - widget->w - 2) / 2;
+ widget->y = window->window_y + window->window_h - 2;
}
// Draw the right action
@@ -169,15 +172,31 @@
if (window->actions[TXT_HORIZ_RIGHT] != NULL)
{
- TXT_CalcWidgetSize(window->actions[TXT_HORIZ_RIGHT], &ww, &wh);
- TXT_GotoXY(window_x + window_w - 2 - ww, window_y + window_h - 2);
- TXT_DrawWidget(window->actions[TXT_HORIZ_RIGHT], 0, 0);
+ widget = (txt_widget_t *) window->actions[TXT_HORIZ_RIGHT];
+
+ TXT_CalcWidgetSize(widget);
+
+ widget->x = window->window_x + window->window_w - 2 - widget->w;
+ widget->y = window->window_y + window->window_h - 2;
}
}
-static int CalcActionAreaWidth(txt_window_t *window, int *widgets_w)
+static void DrawActionArea(txt_window_t *window)
{
- int ww, wh;
+ int i;
+
+ for (i=0; i<3; ++i)
+ {
+ if (window->actions[i] != NULL)
+ {
+ TXT_DrawWidget(window->actions[i], 0);
+ }
+ }
+}
+
+static int ActionAreaWidth(txt_window_t *window)
+{
+ txt_widget_t *widget;
int w;
int i;
@@ -188,57 +207,99 @@
for (i=0; i<3; ++i)
{
- if (window->actions[i] != NULL)
+ widget = (txt_widget_t *) window->actions[i];
+
+ if (widget != NULL)
{
- TXT_CalcWidgetSize(window->actions[i], &ww, &wh);
- w += ww + 1;
+ TXT_CalcWidgetSize(widget);
+ w += widget->w + 1;
}
}
- // If this is larger than the window size, adjust the window to fit.
-
- if (w > *widgets_w)
- *widgets_w = w;
+ return w;
}
-void TXT_DrawWindow(txt_window_t *window)
+// Sets size and position of all widgets in a window
+
+void TXT_LayoutWindow(txt_window_t *window)
{
- int widgets_w, widgets_h;
- int window_w, window_h;
- int x, y;
- int window_x, window_y;
- int i;
- int ww, wh;
+ txt_widget_t *widgets = (txt_widget_t *) window;
+ int widgets_w;
+ int actionarea_w;
+
+ // Calculate size of table
- TXT_CalcWidgetSize(window, &widgets_w, &widgets_h);
- CalcActionAreaWidth(window, &widgets_w);
+ TXT_CalcWidgetSize(window);
- // Actual window size after padding
+ // Calculate the size of the action area
+
+ actionarea_w = ActionAreaWidth(window);
+
+ // Which one is larger?
- window_w = widgets_w + 2;
- window_h = widgets_h + 5;
+ widgets_w = widgets->w;
+ if (actionarea_w > widgets_w)
+ widgets_w = actionarea_w;
+
+ // Set the window size based on widgets_w
+
+ window->window_w = widgets_w + 2;
+ window->window_h = widgets->h + 3;
+
+ // If the window has a title, add an extra two lines
+
+ if (window->title != NULL)
+ {
+ window->window_h += 2;
+ }
+
// Use the x,y position as the centerpoint and find the location to
// draw the window.
- CalcWindowPosition(window, &window_x, &window_y, window_w, window_h);
+ CalcWindowPosition(window);
+ // Set the table size and position
+
+ widgets->w = widgets_w;
+ // widgets->h (already set)
+ widgets->x = window->window_x + 1;
+ widgets->y = window->window_y + window->window_h - widgets->h - 3;
+
+ // Layout the table and action area
+
+ LayoutActionArea(window);
+ TXT_LayoutWidget(widgets);
+}
+
+void TXT_DrawWindow(txt_window_t *window)
+{
+ txt_widget_t *widgets;
+ int x, y;
+ int i;
+ int ww, wh;
+
+ TXT_LayoutWindow(window);
+
// Draw the window
- TXT_DrawWindowFrame(window->title, window_x, window_y, window_w, window_h);
+ TXT_DrawWindowFrame(window->title,
+ window->window_x, window->window_y,
+ window->window_w, window->window_h);
// Draw all widgets
- TXT_GotoXY(window_x + 1, window_y + 2);
- TXT_DrawWidget(window, widgets_w, 1);
+ TXT_DrawWidget(window, 1);
// Separator for action area
- TXT_DrawSeparator(window_x, window_y + 2 + widgets_h, window_w);
+ widgets = (txt_widget_t *) window;
+ TXT_DrawSeparator(window->window_x, widgets->y + widgets->h, widgets->w);
+
// Action area at the window bottom
- DrawActionArea(window, window_x, window_y, window_w, window_h);
+ DrawActionArea(window);
}
void TXT_SetWindowPosition(txt_window_t *window,
@@ -252,9 +313,41 @@
window->y = y;
}
+static void MouseButtonPress(txt_window_t *window, int b)
+{
+ int x, y;
+ txt_widget_t *widgets;
+
+ // Lay out the window, set positions and sizes of all widgets
+
+ TXT_LayoutWindow(window);
+
+ // Get the current mouse position
+
+ TXT_GetMousePosition(&x, &y);
+
+ // Is it within the table range?
+
+ widgets = (txt_widget_t *) window;
+
+ if (x >= widgets->x && x < widgets->x + widgets->w
+ && y >= widgets->y && y < widgets->y + widgets->h)
+ {
+ TXT_WidgetMousePress(window, x, y, b);
+ }
+}
+
void TXT_WindowKeyPress(txt_window_t *window, int c)
{
int i;
+
+ // Is this a mouse button ?
+
+ if (c == TXT_MOUSE_LEFT)
+ {
+ MouseButtonPress(window, c);
+ return;
+ }
// Send to the currently selected widget first
--- a/textscreen/txt_window.h
+++ b/textscreen/txt_window.h
@@ -50,6 +50,11 @@
// Actions that appear in the box at the bottom of the window
txt_window_action_t *actions[3];
+
+ // These are set automatically when the window is drawn
+
+ int window_x, window_y;
+ int window_w, window_h;
};
txt_window_t *TXT_NewWindow(char *title);
--- a/textscreen/txt_window_action.c
+++ b/textscreen/txt_window_action.c
@@ -9,8 +9,7 @@
#include "txt_main.h"
#include "txt_window.h"
-static void TXT_WindowActionSizeCalc(TXT_UNCAST_ARG(action),
- int *w, int *h)
+static void TXT_WindowActionSizeCalc(TXT_UNCAST_ARG(action))
{
TXT_CAST_ARG(txt_window_action_t, action);
char buf[10];
@@ -19,11 +18,11 @@
// Minimum width is the string length + two spaces for padding
- *w = strlen(action->label) + strlen(buf) + 1;
- *h = 1;
+ action->widget.w = strlen(action->label) + strlen(buf) + 1;
+ action->widget.h = 1;
}
-static void TXT_WindowActionDrawer(TXT_UNCAST_ARG(action), int w, int selected)
+static void TXT_WindowActionDrawer(TXT_UNCAST_ARG(action), int selected)
{
TXT_CAST_ARG(txt_window_action_t, action);
int i;