Rework textscreen focus handling so that input boxes will stop editing
when they lose their focus (thanks Twelve). Subversion-branch: /trunk/chocolate-doom Subversion-revision: 2460
This commit is contained in:
parent
71d316afb2
commit
dd52766c7b
20 changed files with 330 additions and 165 deletions
|
|
@ -147,7 +147,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];
|
||||
|
|
@ -162,7 +162,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);
|
||||
|
|
|
|||
|
|
@ -112,7 +112,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];
|
||||
|
|
@ -127,7 +127,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);
|
||||
|
|
|
|||
|
|
@ -104,7 +104,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];
|
||||
|
|
@ -119,7 +119,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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -41,14 +41,29 @@ static int main_loop_running = 0;
|
|||
|
||||
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)
|
||||
|
|
@ -57,8 +72,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)
|
||||
|
|
@ -140,7 +162,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();
|
||||
|
|
|
|||
|
|
@ -34,7 +34,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);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -206,7 +206,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;
|
||||
|
|
@ -214,7 +214,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
|
||||
|
|
|
|||
|
|
@ -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(" ");
|
||||
|
|
@ -95,6 +161,14 @@ static void TXT_InputBoxDestructor(TXT_UNCAST_ARG(inputbox))
|
|||
{
|
||||
TXT_CAST_ARG(txt_inputbox_t, inputbox);
|
||||
|
||||
// If we're still editing when the widget is destroyed, save the
|
||||
// value first.
|
||||
|
||||
if (inputbox->editing)
|
||||
{
|
||||
FinishEditing(inputbox);
|
||||
}
|
||||
|
||||
free(inputbox->buffer);
|
||||
}
|
||||
|
||||
|
|
@ -125,8 +199,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 +208,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 +227,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 +249,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 +270,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 +278,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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -160,7 +160,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;
|
||||
|
|
@ -199,7 +199,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.
|
||||
|
|
@ -217,6 +217,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.
|
||||
|
|
@ -540,6 +553,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))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ static void DrawActionArea(txt_window_t *window)
|
|||
{
|
||||
if (window->actions[i] != NULL)
|
||||
{
|
||||
TXT_DrawWidget(window->actions[i], 0);
|
||||
TXT_DrawWidget(window->actions[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -315,7 +315,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;
|
||||
|
||||
|
|
@ -329,7 +329,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
|
||||
|
||||
|
|
@ -408,7 +408,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -472,3 +486,8 @@ 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
Loading…
Reference in a new issue