/** * @brief Called when we press a key when the node got the focus * @return True, if we use the event */ bool uiTextEntryNode::onKeyPressed (uiNode_t* node, unsigned int key, unsigned short unicode) { switch (key) { /* remove the last char. */ case K_BACKSPACE: UI_TextEntryNodeEdit(node, K_BACKSPACE); return true; /* cancel the edition */ case K_ESCAPE: isAborted = true; UI_RemoveFocus(); return true; /* validate the edition */ case K_ENTER: case K_KP_ENTER: UI_TextEntryNodeValidateEdition(node); UI_RemoveFocus(); return true; case K_LEFTARROW: case K_KP_LEFTARROW: if (EXTRADATA(node).cursorPosition > 0) EXTRADATA(node).cursorPosition--; return true; case K_RIGHTARROW: case K_KP_RIGHTARROW: if (EXTRADATA(node).cursorPosition < UTF8_strlen(editedCvar->string)) EXTRADATA(node).cursorPosition++; return true; case K_HOME: case K_KP_HOME: EXTRADATA(node).cursorPosition = 0; return true; case K_END: case K_KP_END: EXTRADATA(node).cursorPosition = UTF8_strlen(editedCvar->string); return true; case K_DEL: case K_KP_DEL: UI_TextEntryNodeEdit(node, K_DEL); return true; } /* non printable */ if (unicode < 32 || (unicode >= 127 && unicode < 192)) return false; /* add a char. */ UI_TextEntryNodeEdit(node, unicode); return true; }
void uiTextEntryNode::draw (uiNode_t* node) { const float* textColor; vec2_t pos; const char* font = UI_GetFontFromNode(node); uiSpriteStatus_t iconStatus = SPRITE_STATUS_NORMAL; if (node->disabled) { textColor = node->disabledColor; iconStatus = SPRITE_STATUS_DISABLED; } else if (node->state) { textColor = node->color; iconStatus = SPRITE_STATUS_HOVER; } else { textColor = node->color; } if (UI_HasFocus(node)) { textColor = node->selectedColor; } UI_GetNodeAbsPos(node, pos); if (EXTRADATA(node).background) { UI_DrawSpriteInBox(false, EXTRADATA(node).background, iconStatus, pos[0], pos[1], node->box.size[0], node->box.size[1]); } if (char const* const text = UI_GetReferenceString(node, node->text)) { char buf[MAX_VAR]; if (EXTRADATA(node).isPassword) { size_t size = UTF8_strlen(text); if (size > MAX_VAR - 2) size = MAX_VAR - 2; memset(buf, HIDECHAR, size); buf[size] = '\0'; } else { /* leave one byte empty for the text-based cursor */ UTF8_strncpyz(buf, text, sizeof(buf) - 1); } /** @todo Make the cursor into a real graphical object instead of using a text character. */ if (UI_HasFocus(node)) { if (CL_Milliseconds() % 1000 < 500) { UTF8_insert_char_at(buf, sizeof(buf), EXTRADATA(node).cursorPosition, (int)CURSOR_ON); } else { UTF8_insert_char_at(buf, sizeof(buf), EXTRADATA(node).cursorPosition, (int)CURSOR_OFF); } } if (*buf != '\0') { R_Color(textColor); UI_DrawStringInBox(font, (align_t)node->contentAlign, pos[0] + node->padding, pos[1] + node->padding, node->box.size[0] - node->padding - node->padding, node->box.size[1] - node->padding - node->padding, buf); R_Color(nullptr); } } }
/** * @brief edit the current cvar with a char */ static void UI_TextEntryNodeEdit (uiNode_t* node, unsigned int unicode) { char buffer[MAX_CVAR_EDITING_LENGTH]; /* copy the cvar */ Q_strncpyz(buffer, editedCvar->string, sizeof(buffer)); /* compute result */ if (unicode == K_BACKSPACE) { if (EXTRADATA(node).cursorPosition > 0){ UTF8_delete_char_at(buffer, EXTRADATA(node).cursorPosition - 1); EXTRADATA(node).cursorPosition--; } } else if (unicode == K_DEL) { if (EXTRADATA(node).cursorPosition < UTF8_strlen(editedCvar->string)){ UTF8_delete_char_at(buffer, EXTRADATA(node).cursorPosition); } } else { int length = strlen(buffer); int charLength = UTF8_encoded_len(unicode); /* is buffer full? */ if (length + charLength >= sizeof(buffer)) return; int insertedLength = UTF8_insert_char_at(buffer, sizeof(buffer), EXTRADATA(node).cursorPosition, unicode); if (insertedLength > 0) EXTRADATA(node).cursorPosition++; } /* update the cvar */ Cvar_ForceSet(editedCvar->name, buffer); }
/** * @brief Called when the node got the focus */ void uiTextEntryNode::onFocusGained (uiNode_t* node) { assert(editedCvar == nullptr); /* skip '*cvar ' */ const char* cvarRef = "*cvar:"; editedCvar = Cvar_Get(&((const char*)node->text)[strlen(cvarRef)]); assert(editedCvar); Q_strncpyz(cvarValueBackup, editedCvar->string, sizeof(cvarValueBackup)); isAborted = false; EXTRADATA(node).cursorPosition = UTF8_strlen(editedCvar->string); #if SDL_VERSION_ATLEAST(2,0,0) SDL_StartTextInput(); vec2_t pos; UI_GetNodeAbsPos(node, pos); SDL_Rect r = {static_cast<int>(pos[0]), static_cast<int>(pos[1]), static_cast<int>(node->box.size[0]), static_cast<int>(node->box.size[1])}; SDL_SetTextInputRect(&r); #else #ifdef ANDROID char buf[MAX_CVAR_EDITING_LENGTH]; Q_strncpyz(buf, editedCvar->string, sizeof(buf)); SDL_ANDROID_GetScreenKeyboardTextInput(buf, sizeof(buf)); Cvar_ForceSet(editedCvar->name, buf); UI_TextEntryNodeValidateEdition(node); UI_RemoveFocus(); #endif #endif }
static void UI_TextEntryNodeDraw (uiNode_t *node) { static const int panelTemplate[] = { CORNER_SIZE, MID_SIZE, CORNER_SIZE, CORNER_SIZE, MID_SIZE, CORNER_SIZE, MARGE }; const char *text; int texX, texY; const float *textColor; const char *image; vec2_t pos; static vec4_t disabledColor = {0.5, 0.5, 0.5, 1.0}; const char *font = UI_GetFontFromNode(node); if (node->disabled) { /** @todo need custom color when node is disabled */ textColor = disabledColor; texX = TILE_SIZE; texY = TILE_SIZE; } else if (node->state) { textColor = node->color; texX = TILE_SIZE; texY = 0; } else { textColor = node->color; texX = 0; texY = 0; } if (UI_HasFocus(node)) textColor = node->selectedColor; UI_GetNodeAbsPos(node, pos); image = UI_GetReferenceString(node, node->image); if (image) UI_DrawPanel(pos, node->size, image, texX, texY, panelTemplate); text = UI_GetReferenceString(node, node->text); if (text != NULL) { /** @todo we don't need to edit the text to draw the cursor */ if (UI_HasFocus(node)) { if (CL_Milliseconds() % 1000 < 500) { text = va("%s%c", text, CURSOR); } } if (EXTRADATA(node).isPassword) { char *c = va("%s", text); int size = UTF8_strlen(c); text = c; /* hide the text with a special char */ assert(strlen(c) >= size); /* trustable, but it can't be false */ while (size) { *c++ = HIDECHAR; size--; } /* readd the cursor */ if (UI_HasFocus(node)) { if (CL_Milliseconds() % 1000 < 500) { c--; *c++ = CURSOR; } } *c = '\0'; } if (*text != '\0') { R_Color(textColor); UI_DrawStringInBox(font, node->textalign, pos[0] + node->padding, pos[1] + node->padding, node->size[0] - node->padding - node->padding, node->size[1] - node->padding - node->padding, text, LONGLINES_PRETTYCHOP); R_Color(NULL); } } }