mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-04-10 19:15:13 +00:00
Added a blinking cursor to TextEditComponent.
Also fixed a text field sizing bug and made a small padding adjustment.
This commit is contained in:
parent
08790ed1f3
commit
bbaf2739d4
|
@ -10,25 +10,27 @@
|
||||||
|
|
||||||
#include "utils/StringUtil.h"
|
#include "utils/StringUtil.h"
|
||||||
|
|
||||||
#define TEXT_PADDING_HORIZ 10.0f
|
#define TEXT_PADDING_HORIZ 12.0f
|
||||||
#define TEXT_PADDING_VERT 2.0f
|
#define TEXT_PADDING_VERT 2.0f
|
||||||
|
|
||||||
#define CURSOR_REPEAT_START_DELAY 500
|
#define CURSOR_REPEAT_START_DELAY 500
|
||||||
#define CURSOR_REPEAT_SPEED 28 // Lower is faster.
|
#define CURSOR_REPEAT_SPEED 28 // Lower is faster.
|
||||||
|
|
||||||
|
#define BLINKTIME 1000
|
||||||
|
|
||||||
TextEditComponent::TextEditComponent(Window* window)
|
TextEditComponent::TextEditComponent(Window* window)
|
||||||
: GuiComponent(window)
|
: GuiComponent{window}
|
||||||
, mBox(window, ":/graphics/textinput.svg")
|
, mBox{window, ":/graphics/textinput.svg"}
|
||||||
, mFocused(false)
|
, mFocused{false}
|
||||||
, mScrollOffset(0.0f, 0.0f)
|
, mScrollOffset{0.0f, 0.0f}
|
||||||
, mCursor(0)
|
, mCursor{0}
|
||||||
, mEditing(false)
|
, mEditing{false}
|
||||||
, mFont(Font::get(FONT_SIZE_MEDIUM, FONT_PATH_LIGHT))
|
, mFont{Font::get(FONT_SIZE_MEDIUM, FONT_PATH_LIGHT)}
|
||||||
, mCursorRepeatDir(0)
|
, mCursorRepeatDir{0}
|
||||||
|
, mBlinkTime{0}
|
||||||
{
|
{
|
||||||
addChild(&mBox);
|
addChild(&mBox);
|
||||||
onFocusLost();
|
onFocusLost();
|
||||||
mResolutionAdjustment = -(34.0f * Renderer::getScreenWidthModifier() - 34.0f);
|
|
||||||
setSize(4096, mFont->getHeight() + (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier()));
|
setSize(4096, mFont->getHeight() + (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +38,7 @@ void TextEditComponent::onFocusGained()
|
||||||
{
|
{
|
||||||
mFocused = true;
|
mFocused = true;
|
||||||
mBox.setImagePath(":/graphics/textinput_focused.svg");
|
mBox.setImagePath(":/graphics/textinput_focused.svg");
|
||||||
|
startEditing();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditComponent::onFocusLost()
|
void TextEditComponent::onFocusLost()
|
||||||
|
@ -46,9 +49,9 @@ void TextEditComponent::onFocusLost()
|
||||||
|
|
||||||
void TextEditComponent::onSizeChanged()
|
void TextEditComponent::onSizeChanged()
|
||||||
{
|
{
|
||||||
mBox.fitTo(mSize, glm::vec3{},
|
mBox.fitTo(
|
||||||
glm::vec2{-34.0f + mResolutionAdjustment,
|
mSize, glm::vec3{},
|
||||||
-32.0f - (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier())});
|
glm::vec2{-34.0f, -32.0f - (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier())});
|
||||||
onTextChanged(); // Wrap point probably changed.
|
onTextChanged(); // Wrap point probably changed.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +65,7 @@ void TextEditComponent::setValue(const std::string& val)
|
||||||
void TextEditComponent::textInput(const std::string& text)
|
void TextEditComponent::textInput(const std::string& text)
|
||||||
{
|
{
|
||||||
if (mEditing) {
|
if (mEditing) {
|
||||||
|
mBlinkTime = 0;
|
||||||
mCursorRepeatDir = 0;
|
mCursorRepeatDir = 0;
|
||||||
if (text[0] == '\b') {
|
if (text[0] == '\b') {
|
||||||
if (mCursor > 0) {
|
if (mCursor > 0) {
|
||||||
|
@ -82,17 +86,17 @@ void TextEditComponent::textInput(const std::string& text)
|
||||||
|
|
||||||
void TextEditComponent::startEditing()
|
void TextEditComponent::startEditing()
|
||||||
{
|
{
|
||||||
if (!isMultiline())
|
|
||||||
setCursor(mText.size());
|
|
||||||
SDL_StartTextInput();
|
SDL_StartTextInput();
|
||||||
mEditing = true;
|
mEditing = true;
|
||||||
updateHelpPrompts();
|
updateHelpPrompts();
|
||||||
|
mBlinkTime = BLINKTIME / 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditComponent::stopEditing()
|
void TextEditComponent::stopEditing()
|
||||||
{
|
{
|
||||||
SDL_StopTextInput();
|
SDL_StopTextInput();
|
||||||
mEditing = false;
|
mEditing = false;
|
||||||
|
mCursorRepeatDir = 0;
|
||||||
updateHelpPrompts();
|
updateHelpPrompts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,41 +145,33 @@ bool TextEditComponent::input(InputConfig* config, Input input)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Done editing (accept changes).
|
if (cursor_left || cursor_right) {
|
||||||
if ((config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_ESCAPE) ||
|
mBlinkTime = 0;
|
||||||
(config->getDeviceId() != DEVICE_KEYBOARD &&
|
|
||||||
(config->isMappedTo("a", input) || config->isMappedTo("b", input)))) {
|
|
||||||
mTextOrig = mText;
|
|
||||||
stopEditing();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (cursor_left || cursor_right) {
|
|
||||||
mCursorRepeatDir = cursor_left ? -1 : 1;
|
mCursorRepeatDir = cursor_left ? -1 : 1;
|
||||||
mCursorRepeatTimer = -(CURSOR_REPEAT_START_DELAY - CURSOR_REPEAT_SPEED);
|
mCursorRepeatTimer = -(CURSOR_REPEAT_START_DELAY - CURSOR_REPEAT_SPEED);
|
||||||
moveCursor(mCursorRepeatDir);
|
moveCursor(mCursorRepeatDir);
|
||||||
}
|
}
|
||||||
else if (cursor_up) {
|
// Stop editing and let the button down event be captured by the parent component.
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
else if (cursor_down) {
|
else if (cursor_down) {
|
||||||
// TODO
|
stopEditing();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else if (shoulder_left || shoulder_right) {
|
else if (shoulder_left || shoulder_right) {
|
||||||
|
mBlinkTime = 0;
|
||||||
mCursorRepeatDir = shoulder_left ? -10 : 10;
|
mCursorRepeatDir = shoulder_left ? -10 : 10;
|
||||||
mCursorRepeatTimer = -(CURSOR_REPEAT_START_DELAY - CURSOR_REPEAT_SPEED);
|
mCursorRepeatTimer = -(CURSOR_REPEAT_START_DELAY - CURSOR_REPEAT_SPEED);
|
||||||
moveCursor(mCursorRepeatDir);
|
moveCursor(mCursorRepeatDir);
|
||||||
}
|
}
|
||||||
// Jump to beginning of text.
|
// Jump to beginning of text.
|
||||||
else if (trigger_left) {
|
else if (trigger_left) {
|
||||||
|
mBlinkTime = 0;
|
||||||
setCursor(0);
|
setCursor(0);
|
||||||
}
|
}
|
||||||
// Jump to end of text.
|
// Jump to end of text.
|
||||||
else if (trigger_right) {
|
else if (trigger_right) {
|
||||||
|
mBlinkTime = 0;
|
||||||
setCursor(mText.length());
|
setCursor(mText.length());
|
||||||
}
|
}
|
||||||
else if (config->getDeviceId() != DEVICE_KEYBOARD && config->isMappedTo("y", input)) {
|
|
||||||
textInput("\b");
|
|
||||||
}
|
|
||||||
else if (config->getDeviceId() == DEVICE_KEYBOARD) {
|
else if (config->getDeviceId() == DEVICE_KEYBOARD) {
|
||||||
switch (input.id) {
|
switch (input.id) {
|
||||||
case SDLK_HOME: {
|
case SDLK_HOME: {
|
||||||
|
@ -207,6 +203,10 @@ void TextEditComponent::update(int deltaTime)
|
||||||
{
|
{
|
||||||
updateCursorRepeat(deltaTime);
|
updateCursorRepeat(deltaTime);
|
||||||
GuiComponent::update(deltaTime);
|
GuiComponent::update(deltaTime);
|
||||||
|
|
||||||
|
mBlinkTime += deltaTime;
|
||||||
|
if (mBlinkTime >= BLINKTIME)
|
||||||
|
mBlinkTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditComponent::updateCursorRepeat(int deltaTime)
|
void TextEditComponent::updateCursorRepeat(int deltaTime)
|
||||||
|
@ -216,6 +216,7 @@ void TextEditComponent::updateCursorRepeat(int deltaTime)
|
||||||
|
|
||||||
mCursorRepeatTimer += deltaTime;
|
mCursorRepeatTimer += deltaTime;
|
||||||
while (mCursorRepeatTimer >= CURSOR_REPEAT_SPEED) {
|
while (mCursorRepeatTimer >= CURSOR_REPEAT_SPEED) {
|
||||||
|
mBlinkTime = 0;
|
||||||
moveCursor(mCursorRepeatDir);
|
moveCursor(mCursorRepeatDir);
|
||||||
mCursorRepeatTimer -= CURSOR_REPEAT_SPEED;
|
mCursorRepeatTimer -= CURSOR_REPEAT_SPEED;
|
||||||
}
|
}
|
||||||
|
@ -298,7 +299,6 @@ void TextEditComponent::render(const glm::mat4& parentTrans)
|
||||||
Renderer::popClipRect();
|
Renderer::popClipRect();
|
||||||
|
|
||||||
// Draw cursor.
|
// Draw cursor.
|
||||||
if (mEditing) {
|
|
||||||
glm::vec2 cursorPos;
|
glm::vec2 cursorPos;
|
||||||
if (isMultiline()) {
|
if (isMultiline()) {
|
||||||
cursorPos = mFont->getWrappedTextCursorOffset(mText, getTextAreaSize().x, mCursor);
|
cursorPos = mFont->getWrappedTextCursorOffset(mText, getTextAreaSize().x, mCursor);
|
||||||
|
@ -309,23 +309,29 @@ void TextEditComponent::render(const glm::mat4& parentTrans)
|
||||||
}
|
}
|
||||||
|
|
||||||
float cursorHeight = mFont->getHeight() * 0.8f;
|
float cursorHeight = mFont->getHeight() * 0.8f;
|
||||||
|
|
||||||
|
if (!mEditing) {
|
||||||
Renderer::drawRect(cursorPos.x, cursorPos.y + (mFont->getHeight() - cursorHeight) / 2.0f,
|
Renderer::drawRect(cursorPos.x, cursorPos.y + (mFont->getHeight() - cursorHeight) / 2.0f,
|
||||||
2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0x000000FF,
|
2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0xC7C7C7FF,
|
||||||
0x000000FF);
|
0xC7C7C7FF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mEditing && mBlinkTime < BLINKTIME / 2) {
|
||||||
|
Renderer::drawRect(cursorPos.x, cursorPos.y + (mFont->getHeight() - cursorHeight) / 2.0f,
|
||||||
|
2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0x777777FF,
|
||||||
|
0x777777FF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec2 TextEditComponent::getTextAreaPos() const
|
glm::vec2 TextEditComponent::getTextAreaPos() const
|
||||||
{
|
{
|
||||||
return glm::vec2{
|
return glm::vec2{(TEXT_PADDING_HORIZ * Renderer::getScreenWidthModifier()) / 2.0f,
|
||||||
(-mResolutionAdjustment + (TEXT_PADDING_HORIZ * Renderer::getScreenWidthModifier())) / 2.0f,
|
|
||||||
(TEXT_PADDING_VERT * Renderer::getScreenHeightModifier()) / 2.0f};
|
(TEXT_PADDING_VERT * Renderer::getScreenHeightModifier()) / 2.0f};
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec2 TextEditComponent::getTextAreaSize() const
|
glm::vec2 TextEditComponent::getTextAreaSize() const
|
||||||
{
|
{
|
||||||
return glm::vec2{mSize.x + mResolutionAdjustment -
|
return glm::vec2{mSize.x - (TEXT_PADDING_HORIZ * Renderer::getScreenWidthModifier()),
|
||||||
(TEXT_PADDING_HORIZ * Renderer::getScreenWidthModifier()),
|
|
||||||
mSize.y - (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier())};
|
mSize.y - (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier())};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,10 +339,10 @@ std::vector<HelpPrompt> TextEditComponent::getHelpPrompts()
|
||||||
{
|
{
|
||||||
std::vector<HelpPrompt> prompts;
|
std::vector<HelpPrompt> prompts;
|
||||||
if (mEditing) {
|
if (mEditing) {
|
||||||
prompts.push_back(HelpPrompt("up/down/left/right", "move cursor"));
|
prompts.push_back(HelpPrompt("lt", "first"));
|
||||||
prompts.push_back(HelpPrompt("y", "backspace"));
|
prompts.push_back(HelpPrompt("rt", "last"));
|
||||||
prompts.push_back(HelpPrompt("a", "accept changes"));
|
prompts.push_back(HelpPrompt("left/right", "move cursor"));
|
||||||
prompts.push_back(HelpPrompt("b", "accept changes"));
|
prompts.push_back(HelpPrompt("b", "back"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
prompts.push_back(HelpPrompt("a", "edit"));
|
prompts.push_back(HelpPrompt("a", "edit"));
|
||||||
|
|
|
@ -61,6 +61,7 @@ private:
|
||||||
bool mFocused;
|
bool mFocused;
|
||||||
bool mEditing;
|
bool mEditing;
|
||||||
unsigned int mCursor; // Cursor position in characters.
|
unsigned int mCursor; // Cursor position in characters.
|
||||||
|
int mBlinkTime;
|
||||||
|
|
||||||
int mCursorRepeatTimer;
|
int mCursorRepeatTimer;
|
||||||
int mCursorRepeatDir;
|
int mCursorRepeatDir;
|
||||||
|
@ -68,7 +69,6 @@ private:
|
||||||
glm::vec2 mScrollOffset;
|
glm::vec2 mScrollOffset;
|
||||||
|
|
||||||
NinePatchComponent mBox;
|
NinePatchComponent mBox;
|
||||||
float mResolutionAdjustment;
|
|
||||||
|
|
||||||
std::shared_ptr<Font> mFont;
|
std::shared_ptr<Font> mFont;
|
||||||
std::unique_ptr<TextCache> mTextCache;
|
std::unique_ptr<TextCache> mTextCache;
|
||||||
|
|
Loading…
Reference in a new issue