diff options
author | Simon Howard | 2011-10-23 20:07:40 +0000 |
---|---|---|
committer | Simon Howard | 2011-10-23 20:07:40 +0000 |
commit | 379d372c65dee97d13b9a490c7c7a1a466478b7f (patch) | |
tree | 5df907dfd14c72fdfc05fc6e4cb2d4b3081db711 | |
parent | 1ec21c92ed4c3f792e642524c5cd5bc30b6d7457 (diff) | |
parent | cc87c97e4bae07238e9e1af8668944fd7805c133 (diff) | |
download | chocolate-doom-379d372c65dee97d13b9a490c7c7a1a466478b7f.tar.gz chocolate-doom-379d372c65dee97d13b9a490c7c7a1a466478b7f.tar.bz2 chocolate-doom-379d372c65dee97d13b9a490c7c7a1a466478b7f.zip |
Merge from trunk.
Subversion-branch: /branches/v2-branch
Subversion-revision: 2464
-rw-r--r-- | NEWS | 7 | ||||
-rw-r--r-- | src/setup/txt_joybinput.c | 4 | ||||
-rw-r--r-- | src/setup/txt_keyinput.c | 4 | ||||
-rw-r--r-- | src/setup/txt_mouseinput.c | 4 | ||||
-rw-r--r-- | textscreen/txt_button.c | 4 | ||||
-rw-r--r-- | textscreen/txt_checkbox.c | 4 | ||||
-rw-r--r-- | textscreen/txt_desktop.c | 26 | ||||
-rw-r--r-- | textscreen/txt_desktop.h | 3 | ||||
-rw-r--r-- | textscreen/txt_dropdown.c | 4 | ||||
-rw-r--r-- | textscreen/txt_inputbox.c | 176 | ||||
-rw-r--r-- | textscreen/txt_label.c | 2 | ||||
-rw-r--r-- | textscreen/txt_radiobutton.c | 4 | ||||
-rw-r--r-- | textscreen/txt_scrollpane.c | 18 | ||||
-rw-r--r-- | textscreen/txt_sdl.c | 48 | ||||
-rw-r--r-- | textscreen/txt_separator.c | 2 | ||||
-rw-r--r-- | textscreen/txt_spinctrl.c | 48 | ||||
-rw-r--r-- | textscreen/txt_strut.c | 2 | ||||
-rw-r--r-- | textscreen/txt_table.c | 113 | ||||
-rw-r--r-- | textscreen/txt_widget.c | 32 | ||||
-rw-r--r-- | textscreen/txt_widget.h | 10 | ||||
-rw-r--r-- | textscreen/txt_window.c | 28 | ||||
-rw-r--r-- | textscreen/txt_window_action.c | 2 |
22 files changed, 358 insertions, 187 deletions
@@ -8,6 +8,13 @@ * Fix teleport behavior when emulating the alternate Final Doom executable (-gameversion final2) (thanks xttl). + libtextscreen: + * Input boxes stop editing and save when they lose their focus, + correcting a previous counterintuitive behavior (thanks + Twelve). + * The numeric keypad now works properly when entering text values + (thanks Twelve). + 1.6.0 (2011-05-17): * The instructions in the INSTALL file are now customized for diff --git a/src/setup/txt_joybinput.c b/src/setup/txt_joybinput.c index 97aaca94..3e033df9 100644 --- a/src/setup/txt_joybinput.c +++ b/src/setup/txt_joybinput.c @@ -129,7 +129,7 @@ static void GetJoystickButtonDescription(int button, char *buf) sprintf(buf, "BUTTON #%i", button + 1); } -static void TXT_JoystickInputDrawer(TXT_UNCAST_ARG(joystick_input), int selected) +static void TXT_JoystickInputDrawer(TXT_UNCAST_ARG(joystick_input)) { TXT_CAST_ARG(txt_joystick_input_t, joystick_input); char buf[20]; @@ -144,7 +144,7 @@ static void TXT_JoystickInputDrawer(TXT_UNCAST_ARG(joystick_input), int selected GetJoystickButtonDescription(*joystick_input->variable, buf); } - TXT_SetWidgetBG(joystick_input, selected); + TXT_SetWidgetBG(joystick_input); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(buf); diff --git a/src/setup/txt_keyinput.c b/src/setup/txt_keyinput.c index 47e782be..55889dbc 100644 --- a/src/setup/txt_keyinput.c +++ b/src/setup/txt_keyinput.c @@ -102,7 +102,7 @@ static void TXT_KeyInputSizeCalc(TXT_UNCAST_ARG(key_input)) } -static void TXT_KeyInputDrawer(TXT_UNCAST_ARG(key_input), int selected) +static void TXT_KeyInputDrawer(TXT_UNCAST_ARG(key_input)) { TXT_CAST_ARG(txt_key_input_t, key_input); char buf[20]; @@ -117,7 +117,7 @@ static void TXT_KeyInputDrawer(TXT_UNCAST_ARG(key_input), int selected) TXT_GetKeyDescription(*key_input->variable, buf); } - TXT_SetWidgetBG(key_input, selected); + TXT_SetWidgetBG(key_input); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(buf); diff --git a/src/setup/txt_mouseinput.c b/src/setup/txt_mouseinput.c index c45bdc2e..6eee78cd 100644 --- a/src/setup/txt_mouseinput.c +++ b/src/setup/txt_mouseinput.c @@ -94,7 +94,7 @@ static void GetMouseButtonDescription(int button, char *buf) } } -static void TXT_MouseInputDrawer(TXT_UNCAST_ARG(mouse_input), int selected) +static void TXT_MouseInputDrawer(TXT_UNCAST_ARG(mouse_input)) { TXT_CAST_ARG(txt_mouse_input_t, mouse_input); char buf[20]; @@ -109,7 +109,7 @@ static void TXT_MouseInputDrawer(TXT_UNCAST_ARG(mouse_input), int selected) GetMouseButtonDescription(*mouse_input->variable, buf); } - TXT_SetWidgetBG(mouse_input, selected); + TXT_SetWidgetBG(mouse_input); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(buf); diff --git a/textscreen/txt_button.c b/textscreen/txt_button.c index 536e5f56..989bd4fc 100644 --- a/textscreen/txt_button.c +++ b/textscreen/txt_button.c @@ -38,7 +38,7 @@ static void TXT_ButtonSizeCalc(TXT_UNCAST_ARG(button)) button->widget.h = 1; } -static void TXT_ButtonDrawer(TXT_UNCAST_ARG(button), int selected) +static void TXT_ButtonDrawer(TXT_UNCAST_ARG(button)) { TXT_CAST_ARG(txt_button_t, button); int i; @@ -48,7 +48,7 @@ static void TXT_ButtonDrawer(TXT_UNCAST_ARG(button), int selected) TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); - TXT_SetWidgetBG(button, selected); + TXT_SetWidgetBG(button); TXT_DrawString(button->label); diff --git a/textscreen/txt_checkbox.c b/textscreen/txt_checkbox.c index f2183b7c..8c3271cf 100644 --- a/textscreen/txt_checkbox.c +++ b/textscreen/txt_checkbox.c @@ -40,7 +40,7 @@ static void TXT_CheckBoxSizeCalc(TXT_UNCAST_ARG(checkbox)) checkbox->widget.h = 1; } -static void TXT_CheckBoxDrawer(TXT_UNCAST_ARG(checkbox), int selected) +static void TXT_CheckBoxDrawer(TXT_UNCAST_ARG(checkbox)) { TXT_CAST_ARG(txt_checkbox_t, checkbox); int i; @@ -67,7 +67,7 @@ static void TXT_CheckBoxDrawer(TXT_UNCAST_ARG(checkbox), int selected) TXT_DrawString(") "); - TXT_SetWidgetBG(checkbox, selected); + TXT_SetWidgetBG(checkbox); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(checkbox->label); diff --git a/textscreen/txt_desktop.c b/textscreen/txt_desktop.c index 31c3921e..09589688 100644 --- a/textscreen/txt_desktop.c +++ b/textscreen/txt_desktop.c @@ -45,14 +45,29 @@ static unsigned int periodic_callback_period; void TXT_AddDesktopWindow(txt_window_t *win) { + // Previously-top window loses focus: + + if (num_windows > 0) + { + TXT_SetWindowFocus(all_windows[num_windows - 1], 0); + } + all_windows[num_windows] = win; ++num_windows; + + // New window gains focus: + + TXT_SetWindowFocus(win, 1); } void TXT_RemoveDesktopWindow(txt_window_t *win) { int from, to; + // Window must lose focus if it's being removed: + + TXT_SetWindowFocus(win, 0); + for (from=0, to=0; from<num_windows; ++from) { if (all_windows[from] != win) @@ -61,8 +76,15 @@ void TXT_RemoveDesktopWindow(txt_window_t *win) ++to; } } - + num_windows = to; + + // Top window gains focus: + + if (num_windows > 0) + { + TXT_SetWindowFocus(all_windows[num_windows - 1], 1); + } } txt_window_t *TXT_GetActiveWindow(void) @@ -144,7 +166,7 @@ void TXT_DrawDesktop(void) for (i=0; i<num_windows; ++i) { - TXT_DrawWindow(all_windows[i], i == num_windows - 1); + TXT_DrawWindow(all_windows[i]); } TXT_UpdateScreen(); diff --git a/textscreen/txt_desktop.h b/textscreen/txt_desktop.h index 4b6bd4b5..9e2a42c7 100644 --- a/textscreen/txt_desktop.h +++ b/textscreen/txt_desktop.h @@ -36,7 +36,8 @@ void TXT_AddDesktopWindow(txt_window_t *win); void TXT_RemoveDesktopWindow(txt_window_t *win); void TXT_DrawDesktop(void); void TXT_DispatchEvents(void); -void TXT_DrawWindow(txt_window_t *window, int selected); +void TXT_DrawWindow(txt_window_t *window); +void TXT_SetWindowFocus(txt_window_t *window, int focused); void TXT_WindowKeyPress(txt_window_t *window, int c); /** diff --git a/textscreen/txt_dropdown.c b/textscreen/txt_dropdown.c index a6185a4c..efc94683 100644 --- a/textscreen/txt_dropdown.c +++ b/textscreen/txt_dropdown.c @@ -221,7 +221,7 @@ static void TXT_DropdownListSizeCalc(TXT_UNCAST_ARG(list)) list->widget.h = 1; } -static void TXT_DropdownListDrawer(TXT_UNCAST_ARG(list), int selected) +static void TXT_DropdownListDrawer(TXT_UNCAST_ARG(list)) { TXT_CAST_ARG(txt_dropdown_list_t, list); unsigned int i; @@ -229,7 +229,7 @@ static void TXT_DropdownListDrawer(TXT_UNCAST_ARG(list), int selected) // Set bg/fg text colors. - TXT_SetWidgetBG(list, selected); + TXT_SetWidgetBG(list); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); // Select a string to draw from the list, if the current value is diff --git a/textscreen/txt_inputbox.c b/textscreen/txt_inputbox.c index a28c342c..2ba08ac6 100644 --- a/textscreen/txt_inputbox.c +++ b/textscreen/txt_inputbox.c @@ -32,7 +32,71 @@ #include "txt_main.h" #include "txt_window.h" -static void SetBufferFromValue(txt_inputbox_t *inputbox); +extern txt_widget_class_t txt_inputbox_class; +extern txt_widget_class_t txt_int_inputbox_class; + +static void SetBufferFromValue(txt_inputbox_t *inputbox) +{ + if (inputbox->widget.widget_class == &txt_inputbox_class) + { + char **value = (char **) inputbox->value; + + if (*value != NULL) + { + strncpy(inputbox->buffer, *value, inputbox->size); + inputbox->buffer[inputbox->size] = '\0'; + } + else + { + strcpy(inputbox->buffer, ""); + } + } + else if (inputbox->widget.widget_class == &txt_int_inputbox_class) + { + int *value = (int *) inputbox->value; + sprintf(inputbox->buffer, "%i", *value); + } +} + +static void StartEditing(txt_inputbox_t *inputbox) +{ + // Integer input boxes start from an empty buffer: + + if (inputbox->widget.widget_class == &txt_int_inputbox_class) + { + strcpy(inputbox->buffer, ""); + } + else + { + SetBufferFromValue(inputbox); + } + + inputbox->editing = 1; +} + +static void FinishEditing(txt_inputbox_t *inputbox) +{ + if (!inputbox->editing) + { + return; + } + + // Save the new value back to the variable. + + if (inputbox->widget.widget_class == &txt_inputbox_class) + { + free(*((char **)inputbox->value)); + *((char **) inputbox->value) = strdup(inputbox->buffer); + } + else if (inputbox->widget.widget_class == &txt_int_inputbox_class) + { + *((int *) inputbox->value) = atoi(inputbox->buffer); + } + + TXT_EmitSignal(&inputbox->widget, "changed"); + + inputbox->editing = 0; +} static void TXT_InputBoxSizeCalc(TXT_UNCAST_ARG(inputbox)) { @@ -44,25 +108,27 @@ static void TXT_InputBoxSizeCalc(TXT_UNCAST_ARG(inputbox)) inputbox->widget.h = 1; } -static void TXT_InputBoxDrawer(TXT_UNCAST_ARG(inputbox), int selected) +static void TXT_InputBoxDrawer(TXT_UNCAST_ARG(inputbox)) { TXT_CAST_ARG(txt_inputbox_t, inputbox); + int focused; int i; int chars; int w; + focused = inputbox->widget.focused; w = inputbox->widget.w; // Select the background color based on whether we are currently - // editing, and if not, whether the widget is selected. + // editing, and if not, whether the widget is focused. - if (inputbox->editing && selected) + if (inputbox->editing && focused) { TXT_BGColor(TXT_COLOR_BLACK, 0); } else { - TXT_SetWidgetBG(inputbox, selected); + TXT_SetWidgetBG(inputbox); } TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); @@ -70,21 +136,21 @@ static void TXT_InputBoxDrawer(TXT_UNCAST_ARG(inputbox), int selected) if (!inputbox->editing) { // If not editing, use the current value from inputbox->value. - + SetBufferFromValue(inputbox); } - + TXT_DrawString(inputbox->buffer); chars = strlen(inputbox->buffer); - if (chars < w && inputbox->editing && selected) + if (chars < w && inputbox->editing && focused) { TXT_BGColor(TXT_COLOR_BLACK, 1); TXT_DrawString("_"); ++chars; } - + for (i=chars; i < w; ++i) { TXT_DrawString(" "); @@ -125,8 +191,7 @@ static int TXT_InputBoxKeyPress(TXT_UNCAST_ARG(inputbox), int key) { if (key == KEY_ENTER) { - SetBufferFromValue(inputbox); - inputbox->editing = 1; + StartEditing(inputbox); return 1; } @@ -135,12 +200,7 @@ static int TXT_InputBoxKeyPress(TXT_UNCAST_ARG(inputbox), int key) if (key == KEY_ENTER) { - free(*((char **)inputbox->value)); - *((char **) inputbox->value) = strdup(inputbox->buffer); - - TXT_EmitSignal(&inputbox->widget, "changed"); - - inputbox->editing = 0; + FinishEditing(inputbox); } if (key == KEY_ESCAPE) @@ -159,50 +219,7 @@ static int TXT_InputBoxKeyPress(TXT_UNCAST_ARG(inputbox), int key) { Backspace(inputbox); } - - return 1; -} - -static int TXT_IntInputBoxKeyPress(TXT_UNCAST_ARG(inputbox), int key) -{ - TXT_CAST_ARG(txt_inputbox_t, inputbox); - - if (!inputbox->editing) - { - if (key == KEY_ENTER) - { - strcpy(inputbox->buffer, ""); - inputbox->editing = 1; - return 1; - } - - return 0; - } - - if (key == KEY_ENTER) - { - *((int *) inputbox->value) = atoi(inputbox->buffer); - inputbox->editing = 0; - } - - if (key == KEY_ESCAPE) - { - inputbox->editing = 0; - } - - if (isdigit(key)) - { - // Add character to the buffer - - AddCharacter(inputbox, key); - } - - if (key == KEY_BACKSPACE) - { - Backspace(inputbox); - } - return 1; } @@ -224,6 +241,18 @@ static void TXT_InputBoxMousePress(TXT_UNCAST_ARG(inputbox), } } +static void TXT_InputBoxFocused(TXT_UNCAST_ARG(inputbox), int focused) +{ + TXT_CAST_ARG(txt_inputbox_t, inputbox); + + // Stop editing when we lose focus. + + if (inputbox->editing && !focused) + { + FinishEditing(inputbox); + } +} + txt_widget_class_t txt_inputbox_class = { TXT_AlwaysSelectable, @@ -233,6 +262,7 @@ txt_widget_class_t txt_inputbox_class = TXT_InputBoxDestructor, TXT_InputBoxMousePress, NULL, + TXT_InputBoxFocused, }; txt_widget_class_t txt_int_inputbox_class = @@ -240,35 +270,13 @@ txt_widget_class_t txt_int_inputbox_class = TXT_AlwaysSelectable, TXT_InputBoxSizeCalc, TXT_InputBoxDrawer, - TXT_IntInputBoxKeyPress, + TXT_InputBoxKeyPress, TXT_InputBoxDestructor, TXT_InputBoxMousePress, NULL, + TXT_InputBoxFocused, }; -static void SetBufferFromValue(txt_inputbox_t *inputbox) -{ - if (inputbox->widget.widget_class == &txt_inputbox_class) - { - char **value = (char **) inputbox->value; - - if (*value != NULL) - { - strncpy(inputbox->buffer, *value, inputbox->size); - inputbox->buffer[inputbox->size] = '\0'; - } - else - { - strcpy(inputbox->buffer, ""); - } - } - else if (inputbox->widget.widget_class == &txt_int_inputbox_class) - { - int *value = (int *) inputbox->value; - sprintf(inputbox->buffer, "%i", *value); - } -} - txt_inputbox_t *TXT_NewInputBox(char **value, int size) { txt_inputbox_t *inputbox; diff --git a/textscreen/txt_label.c b/textscreen/txt_label.c index c973bce2..a2afc13b 100644 --- a/textscreen/txt_label.c +++ b/textscreen/txt_label.c @@ -36,7 +36,7 @@ static void TXT_LabelSizeCalc(TXT_UNCAST_ARG(label)) label->widget.h = label->h; } -static void TXT_LabelDrawer(TXT_UNCAST_ARG(label), int selected) +static void TXT_LabelDrawer(TXT_UNCAST_ARG(label)) { TXT_CAST_ARG(txt_label_t, label); unsigned int x, y; diff --git a/textscreen/txt_radiobutton.c b/textscreen/txt_radiobutton.c index 0755562d..10f94ad3 100644 --- a/textscreen/txt_radiobutton.c +++ b/textscreen/txt_radiobutton.c @@ -40,7 +40,7 @@ static void TXT_RadioButtonSizeCalc(TXT_UNCAST_ARG(radiobutton)) radiobutton->widget.h = 1; } -static void TXT_RadioButtonDrawer(TXT_UNCAST_ARG(radiobutton), int selected) +static void TXT_RadioButtonDrawer(TXT_UNCAST_ARG(radiobutton)) { TXT_CAST_ARG(txt_radiobutton_t, radiobutton); int i; @@ -67,7 +67,7 @@ static void TXT_RadioButtonDrawer(TXT_UNCAST_ARG(radiobutton), int selected) TXT_DrawString(") "); - TXT_SetWidgetBG(radiobutton, selected); + TXT_SetWidgetBG(radiobutton); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(radiobutton->label); diff --git a/textscreen/txt_scrollpane.c b/textscreen/txt_scrollpane.c index dba69d30..c53f68df 100644 --- a/textscreen/txt_scrollpane.c +++ b/textscreen/txt_scrollpane.c @@ -172,7 +172,7 @@ static void TXT_ScrollPaneSizeCalc(TXT_UNCAST_ARG(scrollpane)) } } -static void TXT_ScrollPaneDrawer(TXT_UNCAST_ARG(scrollpane), int selected) +static void TXT_ScrollPaneDrawer(TXT_UNCAST_ARG(scrollpane)) { TXT_CAST_ARG(txt_scrollpane_t, scrollpane); int x1, y1, x2, y2; @@ -211,7 +211,7 @@ static void TXT_ScrollPaneDrawer(TXT_UNCAST_ARG(scrollpane), int selected) if (scrollpane->child != NULL) { - TXT_DrawWidget(scrollpane->child, selected); + TXT_DrawWidget(scrollpane->child); } // Restore old clipping area. @@ -229,6 +229,19 @@ static void TXT_ScrollPaneDestructor(TXT_UNCAST_ARG(scrollpane)) } } +static void TXT_ScrollPaneFocused(TXT_UNCAST_ARG(scrollpane), int focused) +{ + TXT_CAST_ARG(txt_scrollpane_t, scrollpane); + + // Whether the child is focused depends only on whether the scroll pane + // itself is focused. Pass through focus to the child. + + if (scrollpane->child != NULL) + { + TXT_SetWidgetFocus(scrollpane->child, focused); + } +} + // Hack for tables - when browsing a table inside a scroll pane, // automatically scroll the window to show the newly-selected // item. @@ -552,6 +565,7 @@ txt_widget_class_t txt_scrollpane_class = TXT_ScrollPaneDestructor, TXT_ScrollPaneMousePress, TXT_ScrollPaneLayout, + TXT_ScrollPaneFocused, }; txt_scrollpane_t *TXT_NewScrollPane(int w, int h, TXT_UNCAST_ARG(target)) diff --git a/textscreen/txt_sdl.c b/textscreen/txt_sdl.c index c22580fe..8ad5bf74 100644 --- a/textscreen/txt_sdl.c +++ b/textscreen/txt_sdl.c @@ -410,25 +410,6 @@ static int TranslateKey(SDL_keysym *sym) case SDLK_CAPSLOCK: return KEY_CAPSLOCK; case SDLK_SCROLLOCK: return KEY_SCRLCK; - case SDLK_KP0: return KEYP_0; - case SDLK_KP1: return KEYP_1; - case SDLK_KP2: return KEYP_2; - case SDLK_KP3: return KEYP_3; - case SDLK_KP4: return KEYP_4; - case SDLK_KP5: return KEYP_5; - case SDLK_KP6: return KEYP_6; - case SDLK_KP7: return KEYP_7; - case SDLK_KP8: return KEYP_8; - case SDLK_KP9: return KEYP_9; - - case SDLK_KP_PERIOD: return KEYP_PERIOD; - case SDLK_KP_MULTIPLY: return KEYP_MULTIPLY; - case SDLK_KP_PLUS: return KEYP_PLUS; - case SDLK_KP_MINUS: return KEYP_MINUS; - case SDLK_KP_DIVIDE: return KEYP_DIVIDE; - case SDLK_KP_EQUALS: return KEYP_EQUALS; - case SDLK_KP_ENTER: return KEYP_ENTER; - case SDLK_HOME: return KEY_HOME; case SDLK_INSERT: return KEY_INS; case SDLK_END: return KEY_END; @@ -459,7 +440,34 @@ static int TranslateKey(SDL_keysym *sym) } else { - return tolower(sym->sym); + // Keypad mapping is only done when we want a raw value: + // most of the time, the keypad should behave as it normally + // does. + + switch (sym->sym) + { + case SDLK_KP0: return KEYP_0; + case SDLK_KP1: return KEYP_1; + case SDLK_KP2: return KEYP_2; + case SDLK_KP3: return KEYP_3; + case SDLK_KP4: return KEYP_4; + case SDLK_KP5: return KEYP_5; + case SDLK_KP6: return KEYP_6; + case SDLK_KP7: return KEYP_7; + case SDLK_KP8: return KEYP_8; + case SDLK_KP9: return KEYP_9; + + case SDLK_KP_PERIOD: return KEYP_PERIOD; + case SDLK_KP_MULTIPLY: return KEYP_MULTIPLY; + case SDLK_KP_PLUS: return KEYP_PLUS; + case SDLK_KP_MINUS: return KEYP_MINUS; + case SDLK_KP_DIVIDE: return KEYP_DIVIDE; + case SDLK_KP_EQUALS: return KEYP_EQUALS; + case SDLK_KP_ENTER: return KEYP_ENTER; + + default: + return tolower(sym->sym); + } } } diff --git a/textscreen/txt_separator.c b/textscreen/txt_separator.c index 89db0b03..ce6e29ec 100644 --- a/textscreen/txt_separator.c +++ b/textscreen/txt_separator.c @@ -46,7 +46,7 @@ static void TXT_SeparatorSizeCalc(TXT_UNCAST_ARG(separator)) separator->widget.h = 1; } -static void TXT_SeparatorDrawer(TXT_UNCAST_ARG(separator), int selected) +static void TXT_SeparatorDrawer(TXT_UNCAST_ARG(separator)) { TXT_CAST_ARG(txt_separator_t, separator); int x, y; diff --git a/textscreen/txt_spinctrl.c b/textscreen/txt_spinctrl.c index 2b2d4d09..a4d20343 100644 --- a/textscreen/txt_spinctrl.c +++ b/textscreen/txt_spinctrl.c @@ -142,11 +142,14 @@ static void SetBuffer(txt_spincontrol_t *spincontrol) } } -static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol), int selected) +static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol)) { TXT_CAST_ARG(txt_spincontrol_t, spincontrol); unsigned int i; unsigned int padding; + int focused; + + focused = spincontrol->widget.focused; TXT_FGColor(TXT_COLOR_BRIGHT_CYAN); TXT_BGColor(TXT_WINDOW_BACKGROUND, 0); @@ -157,13 +160,13 @@ static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol), int selected) // Choose background color - if (selected && spincontrol->editing) + if (focused && spincontrol->editing) { TXT_BGColor(TXT_COLOR_BLACK, 0); } else { - TXT_SetWidgetBG(spincontrol, selected); + TXT_SetWidgetBG(spincontrol); } if (!spincontrol->editing) @@ -239,6 +242,23 @@ static void EnforceLimits(txt_spincontrol_t *spincontrol) } } +static void FinishEditing(txt_spincontrol_t *spincontrol) +{ + switch (spincontrol->type) + { + case TXT_SPINCONTROL_INT: + spincontrol->value->i = atoi(spincontrol->buffer); + break; + + case TXT_SPINCONTROL_FLOAT: + spincontrol->value->f = (float) atof(spincontrol->buffer); + break; + } + + spincontrol->editing = 0; + EnforceLimits(spincontrol); +} + static int TXT_SpinControlKeyPress(TXT_UNCAST_ARG(spincontrol), int key) { TXT_CAST_ARG(txt_spincontrol_t, spincontrol); @@ -249,19 +269,7 @@ static int TXT_SpinControlKeyPress(TXT_UNCAST_ARG(spincontrol), int key) { if (key == KEY_ENTER) { - switch (spincontrol->type) - { - case TXT_SPINCONTROL_INT: - spincontrol->value->i = atoi(spincontrol->buffer); - break; - - case TXT_SPINCONTROL_FLOAT: - spincontrol->value->f = (float) atof(spincontrol->buffer); - break; - } - - spincontrol->editing = 0; - EnforceLimits(spincontrol); + FinishEditing(spincontrol); return 1; } @@ -352,6 +360,13 @@ static void TXT_SpinControlMousePress(TXT_UNCAST_ARG(spincontrol), } } +static void TXT_SpinControlFocused(TXT_UNCAST_ARG(spincontrol), int focused) +{ + TXT_CAST_ARG(txt_spincontrol_t, spincontrol); + + FinishEditing(spincontrol); +} + txt_widget_class_t txt_spincontrol_class = { TXT_AlwaysSelectable, @@ -361,6 +376,7 @@ txt_widget_class_t txt_spincontrol_class = TXT_SpinControlDestructor, TXT_SpinControlMousePress, NULL, + TXT_SpinControlFocused, }; static txt_spincontrol_t *TXT_BaseSpinControl(void) diff --git a/textscreen/txt_strut.c b/textscreen/txt_strut.c index f3a618f3..367e798a 100644 --- a/textscreen/txt_strut.c +++ b/textscreen/txt_strut.c @@ -39,7 +39,7 @@ static void TXT_StrutSizeCalc(TXT_UNCAST_ARG(strut)) strut->widget.h = strut->height; } -static void TXT_StrutDrawer(TXT_UNCAST_ARG(strut), int selected) +static void TXT_StrutDrawer(TXT_UNCAST_ARG(strut)) { // Nothing is drawn for a strut. } diff --git a/textscreen/txt_table.c b/textscreen/txt_table.c index 7a8624f0..573df428 100644 --- a/textscreen/txt_table.c +++ b/textscreen/txt_table.c @@ -264,6 +264,48 @@ static int FindSelectableColumn(txt_table_t *table, int row, int start_col) return -1; } +// Change the selected widget. + +static void ChangeSelection(txt_table_t *table, int x, int y) +{ + txt_widget_t *cur_widget; + txt_widget_t *new_widget; + int i; + + // No change? + + if (x == table->selected_x && y == table->selected_y) + { + return; + } + + // Unfocus current widget: + + i = table->selected_y * table->columns + table->selected_x; + + if (i < table->num_widgets) + { + cur_widget = table->widgets[i]; + + if (table->widget.focused && cur_widget != NULL) + { + TXT_SetWidgetFocus(cur_widget, 0); + } + } + + // Focus new widget. + + new_widget = table->widgets[y * table->columns + x]; + + table->selected_x = x; + table->selected_y = y; + + if (table->widget.focused && new_widget != NULL) + { + TXT_SetWidgetFocus(new_widget, 1); + } +} + static int TXT_TableKeyPress(TXT_UNCAST_ARG(table), int key) { TXT_CAST_ARG(txt_table_t, table); @@ -300,8 +342,7 @@ static int TXT_TableKeyPress(TXT_UNCAST_ARG(table), int key) { // Found a selectable widget in this column! - table->selected_x = new_x; - table->selected_y = new_y; + ChangeSelection(table, new_x, new_y); return 1; } @@ -317,13 +358,12 @@ static int TXT_TableKeyPress(TXT_UNCAST_ARG(table), int key) for (new_y = table->selected_y - 1; new_y >= 0; --new_y) { new_x = FindSelectableColumn(table, new_y, table->selected_x); - + if (new_x >= 0) { // Found a selectable widget in this column! - table->selected_x = new_x; - table->selected_y = new_y; + ChangeSelection(table, new_x, new_y); return 1; } @@ -342,7 +382,7 @@ static int TXT_TableKeyPress(TXT_UNCAST_ARG(table), int key) { // Found a selectable widget! - table->selected_x = new_x; + ChangeSelection(table, new_x, table->selected_y); return 1; } @@ -361,7 +401,7 @@ static int TXT_TableKeyPress(TXT_UNCAST_ARG(table), int key) { // Found a selectable widget! - table->selected_x = new_x; + ChangeSelection(table, new_x, table->selected_y); return 1; } @@ -388,8 +428,7 @@ static void CheckValidSelection(txt_table_t *table) { // Found a selectable column. - table->selected_x = new_x; - table->selected_y = new_y; + ChangeSelection(table, new_x, new_y); break; } @@ -502,25 +541,20 @@ static void TXT_TableLayout(TXT_UNCAST_ARG(table)) free(row_heights); free(column_widths); } - -static void TXT_TableDrawer(TXT_UNCAST_ARG(table), int selected) + +static void TXT_TableDrawer(TXT_UNCAST_ARG(table)) { 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]; @@ -528,7 +562,7 @@ static void TXT_TableDrawer(TXT_UNCAST_ARG(table), int selected) if (widget != NULL) { TXT_GotoXY(widget->x, widget->y); - TXT_DrawWidget(widget, selected && i == selected_cell); + TXT_DrawWidget(widget); } } } @@ -558,8 +592,8 @@ static void TXT_TableMousePress(TXT_UNCAST_ARG(table), int x, int y, int b) if (TXT_SelectableWidget(widget)) { - table->selected_x = i % table->columns; - table->selected_y = i / table->columns; + ChangeSelection(table, i % table->columns, + i / table->columns); } // Propagate click @@ -593,8 +627,7 @@ static int TXT_TableSelectable(TXT_UNCAST_ARG(table)) if (table->widgets[i] != NULL && TXT_SelectableWidget(table->widgets[i])) { - table->selected_x = i % table->columns; - table->selected_y = i / table->columns; + ChangeSelection(table, i % table->columns, i / table->columns); return 1; } } @@ -604,6 +637,24 @@ static int TXT_TableSelectable(TXT_UNCAST_ARG(table)) return 0; } +// Need to pass through focus changes to the selected child widget. + +static void TXT_TableFocused(TXT_UNCAST_ARG(table), int focused) +{ + TXT_CAST_ARG(txt_table_t, table); + int i; + + i = table->selected_y * table->columns + table->selected_x; + + if (i < table->num_widgets) + { + if (table->widgets[i] != NULL) + { + TXT_SetWidgetFocus(table->widgets[i], focused); + } + } +} + txt_widget_class_t txt_table_class = { TXT_TableSelectable, @@ -613,6 +664,7 @@ txt_widget_class_t txt_table_class = TXT_TableDestructor, TXT_TableMousePress, TXT_TableLayout, + TXT_TableFocused, }; void TXT_InitTable(txt_table_t *table, int columns) @@ -757,17 +809,16 @@ int TXT_SelectWidget(TXT_UNCAST_ARG(table), TXT_UNCAST_ARG(widget)) { continue; } - + if (table->widgets[i] == widget) { // Found the item! Select it and return. - - table->selected_x = i % table->columns; - table->selected_y = i / table->columns; + + ChangeSelection(table, i % table->columns, i / table->columns); return 1; } - + if (table->widgets[i]->widget_class == &txt_table_class) { // This item is a subtable. Recursively search this table. @@ -776,8 +827,7 @@ int TXT_SelectWidget(TXT_UNCAST_ARG(table), TXT_UNCAST_ARG(widget)) { // Found it in the subtable. Select this subtable and return. - table->selected_x = i % table->columns; - table->selected_y = i / table->columns; + ChangeSelection(table, i % table->columns, i / table->columns); return 1; } @@ -874,8 +924,7 @@ int TXT_PageTable(TXT_UNCAST_ARG(table), int pagex, int pagey) // Found a selectable widget in this column! // Select it anyway in case we don't find something better. - table->selected_x = new_x; - table->selected_y = new_y; + ChangeSelection(table, new_x, new_y); changed = 1; // ...but is it far enough away? diff --git a/textscreen/txt_widget.c b/textscreen/txt_widget.c index d47a7507..7d31ad68 100644 --- a/textscreen/txt_widget.c +++ b/textscreen/txt_widget.c @@ -86,6 +86,10 @@ void TXT_InitWidget(TXT_UNCAST_ARG(widget), txt_widget_class_t *widget_class) widget->callback_table = TXT_NewCallbackTable(); widget->parent = NULL; + // Not focused until we hear otherwise. + + widget->focused = 0; + // Visible by default. widget->visible = 1; @@ -155,7 +159,7 @@ void TXT_CalcWidgetSize(TXT_UNCAST_ARG(widget)) widget->widget_class->size_calc(widget); } -void TXT_DrawWidget(TXT_UNCAST_ARG(widget), int selected) +void TXT_DrawWidget(TXT_UNCAST_ARG(widget)) { TXT_CAST_ARG(txt_widget_t, widget); @@ -165,7 +169,7 @@ void TXT_DrawWidget(TXT_UNCAST_ARG(widget), int selected) // Call drawer method - widget->widget_class->drawer(widget, selected); + widget->widget_class->drawer(widget); } void TXT_DestroyWidget(TXT_UNCAST_ARG(widget)) @@ -189,6 +193,26 @@ int TXT_WidgetKeyPress(TXT_UNCAST_ARG(widget), int key) return 0; } +void TXT_SetWidgetFocus(TXT_UNCAST_ARG(widget), int focused) +{ + TXT_CAST_ARG(txt_widget_t, widget); + + if (widget == NULL) + { + return; + } + + if (widget->focused != focused) + { + widget->focused = focused; + + if (widget->widget_class->focus_change != NULL) + { + widget->widget_class->focus_change(widget, focused); + } + } +} + void TXT_SetWidgetAlign(TXT_UNCAST_ARG(widget), txt_horiz_align_t horiz_align) { TXT_CAST_ARG(txt_widget_t, widget); @@ -281,11 +305,11 @@ int TXT_HoveringOverWidget(TXT_UNCAST_ARG(widget)) && y >= widget->y && y < widget->y + widget->h); } -void TXT_SetWidgetBG(TXT_UNCAST_ARG(widget), int selected) +void TXT_SetWidgetBG(TXT_UNCAST_ARG(widget)) { TXT_CAST_ARG(txt_widget_t, widget); - if (selected) + if (widget->focused) { TXT_BGColor(TXT_COLOR_GREY, 0); } diff --git a/textscreen/txt_widget.h b/textscreen/txt_widget.h index ebb5a292..f64b9517 100644 --- a/textscreen/txt_widget.h +++ b/textscreen/txt_widget.h @@ -71,13 +71,14 @@ typedef struct txt_widget_class_s txt_widget_class_t; typedef struct txt_callback_table_s txt_callback_table_t; typedef void (*TxtWidgetSizeCalc)(TXT_UNCAST_ARG(widget)); -typedef void (*TxtWidgetDrawer)(TXT_UNCAST_ARG(widget), int selected); +typedef void (*TxtWidgetDrawer)(TXT_UNCAST_ARG(widget)); 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)); typedef int (*TxtWidgetSelectableFunc)(TXT_UNCAST_ARG(widget)); +typedef void (*TxtWidgetFocusFunc)(TXT_UNCAST_ARG(widget), int focused); struct txt_widget_class_s { @@ -88,6 +89,7 @@ struct txt_widget_class_s TxtWidgetDestroy destructor; TxtMousePressFunc mouse_press; TxtWidgetLayoutFunc layout; + TxtWidgetFocusFunc focus_change; }; struct txt_widget_s @@ -96,6 +98,7 @@ struct txt_widget_s txt_callback_table_t *callback_table; int visible; txt_horiz_align_t align; + int focused; // These are set automatically when the window is drawn and should // not be set manually. @@ -110,7 +113,7 @@ struct txt_widget_s void TXT_InitWidget(TXT_UNCAST_ARG(widget), txt_widget_class_t *widget_class); void TXT_CalcWidgetSize(TXT_UNCAST_ARG(widget)); -void TXT_DrawWidget(TXT_UNCAST_ARG(widget), int selected); +void TXT_DrawWidget(TXT_UNCAST_ARG(widget)); void TXT_EmitSignal(TXT_UNCAST_ARG(widget), const 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); @@ -118,6 +121,7 @@ void TXT_DestroyWidget(TXT_UNCAST_ARG(widget)); void TXT_LayoutWidget(TXT_UNCAST_ARG(widget)); int TXT_AlwaysSelectable(TXT_UNCAST_ARG(widget)); int TXT_NeverSelectable(TXT_UNCAST_ARG(widget)); +void TXT_SetWidgetFocus(TXT_UNCAST_ARG(widget), int focused); /** * Set a callback function to be invoked when a signal occurs. @@ -167,7 +171,7 @@ int TXT_HoveringOverWidget(TXT_UNCAST_ARG(widget)); * @param selected Whether the widget is selected. */ -void TXT_SetWidgetBG(TXT_UNCAST_ARG(widget), int selected); +void TXT_SetWidgetBG(TXT_UNCAST_ARG(widget)); /** * Query whether the specified widget is contained within another diff --git a/textscreen/txt_window.c b/textscreen/txt_window.c index 8cbddb55..67543735 100644 --- a/textscreen/txt_window.c +++ b/textscreen/txt_window.c @@ -97,6 +97,7 @@ void TXT_CloseWindow(txt_window_t *window) int i; TXT_EmitSignal(window, "closed"); + TXT_RemoveDesktopWindow(window); free(window->title); @@ -113,8 +114,6 @@ void TXT_CloseWindow(txt_window_t *window) // Destroy table and window TXT_DestroyWidget(window); - - TXT_RemoveDesktopWindow(window); } static void CalcWindowPosition(txt_window_t *window) @@ -218,7 +217,7 @@ static void DrawActionArea(txt_window_t *window) { if (window->actions[i] != NULL) { - TXT_DrawWidget(window->actions[i], 0); + TXT_DrawWidget(window->actions[i]); } } } @@ -317,7 +316,7 @@ void TXT_LayoutWindow(txt_window_t *window) TXT_LayoutWidget(widgets); } -void TXT_DrawWindow(txt_window_t *window, int selected) +void TXT_DrawWindow(txt_window_t *window) { txt_widget_t *widgets; @@ -331,7 +330,7 @@ void TXT_DrawWindow(txt_window_t *window, int selected) // Draw all widgets - TXT_DrawWidget(window, selected); + TXT_DrawWidget(window); // Draw an action area, if we have one @@ -410,7 +409,21 @@ static void MouseButtonPress(txt_window_t *window, int b) && x >= widget->x && x < (signed) (widget->x + widget->w) && y >= widget->y && y < (signed) (widget->y + widget->h)) { + int was_focused; + + // Main table temporarily loses focus when action area button + // is clicked. This way, any active input boxes that depend + // on having focus will save their values before the + // action is performed. + + was_focused = window->table.widget.focused; + TXT_SetWidgetFocus(window, 0); + TXT_SetWidgetFocus(window, was_focused); + + // Pass through mouse press. + TXT_WidgetMousePress(widget, x, y, b); + break; } } @@ -474,6 +487,11 @@ void TXT_SetMouseListener(txt_window_t *window, window->mouse_listener_data = user_data; } +void TXT_SetWindowFocus(txt_window_t *window, int focused) +{ + TXT_SetWidgetFocus(window, focused); +} + txt_window_t *TXT_MessageBox(char *title, char *message, ...) { txt_window_t *window; diff --git a/textscreen/txt_window_action.c b/textscreen/txt_window_action.c index df0e4ea3..cf5ac4a7 100644 --- a/textscreen/txt_window_action.c +++ b/textscreen/txt_window_action.c @@ -44,7 +44,7 @@ static void TXT_WindowActionSizeCalc(TXT_UNCAST_ARG(action)) action->widget.h = 1; } -static void TXT_WindowActionDrawer(TXT_UNCAST_ARG(action), int selected) +static void TXT_WindowActionDrawer(TXT_UNCAST_ARG(action)) { TXT_CAST_ARG(txt_window_action_t, action); char buf[10]; |