summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-10-28 14:14:06 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-10-28 14:14:06 +0200
commita5c03e9464d2c2d2f07aff7d26617c6de6dda5d9 (patch)
tree585ba5940b742e138a4d5f040e79f62b5ccdc1f6 /src
parent0a93ff20b1a855222a158b13071cc48f4f03aba1 (diff)
InputWidget: Buffer contents of unfocused input fields
No need to redraw the text string on every frame.
Diffstat (limited to 'src')
-rw-r--r--src/ui/inputwidget.c80
1 files changed, 57 insertions, 23 deletions
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c
index 0fcca40a..56192e27 100644
--- a/src/ui/inputwidget.c
+++ b/src/ui/inputwidget.c
@@ -69,6 +69,7 @@ struct Impl_InputWidget {
69 iClick click; 69 iClick click;
70 int cursorVis; 70 int cursorVis;
71 uint32_t timer; 71 uint32_t timer;
72 iTextBuf * buffered;
72}; 73};
73 74
74iDefineObjectConstructionArgs(InputWidget, (size_t maxLen), maxLen) 75iDefineObjectConstructionArgs(InputWidget, (size_t maxLen), maxLen)
@@ -108,9 +109,11 @@ void init_InputWidget(iInputWidget *d, size_t maxLen) {
108 init_Click(&d->click, d, SDL_BUTTON_LEFT); 109 init_Click(&d->click, d, SDL_BUTTON_LEFT);
109 d->timer = 0; 110 d->timer = 0;
110 d->cursorVis = 0; 111 d->cursorVis = 0;
112 d->buffered = NULL;
111} 113}
112 114
113void deinit_InputWidget(iInputWidget *d) { 115void deinit_InputWidget(iInputWidget *d) {
116 delete_TextBuf(d->buffered);
114 clearUndo_InputWidget_(d); 117 clearUndo_InputWidget_(d);
115 deinit_Array(&d->undoStack); 118 deinit_Array(&d->undoStack);
116 if (d->timer) { 119 if (d->timer) {
@@ -175,6 +178,36 @@ void setHint_InputWidget(iInputWidget *d, const char *hintText) {
175 setCStr_String(&d->hint, hintText); 178 setCStr_String(&d->hint, hintText);
176} 179}
177 180
181static const iChar sensitiveChar_ = 0x25cf; /* black circle */
182
183static iString *visText_InputWidget_(const iInputWidget *d) {
184 iString *text;
185 if (!d->isSensitive) {
186 text = newUnicodeN_String(constData_Array(&d->text), size_Array(&d->text));
187 }
188 else {
189 text = new_String();
190 for (size_t i = 0; i < size_Array(&d->text); ++i) {
191 appendChar_String(text, sensitiveChar_);
192 }
193 }
194 return text;
195}
196
197static void invalidateBuffered_InputWidget_(iInputWidget *d) {
198 if (d->buffered) {
199 delete_TextBuf(d->buffered);
200 d->buffered = NULL;
201 }
202}
203
204static void updateBuffered_InputWidget_(iInputWidget *d) {
205 invalidateBuffered_InputWidget_(d);
206 iString *visText = visText_InputWidget_(d);
207 d->buffered = new_TextBuf(d->font, cstr_String(visText));
208 delete_String(visText);
209}
210
178void setText_InputWidget(iInputWidget *d, const iString *text) { 211void setText_InputWidget(iInputWidget *d, const iString *text) {
179 clearUndo_InputWidget_(d); 212 clearUndo_InputWidget_(d);
180 clear_Array(&d->text); 213 clear_Array(&d->text);
@@ -189,6 +222,9 @@ void setText_InputWidget(iInputWidget *d, const iString *text) {
189 d->cursor = iMin(d->cursor, size_Array(&d->text)); 222 d->cursor = iMin(d->cursor, size_Array(&d->text));
190 iZap(d->mark); 223 iZap(d->mark);
191 } 224 }
225 if (!isFocused_Widget(d)) {
226 updateBuffered_InputWidget_(d);
227 }
192 refresh_Widget(as_Widget(d)); 228 refresh_Widget(as_Widget(d));
193} 229}
194 230
@@ -221,6 +257,7 @@ void begin_InputWidget(iInputWidget *d) {
221 /* Already active. */ 257 /* Already active. */
222 return; 258 return;
223 } 259 }
260 invalidateBuffered_InputWidget_(d);
224 setFlags_Widget(w, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); 261 setFlags_Widget(w, hidden_WidgetFlag | disabled_WidgetFlag, iFalse);
225 setCopy_Array(&d->oldText, &d->text); 262 setCopy_Array(&d->oldText, &d->text);
226 if (d->mode == overwrite_InputMode) { 263 if (d->mode == overwrite_InputMode) {
@@ -252,6 +289,7 @@ void end_InputWidget(iInputWidget *d, iBool accept) {
252 if (!accept) { 289 if (!accept) {
253 setCopy_Array(&d->text, &d->oldText); 290 setCopy_Array(&d->text, &d->oldText);
254 } 291 }
292 updateBuffered_InputWidget_(d);
255 SDL_RemoveTimer(d->timer); 293 SDL_RemoveTimer(d->timer);
256 d->timer = 0; 294 d->timer = 0;
257 SDL_StopTextInput(); 295 SDL_StopTextInput();
@@ -393,22 +431,6 @@ static size_t skipWord_InputWidget_(const iInputWidget *d, size_t pos, int dir)
393 return pos; 431 return pos;
394} 432}
395 433
396static const iChar sensitiveChar_ = 0x25cf; /* black circle */
397
398static iString *visText_InputWidget_(const iInputWidget *d) {
399 iString *text;
400 if (!d->isSensitive) {
401 text = newUnicodeN_String(constData_Array(&d->text), size_Array(&d->text));
402 }
403 else {
404 text = new_String();
405 for (size_t i = 0; i < size_Array(&d->text); ++i) {
406 appendChar_String(text, sensitiveChar_);
407 }
408 }
409 return text;
410}
411
412iLocalDef iInt2 padding_(void) { 434iLocalDef iInt2 padding_(void) {
413 return init_I2(gap_UI / 2, gap_UI / 2); 435 return init_I2(gap_UI / 2, gap_UI / 2);
414} 436}
@@ -467,6 +489,12 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
467 end_InputWidget(d, iTrue); 489 end_InputWidget(d, iTrue);
468 return iFalse; 490 return iFalse;
469 } 491 }
492 else if (isCommand_UserEvent(ev, "theme.changed")) {
493 if (d->buffered) {
494 updateBuffered_InputWidget_(d);
495 }
496 return iFalse;
497 }
470 switch (processEvent_Click(&d->click, ev)) { 498 switch (processEvent_Click(&d->click, ev)) {
471 case none_ClickResult: 499 case none_ClickResult:
472 break; 500 break;
@@ -715,13 +743,19 @@ static void draw_InputWidget_(const iInputWidget *d) {
715 init_I2(iAbs(m2 - m1), lineHeight_Text(d->font)) }, 743 init_I2(iAbs(m2 - m1), lineHeight_Text(d->font)) },
716 uiMarked_ColorId); 744 uiMarked_ColorId);
717 } 745 }
718 draw_Text(d->font, 746 if (d->buffered && !isFocused && !isHint) {
719 textOrigin, 747 /* Most input widgets will use this, since only one is focused at a time. */
720 isHint ? uiAnnotation_ColorId 748 draw_TextBuf(d->buffered, textOrigin, uiInputText_ColorId);
721 : isFocused && !isEmpty_Array(&d->text) ? uiInputTextFocused_ColorId 749 }
722 : uiInputText_ColorId, 750 else {
723 "%s", 751 draw_Text(d->font,
724 cstr_String(text)); 752 textOrigin,
753 isHint ? uiAnnotation_ColorId
754 : isFocused && !isEmpty_Array(&d->text) ? uiInputTextFocused_ColorId
755 : uiInputText_ColorId,
756 "%s",
757 cstr_String(text));
758 }
725 unsetClip_Paint(&p); 759 unsetClip_Paint(&p);
726 /* Cursor blinking. */ 760 /* Cursor blinking. */
727 if (isFocused && d->cursorVis) { 761 if (isFocused && d->cursorVis) {