textbox widget

This commit is contained in:
Robert Jordan 2015-06-06 17:04:53 -04:00
parent dd84ee8340
commit 9f9143a5c6
7 changed files with 204 additions and 11 deletions

View File

@ -736,6 +736,12 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex)
if (widgetIndex == -1)
return;
if (windowClass != gCurrentTextBox.window.classification ||
windowNumber != gCurrentTextBox.window.number ||
widgetIndex != gCurrentTextBox.widget_index) {
window_cancel_textbox();
}
widget = &w->widgets[widgetIndex];
switch (widget->type) {
@ -1173,8 +1179,10 @@ void game_handle_keyboard_input()
// Reserve backtick for console
if (key == SDL_SCANCODE_GRAVE) {
if (gConfigGeneral.debugging_tools || gConsoleOpen)
if (gConfigGeneral.debugging_tools || gConsoleOpen) {
window_cancel_textbox();
console_toggle();
}
continue;
} else if (gConsoleOpen) {
console_input(key);
@ -1195,7 +1203,7 @@ void game_handle_keyboard_input()
if (w != NULL){
((void(*)(int, rct_window*))w->event_handlers[WE_TEXT_INPUT])(key, w);
}
else {
else if (!gUsingWidgetTextBox) {
keyboard_shortcut_handle(key);
}
}
@ -1374,7 +1382,7 @@ void game_handle_key_scroll()
rct_window *textWindow;
textWindow = window_find_by_class(WC_TEXTINPUT);
if (textWindow) return;
if (textWindow || gUsingWidgetTextBox) return;
scrollX = 0;
scrollY = 0;

View File

@ -24,6 +24,8 @@
#include "../sprites.h"
#include "widget.h"
#include "window.h"
#include "../platform/platform.h"
#include "../localisation/localisation.h"
static void widget_frame_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_resize_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
@ -35,6 +37,7 @@ static void widget_text_unknown(rct_drawpixelinfo *dpi, rct_window *w, int widge
static void widget_text(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_text_inset(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_text_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_text_box_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_groupbox_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_caption_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
static void widget_checkbox_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex);
@ -160,6 +163,9 @@ void widget_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex)
break;
case WWT_25:
break;
case WWT_TEXT_BOX:
widget_text_box_draw(dpi, w, widgetIndex);
break;
}
}
@ -1124,4 +1130,77 @@ void widget_set_checkbox_value(rct_window *w, int widgetIndex, int value)
w->pressed_widgets |= (1ULL << widgetIndex);
else
w->pressed_widgets &= ~(1ULL << widgetIndex);
}
}
static void widget_text_box_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex)
{
rct_widget* widget;
int l, t, r, b;
uint8 colour;
int no_lines = 0;
int font_height = 0;
char wrapped_string[512];
// Get the widget
widget = &w->widgets[widgetIndex];
// Resolve the absolute ltrb
l = w->x + widget->left;
t = w->y + widget->top;
r = w->x + widget->right;
b = w->y + widget->bottom;
// Get the colour
colour = w->colours[widget->colour];
bool active = w->classification == gCurrentTextBox.window.classification &&
w->number == gCurrentTextBox.window.number &&
widgetIndex == gCurrentTextBox.widget_index;
//gfx_fill_rect_inset(dpi, l, t, r, b, colour, 0x20 | (!active ? 0x40 : 0x00));
gfx_fill_rect_inset(dpi, l, t, r, b, colour, 0x60);
if (!active) {
if (w->widgets[widgetIndex].image != 0) {
strcpy(wrapped_string, (char*)w->widgets[widgetIndex].image);
gfx_wrap_string(wrapped_string, r - l - 5, &no_lines, &font_height);
gfx_draw_string(dpi, wrapped_string, w->colours[1], l + 2, t);
}
return;
}
strcpy(wrapped_string, gTextBoxInput);
// String length needs to add 12 either side of box
// +13 for cursor when max length.
gfx_wrap_string(wrapped_string, r - l - 5 - 6, &no_lines, &font_height);
gfx_draw_string(dpi, wrapped_string, w->colours[1], l + 2, t);
int string_length = get_string_length(wrapped_string);
// Make a copy of the string for measuring the width.
char temp_string[512] = { 0 };
memcpy(temp_string, wrapped_string, min(string_length, gTextInputCursorPosition));
int cur_x = l + gfx_get_string_width(temp_string) + 3;
int width = 6;
if ((uint32)gTextInputCursorPosition < strlen(gTextBoxInput)){
// Make a new 1 character wide string for measuring the width
// of the character that the cursor is under.
temp_string[1] = '\0';
temp_string[0] = gTextBoxInput[gTextInputCursorPosition];
width = max(gfx_get_string_width(temp_string) - 2, 4);
}
if (gTextBoxFrameNo <= 15){
uint8 colour = RCT2_ADDRESS(0x0141FC48, uint8)[w->colours[1] * 8];
gfx_fill_rect(dpi, cur_x, t + 9, cur_x + width, t + 9, colour + 5);
}
}

