mirror of https://github.com/libsdl-org/SDL
testime: draw a blinking cursor at the text insertion point
This commit is contained in:
parent
3d525331aa
commit
50250adba7
|
@ -40,6 +40,8 @@
|
||||||
#endif
|
#endif
|
||||||
#define MAX_TEXT_LENGTH 256
|
#define MAX_TEXT_LENGTH 256
|
||||||
|
|
||||||
|
#define CURSOR_BLINK_INTERVAL_MS 500
|
||||||
|
|
||||||
static SDLTest_CommonState *state;
|
static SDLTest_CommonState *state;
|
||||||
static SDL_FRect textRect, markedRect;
|
static SDL_FRect textRect, markedRect;
|
||||||
static SDL_Color lineColor = { 0, 0, 0, 255 };
|
static SDL_Color lineColor = { 0, 0, 0, 255 };
|
||||||
|
@ -47,6 +49,8 @@ static SDL_Color backColor = { 255, 255, 255, 255 };
|
||||||
static SDL_Color textColor = { 0, 0, 0, 255 };
|
static SDL_Color textColor = { 0, 0, 0, 255 };
|
||||||
static char text[MAX_TEXT_LENGTH], markedText[MAX_TEXT_LENGTH];
|
static char text[MAX_TEXT_LENGTH], markedText[MAX_TEXT_LENGTH];
|
||||||
static int cursor = 0;
|
static int cursor = 0;
|
||||||
|
static SDL_bool cursor_visible;
|
||||||
|
static Uint64 last_cursor_change;
|
||||||
#ifdef HAVE_SDL_TTF
|
#ifdef HAVE_SDL_TTF
|
||||||
static TTF_Font *font;
|
static TTF_Font *font;
|
||||||
#else
|
#else
|
||||||
|
@ -461,18 +465,20 @@ static void CleanupVideo(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _Redraw(int rendererID)
|
static void RedrawWindow(int rendererID)
|
||||||
{
|
{
|
||||||
SDL_Renderer *renderer = state->renderers[rendererID];
|
SDL_Renderer *renderer = state->renderers[rendererID];
|
||||||
SDL_FRect drawnTextRect, cursorRect, underlineRect;
|
SDL_FRect drawnTextRect, cursorRect, underlineRect;
|
||||||
drawnTextRect.x = textRect.x;
|
|
||||||
drawnTextRect.y = 0;
|
|
||||||
drawnTextRect.w = 0;
|
|
||||||
drawnTextRect.h = 0;
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(renderer, backColor.r, backColor.g, backColor.b, backColor.a);
|
SDL_SetRenderDrawColor(renderer, backColor.r, backColor.g, backColor.b, backColor.a);
|
||||||
SDL_RenderFillRect(renderer, &textRect);
|
SDL_RenderFillRect(renderer, &textRect);
|
||||||
|
|
||||||
|
/* Initialize the drawn text rectangle for the cursor */
|
||||||
|
drawnTextRect.x = textRect.x;
|
||||||
|
drawnTextRect.y = textRect.y + (textRect.h - UNIFONT_GLYPH_SIZE * UNIFONT_DRAW_SCALE) / 2;
|
||||||
|
drawnTextRect.w = 0.0f;
|
||||||
|
drawnTextRect.h = UNIFONT_GLYPH_SIZE * UNIFONT_DRAW_SCALE;
|
||||||
|
|
||||||
if (*text) {
|
if (*text) {
|
||||||
#ifdef HAVE_SDL_TTF
|
#ifdef HAVE_SDL_TTF
|
||||||
SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, text, textColor);
|
SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, text, textColor);
|
||||||
|
@ -510,6 +516,7 @@ static void _Redraw(int rendererID)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The marked text rectangle is the text area that hasn't been filled by committed text */
|
||||||
markedRect.x = textRect.x + drawnTextRect.w;
|
markedRect.x = textRect.x + drawnTextRect.w;
|
||||||
markedRect.w = textRect.w - drawnTextRect.w;
|
markedRect.w = textRect.w - drawnTextRect.w;
|
||||||
if (markedRect.w < 0) {
|
if (markedRect.w < 0) {
|
||||||
|
@ -520,16 +527,14 @@ static void _Redraw(int rendererID)
|
||||||
SDL_StartTextInput(state->windows[0]);
|
SDL_StartTextInput(state->windows[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
cursorRect = drawnTextRect;
|
/* Update the drawn text rectangle for composition text, after the committed text */
|
||||||
cursorRect.x += cursorRect.w;
|
|
||||||
cursorRect.w = 2;
|
|
||||||
cursorRect.h = drawnTextRect.h;
|
|
||||||
|
|
||||||
drawnTextRect.x += drawnTextRect.w;
|
drawnTextRect.x += drawnTextRect.w;
|
||||||
drawnTextRect.w = 0;
|
drawnTextRect.w = 0;
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(renderer, backColor.r, backColor.g, backColor.b, backColor.a);
|
/* Set the cursor to the new location, we'll update it as we go, below */
|
||||||
SDL_RenderFillRect(renderer, &markedRect);
|
cursorRect = drawnTextRect;
|
||||||
|
cursorRect.w = 2;
|
||||||
|
cursorRect.h = drawnTextRect.h;
|
||||||
|
|
||||||
if (markedText[0]) {
|
if (markedText[0]) {
|
||||||
#ifdef HAVE_SDL_TTF
|
#ifdef HAVE_SDL_TTF
|
||||||
|
@ -585,10 +590,8 @@ static void _Redraw(int rendererID)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (cursor > 0) {
|
|
||||||
cursorRect.y = drawnTextRect.y;
|
cursorRect.y = drawnTextRect.y;
|
||||||
cursorRect.h = drawnTextRect.h;
|
cursorRect.h = drawnTextRect.h;
|
||||||
}
|
|
||||||
|
|
||||||
underlineRect = markedRect;
|
underlineRect = markedRect;
|
||||||
underlineRect.y = drawnTextRect.y + drawnTextRect.h - 2;
|
underlineRect.y = drawnTextRect.y + drawnTextRect.h - 2;
|
||||||
|
@ -599,16 +602,25 @@ static void _Redraw(int rendererID)
|
||||||
SDL_RenderFillRect(renderer, &underlineRect);
|
SDL_RenderFillRect(renderer, &underlineRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Draw the cursor */
|
||||||
|
Uint64 now = SDL_GetTicks();
|
||||||
|
if ((now - last_cursor_change) >= CURSOR_BLINK_INTERVAL_MS) {
|
||||||
|
cursor_visible = !cursor_visible;
|
||||||
|
last_cursor_change = now;
|
||||||
|
}
|
||||||
|
if (cursor_visible) {
|
||||||
SDL_SetRenderDrawColor(renderer, lineColor.r, lineColor.g, lineColor.b, lineColor.a);
|
SDL_SetRenderDrawColor(renderer, lineColor.r, lineColor.g, lineColor.b, lineColor.a);
|
||||||
SDL_RenderFillRect(renderer, &cursorRect);
|
SDL_RenderFillRect(renderer, &cursorRect);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
SDL_Rect inputrect;
|
SDL_Rect inputrect;
|
||||||
|
|
||||||
inputrect.x = (int)markedRect.x;
|
/* The input rect is a square at the cursor insertion point */
|
||||||
inputrect.y = (int)markedRect.y;
|
inputrect.x = (int)cursorRect.x;
|
||||||
inputrect.w = (int)markedRect.w;
|
inputrect.y = (int)cursorRect.y;
|
||||||
inputrect.h = (int)markedRect.h;
|
inputrect.w = (int)cursorRect.h;
|
||||||
|
inputrect.h = (int)cursorRect.h;
|
||||||
SDL_SetTextInputRect(state->windows[0], &inputrect);
|
SDL_SetTextInputRect(state->windows[0], &inputrect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -625,7 +637,7 @@ static void Redraw(void)
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
/* Sending in the window id to let the font renderers know which one we're working with. */
|
/* Sending in the window id to let the font renderers know which one we're working with. */
|
||||||
_Redraw(i);
|
RedrawWindow(i);
|
||||||
|
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
|
@ -697,7 +709,7 @@ int main(int argc, char *argv[])
|
||||||
SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
|
SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
}
|
}
|
||||||
Redraw();
|
|
||||||
/* Main render loop */
|
/* Main render loop */
|
||||||
done = 0;
|
done = 0;
|
||||||
while (!done) {
|
while (!done) {
|
||||||
|
@ -709,7 +721,6 @@ int main(int argc, char *argv[])
|
||||||
switch (event.key.key) {
|
switch (event.key.key) {
|
||||||
case SDLK_RETURN:
|
case SDLK_RETURN:
|
||||||
text[0] = 0x00;
|
text[0] = 0x00;
|
||||||
Redraw();
|
|
||||||
break;
|
break;
|
||||||
case SDLK_BACKSPACE:
|
case SDLK_BACKSPACE:
|
||||||
/* Only delete text if not in editing mode. */
|
/* Only delete text if not in editing mode. */
|
||||||
|
@ -736,8 +747,6 @@ int main(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
Redraw();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -771,7 +780,6 @@ int main(int argc, char *argv[])
|
||||||
/* After text inputted, we can clear up markedText because it */
|
/* After text inputted, we can clear up markedText because it */
|
||||||
/* is committed */
|
/* is committed */
|
||||||
markedText[0] = 0;
|
markedText[0] = 0;
|
||||||
Redraw();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_EVENT_TEXT_EDITING:
|
case SDL_EVENT_TEXT_EDITING:
|
||||||
|
@ -780,13 +788,14 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
SDL_strlcpy(markedText, event.edit.text, sizeof(markedText));
|
SDL_strlcpy(markedText, event.edit.text, sizeof(markedText));
|
||||||
cursor = event.edit.start;
|
cursor = event.edit.start;
|
||||||
Redraw();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Redraw();
|
||||||
}
|
}
|
||||||
SDL_free(fontname);
|
SDL_free(fontname);
|
||||||
CleanupVideo();
|
CleanupVideo();
|
||||||
|
|
Loading…
Reference in New Issue