From 2fd49a65afdcadbc09680552142c6f107715ebbc Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Thu, 31 Aug 2006 18:12:05 +0000 Subject: Add dropdown listbox widget Subversion-branch: /trunk/chocolate-doom Subversion-revision: 578 --- textscreen/txt_dropdown.c | 263 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 textscreen/txt_dropdown.c (limited to 'textscreen/txt_dropdown.c') diff --git a/textscreen/txt_dropdown.c b/textscreen/txt_dropdown.c new file mode 100644 index 00000000..84fd3aca --- /dev/null +++ b/textscreen/txt_dropdown.c @@ -0,0 +1,263 @@ + +#include +#include + +#include "doomkeys.h" + +#include "txt_button.h" +#include "txt_dropdown.h" +#include "txt_io.h" +#include "txt_main.h" +#include "txt_window.h" + +typedef struct +{ + txt_window_t *window; + txt_dropdown_list_t *list; + int item; +} callback_data_t; + +// Check if the selected value for a list is valid + +static int ValidSelection(txt_dropdown_list_t *list) +{ + return *list->variable >= 0 && *list->variable < list->num_values; +} + +// Calculate the Y position for the selector window + +static int SelectorWindowY(txt_dropdown_list_t *list) +{ + if (ValidSelection(list)) + { + return list->widget.y - 1 - *list->variable; + } + else + { + return list->widget.y - 1 - (list->num_values / 2); + } +} + +// Called when a button in the selector window is pressed + +static void ItemSelected(TXT_UNCAST_ARG(button), TXT_UNCAST_ARG(callback_data)) +{ + TXT_CAST_ARG(callback_data_t, callback_data); + + // Set the variable + + *callback_data->list->variable = callback_data->item; + + // Close the window + + TXT_CloseWindow(callback_data->window); +} + +// Free callback data when the window is closed + +static void FreeCallbackData(TXT_UNCAST_ARG(list), + TXT_UNCAST_ARG(callback_data)) +{ + TXT_CAST_ARG(callback_data_t, callback_data); + + free(callback_data); +} + +// Catch presses of escape and close the window. + +static int SelectorWindowListener(txt_window_t *window, int key, void *user_data) +{ + if (key == KEY_ESCAPE) + { + TXT_CloseWindow(window); + return 1; + } + + return 0; +} + +// Open the dropdown list window to select an item + +static void OpenSelectorWindow(txt_dropdown_list_t *list) +{ + txt_window_t *window; + int i; + + // Open a simple window with no title bar or action buttons. + + window = TXT_NewWindow(NULL); + + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); + + // Position the window so that the currently selected item appears + // over the top of the list widget. + + TXT_SetWindowPosition(window, TXT_HORIZ_LEFT, TXT_VERT_TOP, + list->widget.x - 2, SelectorWindowY(list)); + + // Add a button to the window for each option in the list. + + for (i=0; inum_values; ++i) + { + txt_button_t *button; + callback_data_t *data; + + button = TXT_NewButton(list->values[i]); + + TXT_AddWidget(window, button); + + // Callback struct + + data = malloc(sizeof(callback_data_t)); + data->list = list; + data->window = window; + data->item = i; + + // When the button is pressed, invoke the button press callback + + TXT_SignalConnect(button, "pressed", ItemSelected, data); + + // When the window is closed, free back the callback struct + + TXT_SignalConnect(window, "closed", FreeCallbackData, data); + + // Is this the currently-selected value? If so, select the button + // in the window as the default. + + if (i == *list->variable) + { + TXT_SelectWidget(window, button); + } + } + + // Catch presses of escape in this window and close it. + + TXT_SetKeyListener(window, SelectorWindowListener, NULL); +} + +static int DropdownListWidth(txt_dropdown_list_t *list) +{ + int i; + int result; + + // Find the maximum string width + + result = 0; + + for (i=0; inum_values; ++i) + { + int w = strlen(list->values[i]); + if (w > result) + { + result = w; + } + } + + return result; +} + +static void TXT_DropdownListSizeCalc(TXT_UNCAST_ARG(list)) +{ + TXT_CAST_ARG(txt_dropdown_list_t, list); + + list->widget.w = DropdownListWidth(list); + list->widget.h = 1; +} + +static void TXT_DropdownListDrawer(TXT_UNCAST_ARG(list), int selected) +{ + TXT_CAST_ARG(txt_dropdown_list_t, list); + int i; + char *str; + + // Set bg/fg text colors. + + if (selected) + { + TXT_BGColor(TXT_COLOR_GREY, 0); + } + else + { + TXT_BGColor(TXT_COLOR_BLUE, 0); + } + + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); + + // Select a string to draw from the list, if the current value is + // in range. Otherwise fall back to a default. + + if (ValidSelection(list)) + { + str = list->values[*list->variable]; + } + else + { + str = "???"; + } + + // Draw the string and fill to the end with spaces + + TXT_DrawString(str); + + for (i=strlen(str); iwidget.w; ++i) + { + TXT_DrawString(" "); + } +} + +static void TXT_DropdownListDestructor(TXT_UNCAST_ARG(list)) +{ +} + +static int TXT_DropdownListKeyPress(TXT_UNCAST_ARG(list), int key) +{ + TXT_CAST_ARG(txt_dropdown_list_t, list); + + if (key == KEY_ENTER) + { + OpenSelectorWindow(list); + return 1; + } + + return 0; +} + +static void TXT_DropdownListMousePress(TXT_UNCAST_ARG(list), + int x, int y, int b) +{ + TXT_CAST_ARG(txt_dropdown_list_t, list); + + // Left mouse click does the same as selecting and pressing enter + + if (b == TXT_MOUSE_LEFT) + { + TXT_DropdownListKeyPress(list, KEY_ENTER); + } +} + +txt_widget_class_t txt_dropdown_list_class = +{ + TXT_DropdownListSizeCalc, + TXT_DropdownListDrawer, + TXT_DropdownListKeyPress, + TXT_DropdownListDestructor, + TXT_DropdownListMousePress, +}; + +txt_dropdown_list_t *TXT_NewDropdownList(int *variable, char **values, + int num_values) +{ + txt_dropdown_list_t *list; + + list = malloc(sizeof(txt_dropdown_list_t)); + + TXT_InitWidget(list, &txt_dropdown_list_class); + list->variable = variable; + list->values = values; + list->num_values = num_values; + + return list; +} + -- cgit v1.2.3