View File

@ -50,7 +50,8 @@ typedef enum {
WWT_CHECKBOX = 23,
WWT_24,
WWT_25,
WWT_LAST = 26,
WWT_TEXT_BOX = 26,
WWT_LAST = 27,
} WINDOW_WIDGET_TYPES;
#define WIDGETS_END WWT_LAST, 0, 0, 0, 0, 0, 0, 0

View File

@ -29,6 +29,8 @@
#include "widget.h"
#include "window.h"
#include "viewport.h"
#include "../localisation/string_ids.h"
#include "../localisation/localisation.h"
#define RCT2_FIRST_WINDOW (RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window))
#define RCT2_LAST_WINDOW (RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*) - 1)
@ -39,6 +41,11 @@
rct_window* g_window_list = RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window);
uint8 TextInputDescriptionArgs[8];
widget_identifier gCurrentTextBox = { { 255, 0 }, 0 };
char gTextBoxInput[512] = { 0 };
int gMaxTextBoxInputLength = 0;
int gTextBoxFrameNo = 0;
bool gUsingWidgetTextBox = 0;
// converted from uint16 values at 0x009A41EC - 0x009A4230
// these are percentage coordinates of the viewport to center to, if a window is obscuring a location, the next is tried
@ -2177,4 +2184,70 @@ void textinput_cancel()
window_event_textinput_call(w, RCT2_GLOBAL(RCT2_ADDRESS_TEXTINPUT_WIDGETINDEX, uint16), NULL);
}
}
}
void window_start_textbox(rct_window *call_w, int call_widget, rct_string_id existing_text, uint32 existing_args, int maxLength)
{
if (gUsingWidgetTextBox)
window_cancel_textbox();
gUsingWidgetTextBox = true;
gCurrentTextBox.window.classification = call_w->classification;
gCurrentTextBox.window.number = call_w->number;
gCurrentTextBox.widget_index = call_widget;
gTextBoxFrameNo = 0;
gMaxTextBoxInputLength = maxLength;
window_close_by_class(WC_TEXTINPUT);
// Clear the text input buffer
memset(gTextBoxInput, 0, maxLength);
// Enter in the the text input buffer any existing
// text.
if (existing_text != (rct_string_id)STR_NONE)
format_string(gTextBoxInput, existing_text, &existing_args);
// In order to prevent strings that exceed the maxLength
// from crashing the game.
gTextBoxInput[maxLength - 1] = '\0';
platform_start_text_input(gTextBoxInput, maxLength);
}
void window_cancel_textbox()
{
if (gUsingWidgetTextBox) {
rct_window *w = window_find_by_number(
gCurrentTextBox.window.classification,
gCurrentTextBox.window.number
);
gCurrentTextBox.window.classification = 255;
gCurrentTextBox.window.number = 0;
platform_stop_text_input();
gUsingWidgetTextBox = false;
widget_invalidate(w, gCurrentTextBox.widget_index);
gCurrentTextBox.widget_index = WWT_LAST;
}
}
void window_update_textbox_caret()
{
gTextBoxFrameNo++;
if (gTextBoxFrameNo > 30)
gTextBoxFrameNo = 0;
}
void window_update_textbox()
{
if (gUsingWidgetTextBox) {
gTextBoxFrameNo = 0;
rct_window *w = window_find_by_number(
gCurrentTextBox.window.classification,
gCurrentTextBox.window.number
);
widget_invalidate(w, gCurrentTextBox.widget_index);
window_event_textinput_call(w, gCurrentTextBox.widget_index, gTextBoxInput);
}
}

View File

