diff --git a/src/pc/djui/djui_inputbox.c b/src/pc/djui/djui_inputbox.c index 9006da3c..76a62a18 100644 --- a/src/pc/djui/djui_inputbox.c +++ b/src/pc/djui/djui_inputbox.c @@ -15,6 +15,20 @@ static u8 sHeldShift = 0; static u8 sHeldControl = 0; static u8 sCursorBlink = 0; +static void djui_inputbox_on_change(struct DjuiInputbox* inputbox) { + struct DjuiBase* base = &inputbox->base; + if (base != NULL && base->interactable != NULL && base->interactable->on_value_change != NULL) { + base->interactable->on_value_change(base); + } +} + +void djui_inputbox_set_text_color(struct DjuiInputbox* inputbox, u8 r, u8 g, u8 b, u8 a) { + inputbox->textColor.r = r; + inputbox->textColor.g = g; + inputbox->textColor.b = b; + inputbox->textColor.a = a; +} + void djui_inputbox_set_text(struct DjuiInputbox* inputbox, char* text) { snprintf(inputbox->buffer, inputbox->bufferSize, "%s", text); } @@ -130,6 +144,7 @@ static void djui_inputbox_delete_selection(struct DjuiInputbox *inputbox) { sel[0] = s1; sel[1] = s1; } + djui_inputbox_on_change(inputbox); } static bool djui_inputbox_on_key_down(struct DjuiBase *base, int scancode) { @@ -316,6 +331,7 @@ static void djui_inputbox_on_text_input(struct DjuiBase *base, char* text) { inputbox->selection[0] += strlen(text); inputbox->selection[1] = inputbox->selection[0]; sCursorBlink = 0; + djui_inputbox_on_change(inputbox); } static void djui_inputbox_render_char(struct DjuiInputbox* inputbox, char c, f32* drawX, f32* additionalShift) { @@ -447,7 +463,7 @@ static void djui_inputbox_render(struct DjuiBase* base) { gSPDisplayList(gDisplayListHead++, font->textBeginDisplayList); // set color - gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 255); + gDPSetEnvColor(gDisplayListHead++, inputbox->textColor.r, inputbox->textColor.g, inputbox->textColor.b, inputbox->textColor.a); // make selection well formed u16 selection[2] = { 0 }; @@ -468,7 +484,7 @@ static void djui_inputbox_render(struct DjuiBase* base) { if (insideSelection && !wasInsideSelection) { gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); } else if (!insideSelection && wasInsideSelection) { - gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 255); + gDPSetEnvColor(gDisplayListHead++, inputbox->textColor.r, inputbox->textColor.g, inputbox->textColor.b, inputbox->textColor.a); } wasInsideSelection = insideSelection; } @@ -498,6 +514,7 @@ struct DjuiInputbox* djui_inputbox_create(struct DjuiBase* parent, u16 bufferSiz djui_base_init(parent, base, djui_inputbox_render, djui_inputbox_destroy); djui_base_set_size(base, 200, 32); djui_base_set_border_width(base, 2); + djui_inputbox_set_text_color(inputbox, 0, 0, 0, 255); djui_interactable_create(base); djui_interactable_hook_hover(base, djui_inputbox_on_hover, djui_inputbox_on_hover_end); djui_interactable_hook_cursor_down(base, djui_inputbox_on_cursor_down_begin, djui_inputbox_on_cursor_down, djui_inputbox_on_cursor_down_end); diff --git a/src/pc/djui/djui_inputbox.h b/src/pc/djui/djui_inputbox.h index c85b05d8..3556fbc7 100644 --- a/src/pc/djui/djui_inputbox.h +++ b/src/pc/djui/djui_inputbox.h @@ -8,9 +8,11 @@ struct DjuiInputbox { u16 bufferSize; u16 selection[2]; f32 viewX; + struct DjuiColor textColor; void (*on_enter_press)(void); }; +void djui_inputbox_set_text_color(struct DjuiInputbox* inputbox, u8 r, u8 g, u8 b, u8 a); void djui_inputbox_set_text(struct DjuiInputbox* inputbox, char* text); void djui_inputbox_select_all(struct DjuiInputbox* inputbox); void djui_inputbox_hook_enter_press(struct DjuiInputbox* inputbox, void (*on_enter_press)(void)); diff --git a/src/pc/djui/djui_panel_join.c b/src/pc/djui/djui_panel_join.c index 3c45adeb..1dbc8f1d 100644 --- a/src/pc/djui/djui_panel_join.c +++ b/src/pc/djui/djui_panel_join.c @@ -1,3 +1,4 @@ +#include #include "djui.h" #include "src/pc/network/network.h" #include "src/pc/utils/misc.h" @@ -15,7 +16,132 @@ static char* sJoiningDirect = "\ Enter \\#d0d0ff\\direct connection\\#c8c8c8\\ IP and port:\ "; +static struct DjuiInputbox* sInputboxIp = NULL; + +static bool djui_panel_join_ip_parse_numbers(char** msg) { + int num = 0; + for (int i = 0; i < 3; i++) { + char c = **msg; + if (c >= '0' && c <= '9') { + // is number + num *= 10; + num += (c - '0'); + *msg = *msg + 1; + } else if (i == 0) { + return false; + } else { + break; + } + } + + return num >= 0 && num <= 127; +} + +static bool djui_panel_join_ip_parse_period(char** msg) { + char c = **msg; + bool isPeriod = (c == '.'); + if (isPeriod) { *msg = *msg + 1; } + return isPeriod; +} + +static bool djui_panel_join_ip_parse_spacer(char** msg) { + char c = **msg; + bool isSpacer = (c == ':' || c == ' '); + if (isSpacer) { *msg = *msg + 1; } + return isSpacer; +} + +static bool djui_panel_join_ip_parse_port(char** msg) { + int num = 0; + for (int i = 0; i < 5; i++) { + char c = **msg; + if (c >= '0' && c <= '9') { + // is number + num *= 10; + num += (c - '0'); + *msg = *msg + 1; + } else if (i == 0) { + return false; + } else { + break; + } + } + + return num >= 1 && num <= 65535; +} + +static bool djui_panel_join_ip_valid(char* buffer) { + char** msg = &buffer; + if (!djui_panel_join_ip_parse_numbers(msg)) { return false; } + if (!djui_panel_join_ip_parse_period(msg)) { return false; } + if (!djui_panel_join_ip_parse_numbers(msg)) { return false; } + if (!djui_panel_join_ip_parse_period(msg)) { return false; } + if (!djui_panel_join_ip_parse_numbers(msg)) { return false; } + if (!djui_panel_join_ip_parse_period(msg)) { return false; } + if (!djui_panel_join_ip_parse_numbers(msg)) { return false; } + if (djui_panel_join_ip_parse_spacer(msg)) { + if (!djui_panel_join_ip_parse_port(msg)) { return false; } + } + + return (**msg == '\0'); +} + +static void djui_panel_join_ip_text_change(struct DjuiBase* caller) { + struct DjuiInputbox* inputbox1 = (struct DjuiInputbox*)caller; + if (djui_panel_join_ip_valid(inputbox1->buffer)) { + djui_inputbox_set_text_color(inputbox1, 0, 0, 0, 255); + } else { + djui_inputbox_set_text_color(inputbox1, 255, 0, 0, 255); + } +} + +static void djui_panel_join_ip_text_set_new(void) { + char buffer[256] = { 0 }; + snprintf(buffer, 256, "%s", sInputboxIp->buffer); + + bool afterSpacer = false; + int port = 0; + for (int i = 0; i < 256; i++) { + if (buffer[i] == ' ' || buffer[i] == ':') { + buffer[i] = '\0'; + afterSpacer = true; + } else if (buffer[i] == '\0') { + break; + } else if (afterSpacer && buffer[i] >= '0' && buffer[i] <= '9') { + port *= 10; + port += buffer[i] - '0'; + } + } + + snprintf(configJoinIp, MAX_CONFIG_STRING, "%s", buffer); + if (port >= 1 && port <= 65535) { + configJoinPort = port; + } else { + configJoinPort = DEFAULT_PORT; + } +} + +static void djui_panel_join_ip_text_set(struct DjuiInputbox* inputbox1) { + char buffer[256] = { 0 }; + if (strlen(configJoinIp) > 0 && configJoinPort != DEFAULT_PORT) { + snprintf(buffer, 256, "%s:%d", configJoinIp, configJoinPort); + } else if (strlen(configJoinIp) > 0) { + snprintf(buffer, 256, "%s", configJoinIp); + } else { + snprintf(buffer, 256, "127.0.0.1"); + } + + djui_inputbox_set_text(inputbox1, buffer); + djui_inputbox_select_all(inputbox1); +} + void djui_panel_join_do_join(struct DjuiBase* caller) { + if (!djui_panel_join_ip_valid(sInputboxIp->buffer)) { + djui_interactable_set_input_focus(&sInputboxIp->base); + djui_inputbox_select_all(sInputboxIp); + return; + } + djui_panel_join_ip_text_set_new(); network_set_system(NS_SOCKET); network_init(NT_CLIENT); djui_panel_join_message_create(caller); @@ -57,8 +183,9 @@ void djui_panel_join_create(struct DjuiBase* caller) { struct DjuiInputbox* inputbox1 = djui_inputbox_create(&body->base, 256); djui_base_set_size_type(&inputbox1->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); djui_base_set_size(&inputbox1->base, 1.0f, 32.0f); - djui_inputbox_set_text(inputbox1, configJoinIp); - djui_inputbox_select_all(inputbox1); + djui_interactable_hook_value_change(&inputbox1->base, djui_panel_join_ip_text_change); + sInputboxIp = inputbox1; + djui_panel_join_ip_text_set(inputbox1); struct DjuiRect* rect2 = djui_rect_create(&body->base); djui_base_set_size_type(&rect2->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);