ref: 1de18c1397bfb069771c02336e47b89e098b6f43
parent: 7666630775f51fe991005ff8219cb4cc0cb70327
author: Simon Howard <fraggle@gmail.com>
date: Mon May 22 20:07:02 EDT 2006
Add window action class for action area labels at the bottom of windows. Adjust txt_table_t to expand tables to their maximum width when they only have one column (ensures separators reach the window edges). Subversion-branch: /trunk/chocolate-doom Subversion-revision: 515
--- a/textscreen/Makefile.am
+++ b/textscreen/Makefile.am
@@ -17,6 +17,7 @@
txt_table.c txt_table.h \
txt_widget.c txt_widget.h \
txt_window.c txt_window.h \
+ txt_window_action.c txt_window_action.h \
txt_font.h
guitest_LDADD = @SDL_LIBS@ libtextscreen.a
--- a/textscreen/txt_table.c
+++ b/textscreen/txt_table.c
@@ -365,6 +365,15 @@
CalcRowColSizes(table, row_heights, column_widths);
+ // If this table only has one column, expand column size to fit
+ // the display width. Ensures that separators reach the window edges
+ // when drawing windows.
+
+ if (table->columns == 1)
+ {
+ column_widths[0] = w;
+ }
+
// Draw all cells
draw_y = origin_y;
--- a/textscreen/txt_window.c
+++ b/textscreen/txt_window.c
@@ -33,8 +33,24 @@
#include "txt_separator.h"
#include "txt_window.h"
+void TXT_SetWindowAction(txt_window_t *window,
+ txt_horiz_align_t position,
+ txt_window_action_t *action)
+{
+ if (window->actions[position] != NULL)
+ {
+ TXT_DestroyWidget(window->actions[position]);
+ }
+
+ window->actions[position] = action;
+}
+
txt_window_t *TXT_NewWindow(char *title)
{
+ int i;
+ txt_window_action_t *cancel_action;
+ txt_window_action_t *accept_action;
+
txt_window_t *win;
win = malloc(sizeof(txt_window_t));
@@ -48,18 +64,41 @@
win->vert_align = TXT_VERT_CENTER;
TXT_AddWidget(win, TXT_NewSeparator(NULL));
+
+ for (i=0; i<3; ++i)
+ win->actions[i] = NULL;
+
TXT_AddDesktopWindow(win);
+ // Default actions
+
+ cancel_action = TXT_NewWindowAction(KEY_ESCAPE, "Abort");
+ TXT_SetWindowAction(win, TXT_HORIZ_LEFT, cancel_action);
+ accept_action = TXT_NewWindowAction(KEY_ENTER, "Accept");
+ TXT_SetWindowAction(win, TXT_HORIZ_RIGHT, accept_action);
+
return win;
}
void TXT_CloseWindow(txt_window_t *window)
{
+ int i;
+
free(window->title);
+ // Destroy all actions
+
+ for (i=0; i<3; ++i)
+ {
+ if (window->actions[i] != NULL)
+ {
+ TXT_DestroyWidget(window->actions[i]);
+ }
+ }
+
// Destroy table and window
- TXT_DestroyWidget((txt_widget_t *) window);
+ TXT_DestroyWidget(window);
TXT_RemoveDesktopWindow(window);
}
@@ -95,6 +134,65 @@
}
}
+static void DrawActionArea(txt_window_t *window,
+ int window_x, int window_y,
+ int window_w, int window_h)
+{
+ int ww, wh;
+
+ // Draw the 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);
+ }
+
+ // Draw the center action
+
+ 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);
+ }
+
+ // Draw the right action
+
+ 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);
+ }
+}
+
+static int CalcActionAreaWidth(txt_window_t *window, int *widgets_w)
+{
+ int ww, wh;
+ int w;
+ int i;
+
+ w = 1;
+
+ // Calculate the width of all the action widgets and use this
+ // to create an overall min. width of the action area
+
+ for (i=0; i<3; ++i)
+ {
+ if (window->actions[i] != NULL)
+ {
+ TXT_CalcWidgetSize(window->actions[i], &ww, &wh);
+ w += ww + 1;
+ }
+ }
+
+ // If this is larger than the window size, adjust the window to fit.
+
+ if (w > *widgets_w)
+ *widgets_w = w;
+}
+
void TXT_DrawWindow(txt_window_t *window)
{
int widgets_w, widgets_h;
@@ -104,7 +202,8 @@
int i;
int ww, wh;
- TXT_CalcWidgetSize((txt_widget_t *) window, &widgets_w, &widgets_h);
+ TXT_CalcWidgetSize(window, &widgets_w, &widgets_h);
+ CalcActionAreaWidth(window, &widgets_w);
// Actual window size after padding
@@ -123,11 +222,15 @@
// Draw all widgets
TXT_GotoXY(window_x + 1, window_y + 2);
- TXT_DrawWidget((txt_widget_t *) window, widgets_w, 1);
+ TXT_DrawWidget(window, widgets_w, 1);
// Separator for action area
TXT_DrawSeparator(window_x, window_y + 2 + widgets_h, window_w);
+
+ // Action area at the window bottom
+
+ DrawActionArea(window, window_x, window_y, window_w, window_h);
}
void TXT_SetWindowPosition(txt_window_t *window,
@@ -143,8 +246,24 @@
void TXT_WindowKeyPress(txt_window_t *window, int c)
{
+ int i;
+
// Send to the currently selected widget first
- TXT_WidgetKeyPress((txt_widget_t *) window, c);
+ if (TXT_WidgetKeyPress(window, c))
+ {
+ return;
+ }
+
+ // Try all of the action buttons
+
+ for (i=0; i<3; ++i)
+ {
+ if (window->actions[i] != NULL
+ && TXT_WidgetKeyPress(window->actions[i], c))
+ {
+ return;
+ }
+ }
}
--- a/textscreen/txt_window.h
+++ b/textscreen/txt_window.h
@@ -43,6 +43,7 @@
#include "txt_widget.h"
#include "txt_table.h"
+#include "txt_window_action.h"
struct txt_window_s
{
@@ -59,6 +60,10 @@
txt_vert_align_t vert_align;
txt_horiz_align_t horiz_align;
int x, y;
+
+ // Actions that appear in the box at the bottom of the window
+
+ txt_window_action_t *actions[3];
};
txt_window_t *TXT_NewWindow(char *title);
@@ -67,6 +72,8 @@
txt_horiz_align_t horiz_align,
txt_vert_align_t vert_align,
int x, int y);
+void TXT_SetWindowAction(txt_window_t *window, txt_horiz_align_t position,
+ txt_window_action_t *action);
#endif /* #ifndef TXT_WINDOW_T */
--- /dev/null
+++ b/textscreen/txt_window_action.c
@@ -1,0 +1,81 @@
+
+#include <string.h>
+
+#include "doomkeys.h"
+
+#include "txt_window_action.h"
+#include "txt_io.h"
+#include "txt_main.h"
+#include "txt_window.h"
+
+static void TXT_WindowActionSizeCalc(TXT_UNCAST_ARG(action),
+ int *w, int *h)
+{
+ TXT_CAST_ARG(txt_window_action_t, action);
+ char buf[10];
+
+ TXT_GetKeyDescription(action->key, buf);
+
+ // Minimum width is the string length + two spaces for padding
+
+ *w = strlen(action->label) + strlen(buf) + 1;
+ *h = 1;
+}
+
+static void TXT_WindowActionDrawer(TXT_UNCAST_ARG(action), int w, int selected)
+{
+ TXT_CAST_ARG(txt_window_action_t, action);
+ int i;
+ char buf[10];
+
+ TXT_GetKeyDescription(action->key, buf);
+
+ TXT_FGColor(TXT_COLOR_BRIGHT_GREEN);
+ TXT_DrawString(buf);
+ TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
+ TXT_DrawString("=");
+ TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
+ TXT_DrawString(action->label);
+}
+
+static void TXT_WindowActionDestructor(TXT_UNCAST_ARG(action))
+{
+ TXT_CAST_ARG(txt_window_action_t, action);
+
+ free(action->label);
+}
+
+static int TXT_WindowActionKeyPress(TXT_UNCAST_ARG(action), int key)
+{
+ TXT_CAST_ARG(txt_window_action_t, action);
+
+ if (key == action->key)
+ {
+ TXT_EmitSignal(action, "pressed");
+ return 1;
+ }
+
+ return 0;
+}
+
+txt_widget_class_t txt_window_action_class =
+{
+ TXT_WindowActionSizeCalc,
+ TXT_WindowActionDrawer,
+ TXT_WindowActionKeyPress,
+ TXT_WindowActionDestructor,
+};
+
+txt_window_action_t *TXT_NewWindowAction(int key, char *label)
+{
+ txt_window_action_t *action;
+
+ action = malloc(sizeof(txt_window_action_t));
+
+ TXT_InitWidget(action, &txt_window_action_class);
+ action->key = key;
+ action->label = strdup(label);
+
+ return action;
+}
+
--- /dev/null
+++ b/textscreen/txt_window_action.h
@@ -1,0 +1,42 @@
+// 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
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+
+#ifndef TXT_WINDOW_ACTION_H
+#define TXT_WINDOW_ACTION_H
+
+typedef struct txt_window_action_s txt_window_action_t;
+
+#include "txt_widget.h"
+
+struct txt_window_action_s
+{
+ txt_widget_t widget;
+ char *label;
+ int key;
+};
+
+txt_window_action_t *TXT_NewWindowAction(int key, char *label);
+
+#endif /* #ifndef TXT_WINDOW_ACTION_H */
+