shithub: choc

Download patch

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 */
+