@@ -11,7 +11,9 @@ namespace gui
11
11
TextBox::TextBox (float width):
12
12
m_box (Box::Input),
13
13
m_cursorPos (0 ),
14
- m_maxLength (256 )
14
+ m_maxLength (256 ),
15
+ m_selectionFirst (0 ),
16
+ m_selectionLast (0 )
15
17
{
16
18
m_box.setSize (width, Theme::getBoxHeight ());
17
19
@@ -74,6 +76,8 @@ void TextBox::setCursor(size_t index)
74
76
if (index <= m_text.getString ().getSize ())
75
77
{
76
78
m_cursorPos = index ;
79
+ m_selectionFirst = index ;
80
+ m_selectionLast = index ;
77
81
78
82
float padding = Theme::borderSize + Theme::PADDING;
79
83
m_cursor.setPosition (m_text.findCharacterPos (index ).x , padding);
@@ -123,11 +127,59 @@ void TextBox::onKeyPressed(const sf::Event::KeyEvent& key)
123
127
switch (key.code )
124
128
{
125
129
case sf::Keyboard::Left:
126
- setCursor (m_cursorPos - 1 );
130
+ if (key.shift )
131
+ {
132
+ if (m_cursorPos == m_selectionLast)
133
+ {
134
+ // Extend selection to left
135
+ if (m_selectionFirst > 0 )
136
+ setSelectedText (m_selectionFirst - 1 , m_selectionLast);
137
+ }
138
+ else
139
+ {
140
+ // Shrink selection to right
141
+ setSelectedText (m_selectionFirst, m_selectionLast - 1 );
142
+ }
143
+ }
144
+ else if (m_selectedText.isEmpty ())
145
+ {
146
+ // Move cursor to the left
147
+ setCursor (m_cursorPos - 1 );
148
+ }
149
+ else
150
+ {
151
+ // Clear selection, move cursor to the left
152
+ setCursor (m_selectionFirst);
153
+ clearSelectedText ();
154
+ }
127
155
break ;
128
156
129
157
case sf::Keyboard::Right:
130
- setCursor (m_cursorPos + 1 );
158
+ if (key.shift )
159
+ {
160
+ if (m_cursorPos == m_selectionFirst)
161
+ {
162
+ // Extend selection to right
163
+ if (m_selectionLast < m_text.getString ().getSize ())
164
+ setSelectedText (m_selectionFirst, m_selectionLast + 1 );
165
+ }
166
+ else
167
+ {
168
+ // Shrink selection to left
169
+ setSelectedText (m_selectionFirst + 1 , m_selectionLast);
170
+ }
171
+ }
172
+ else if (m_selectedText.isEmpty ())
173
+ {
174
+ // Move cursor to the right
175
+ setCursor (m_cursorPos + 1 );
176
+ }
177
+ else
178
+ {
179
+ // Clear selection, move cursor to the right
180
+ setCursor (m_selectionLast);
181
+ clearSelectedText ();
182
+ }
131
183
break ;
132
184
133
185
case sf::Keyboard::BackSpace:
@@ -165,11 +217,27 @@ void TextBox::onKeyPressed(const sf::Event::KeyEvent& key)
165
217
break ;
166
218
167
219
case sf::Keyboard::Home:
168
- setCursor (0 );
220
+ if (key.shift )
221
+ {
222
+ // Shift+Home: select from start to cursor
223
+ setSelectedText (0 , m_cursorPos);
224
+ }
225
+ else
226
+ {
227
+ setCursor (0 );
228
+ }
169
229
break ;
170
230
171
231
case sf::Keyboard::End:
172
- setCursor (m_text.getString ().getSize ());
232
+ if (key.shift )
233
+ {
234
+ // Shift+End: select from cursor to end
235
+ setSelectedText (m_cursorPos, m_text.getString ().getSize ());
236
+ }
237
+ else
238
+ {
239
+ setCursor (m_text.getString ().getSize ());
240
+ }
173
241
break ;
174
242
175
243
case sf::Keyboard::Return:
@@ -269,7 +337,6 @@ void TextBox::onMouseReleased(float x, float)
269
337
if (glyphPos.x <= x)
270
338
{
271
339
setSelectedText (m_cursorPos, i);
272
- setCursor (i);
273
340
break ;
274
341
}
275
342
}
@@ -319,7 +386,7 @@ void TextBox::onStateChanged(State state)
319
386
// Discard selection when focus is lost
320
387
if (state != State::StateFocused)
321
388
{
322
- setSelectedText ( 0 , 0 );
389
+ clearSelectedText ( );
323
390
}
324
391
}
325
392
@@ -356,8 +423,8 @@ void TextBox::draw(sf::RenderTarget& target, sf::RenderStates states) const
356
423
357
424
glDisable (GL_SCISSOR_TEST);
358
425
359
- // Show cursor if focused
360
- if (isFocused ())
426
+ // Show cursor if focused and no selection
427
+ if (isFocused () && m_selectedText. isEmpty () )
361
428
{
362
429
// Make it blink
363
430
float timer = m_cursorTimer.getElapsedTime ().asSeconds ();
@@ -378,17 +445,29 @@ void TextBox::setSelectedText(size_t from, size_t to)
378
445
{
379
446
if (from != to)
380
447
{
381
- m_selectionLast = std::max (from, to);
382
- m_selectionFirst = std::min (from, to);
383
- m_selectedText = m_text.getString ().substring (m_selectionFirst, m_selectionLast - m_selectionFirst);
448
+ size_t selectionLast = std::max (from, to);
449
+ size_t selectionFirst = std::min (from, to);
450
+ if (selectionFirst != m_selectionFirst || selectionLast != m_selectionLast)
451
+ {
452
+ m_selectionFirst = selectionFirst;
453
+ m_selectionLast = selectionLast;
454
+ m_selectedText = m_text.getString ().substring (m_selectionFirst, m_selectionLast - m_selectionFirst);
455
+ }
384
456
}
385
457
else
386
458
{
387
- m_selectionFirst = m_selectionLast = 0 ;
388
- m_selectedText.clear ();
459
+ clearSelectedText ();
389
460
}
390
461
}
391
462
463
+
464
+ void TextBox::clearSelectedText ()
465
+ {
466
+ m_selectionFirst = m_selectionLast = m_cursorPos;
467
+ m_selectedText.clear ();
468
+ }
469
+
470
+
392
471
const sf::String& TextBox::getSelectedText () const
393
472
{
394
473
return m_selectedText;
@@ -403,7 +482,7 @@ void TextBox::deleteSelectedText()
403
482
sf::String str = m_text.getString ();
404
483
str.erase (m_selectionFirst, m_selectionLast - m_selectionFirst);
405
484
setCursor (m_selectionFirst);
406
- setSelectedText ( 0 , 0 );
485
+ clearSelectedText ( );
407
486
m_text.setString (str);
408
487
}
409
488
}
0 commit comments