@ -31,6 +31,10 @@
struct rct_window;
union rct_window_event;
extern uint8 TextInputDescriptionArgs[8];
extern char gTextBoxInput[512];
extern int gMaxTextBoxInputLength;
extern int gTextBoxFrameNo;
extern bool gUsingWidgetTextBox;
typedef void wndproc(struct rct_window*, union rct_window_event*);
@ -47,6 +51,8 @@ typedef struct {
int widget_index;
} widget_identifier;
extern widget_identifier gCurrentTextBox;
/**
* Widget structure
* size: 0x10
@ -605,6 +611,11 @@ void textinput_cancel();
void window_move_and_snap(rct_window *w, int newWindowX, int newWindowY, int snapProximity);
int window_can_resize(rct_window *w);
void window_start_textbox(rct_window *call_w, int call_widget, rct_string_id existing_text, uint32 existing_args, int maxLength);
void window_cancel_textbox();
void window_update_textbox_caret();
void window_update_textbox();
#ifdef _MSC_VER
#define window_get_register(w) \
__asm mov w, esi

View File

@ -389,6 +389,7 @@ void platform_process_messages()
gTextInputCursorPosition--;
gTextInputLength--;
console_refresh_caret();
window_update_textbox();
}
if (e.key.keysym.sym == SDLK_END){
gTextInputCursorPosition = gTextInputLength;
@ -403,6 +404,10 @@ void platform_process_messages()
gTextInput[gTextInputMaxLength - 1] = '\0';
gTextInputLength--;
console_refresh_caret();
window_update_textbox();
}
if (e.key.keysym.sym == SDLK_RETURN && gTextInput) {
window_cancel_textbox();
}
if (e.key.keysym.sym == SDLK_LEFT && gTextInput){
if (gTextInputCursorPosition) gTextInputCursorPosition--;
@ -432,7 +437,7 @@ void platform_process_messages()
gTextInputCursorPosition++;
}
window_update_textbox();
}
}
break;
@ -479,6 +484,7 @@ void platform_process_messages()
gTextInputCursorPosition++;
console_refresh_caret();
window_update_textbox();
}
break;
default:

View File

@ -115,7 +115,7 @@ static rct_widget window_editor_object_selection_widgets[] = {
{ WWT_FLATBTN, 1, 391, 504, 46, 159, 0xFFFFFFFF, STR_NONE },
{ WWT_DROPDOWN_BUTTON, 0, 384, 595, 24, 35, STR_INSTALL_NEW_TRACK_DESIGN, STR_INSTALL_NEW_TRACK_DESIGN_TIP },
{ WWT_DROPDOWN_BUTTON, 0, 350, 463, 23, 34, 5261, 5265 },
{ WWT_DROPDOWN_BUTTON, 1, 4, 214, 46, 57, STR_NONE, STR_NONE },
{ WWT_TEXT_BOX, 1, 4, 214, 46, 57, (uint32)_filter_string, STR_NONE },
{ WWT_DROPDOWN_BUTTON, 1, 218, 287, 46, 57, 5277, STR_NONE },
{ WIDGETS_END }
};
@ -130,6 +130,7 @@ static void window_editor_object_selection_close();
static void window_editor_object_selection_mouseup();
static void window_editor_object_selection_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
static void window_editor_object_selection_dropdown();
static void window_editor_object_selection_update(rct_window *w);
static void window_editor_object_selection_scrollgetsize();
static void window_editor_object_selection_scroll_mousedown();
static void window_editor_object_selection_scroll_mouseover();
@ -146,7 +147,7 @@ static void* window_editor_object_selection_events[] = {
(void*)window_editor_object_selection_mousedown,
(void*)window_editor_object_selection_dropdown,
(void*)window_editor_object_selection_emptysub,
(void*)window_editor_object_selection_emptysub,
(void*)window_editor_object_selection_update,
(void*)window_editor_object_selection_emptysub,
(void*)window_editor_object_selection_emptysub,
(void*)window_editor_object_selection_emptysub,
@ -356,7 +357,8 @@ static void window_editor_object_selection_mouseup()
window_loadsave_open(LOADSAVETYPE_LOAD | LOADSAVETYPE_TRACK);
break;
case WIDX_FILTER_STRING_BUTTON:
window_text_input_open(w, widgetIndex, 5275, 5276, 1170, (uint32)_filter_string, 40);
//window_text_input_open(w, widgetIndex, 5275, 5276, 1170, (uint32)_filter_string, 40);
window_start_textbox(w, widgetIndex, 1170, (uint32)_filter_string, 40);
break;
case WIDX_FILTER_CLEAR_BUTTON:
memset(_filter_string, 0, sizeof(_filter_string));
@ -698,7 +700,7 @@ static void window_editor_object_selection_paint()
rct_stex_entry* stex_entry = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, rct_stex_entry*);
gfx_fill_rect_inset(dpi,
/*gfx_fill_rect_inset(dpi,
w->x + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].left,
w->y + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].top,
w->x + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].right,
@ -716,7 +718,7 @@ static void window_editor_object_selection_paint()
w->x + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].left + 1,
w->y + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].top,
w->x + window_editor_object_selection_widgets[WIDX_FILTER_STRING_BUTTON].right
);
);*/
if (w->selected_list_item == -1 || stex_entry == NULL)
return;
@ -1034,6 +1036,15 @@ static void editor_load_selected_objects()
}
}
static void window_editor_object_selection_update(rct_window *w)
{
if (gCurrentTextBox.window.classification == w->classification &&
gCurrentTextBox.window.number == w->number) {
window_update_textbox_caret();
widget_invalidate(w, WIDX_FILTER_STRING_BUTTON);
}
}
static void window_editor_object_selection_textinput()
{
uint8 result;
@ -1045,6 +1056,10 @@ static void window_editor_object_selection_textinput()
if (widgetIndex != WIDX_FILTER_STRING_BUTTON || !result)
return;
if (strcmp(_filter_string, text) == 0)
return;
if (strlen(text) == 0) {
memset(_filter_string, 0, sizeof(_filter_string));
}