Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epoxy
GitHub Repository: epoxy/proj11
Path: blob/master/SLICK_HOME/src/org/newdawn/slick/gui/TextField.java
1457 views
1
package org.newdawn.slick.gui;
2
3
import org.lwjgl.Sys;
4
import org.newdawn.slick.Color;
5
import org.newdawn.slick.Font;
6
import org.newdawn.slick.Graphics;
7
import org.newdawn.slick.Input;
8
import org.newdawn.slick.geom.Rectangle;
9
10
/**
11
* A single text field supporting text entry
12
*
13
* @author kevin
14
*/
15
public class TextField extends AbstractComponent {
16
/** The key repeat interval */
17
private static final int INITIAL_KEY_REPEAT_INTERVAL = 400;
18
/** The key repeat interval */
19
private static final int KEY_REPEAT_INTERVAL = 50;
20
21
/** The width of the field */
22
private int width;
23
24
/** The height of the field */
25
private int height;
26
27
/** The location in the X coordinate */
28
protected int x;
29
30
/** The location in the Y coordinate */
31
protected int y;
32
33
/** The maximum number of characters allowed to be input */
34
private int maxCharacter = 10000;
35
36
/** The value stored in the text field */
37
private String value = "";
38
39
/** The font used to render text in the field */
40
private Font font;
41
42
/** The border color - null if no border */
43
private Color border = Color.white;
44
45
/** The text color */
46
private Color text = Color.white;
47
48
/** The background color - null if no background */
49
private Color background = new Color(0, 0, 0, 0.5f);
50
51
/** The current cursor position */
52
private int cursorPos;
53
54
/** True if the cursor should be visible */
55
private boolean visibleCursor = true;
56
57
/** The last key pressed */
58
private int lastKey = -1;
59
60
/** The last character pressed */
61
private char lastChar = 0;
62
63
/** The time since last key repeat */
64
private long repeatTimer;
65
66
/** The text before the paste in */
67
private String oldText;
68
69
/** The cursor position before the paste */
70
private int oldCursorPos;
71
72
/** True if events should be consumed by the field */
73
private boolean consume = true;
74
75
/**
76
* Create a new text field
77
*
78
* @param container
79
* The container rendering this field
80
* @param font
81
* The font to use in the text field
82
* @param x
83
* The x coordinate of the top left corner of the text field
84
* @param y
85
* The y coordinate of the top left corner of the text field
86
* @param width
87
* The width of the text field
88
* @param height
89
* The height of the text field
90
* @param listener
91
* The listener to add to the text field
92
*/
93
public TextField(GUIContext container, Font font, int x, int y, int width,
94
int height, ComponentListener listener) {
95
this(container,font,x,y,width,height);
96
addListener(listener);
97
}
98
99
/**
100
* Create a new text field
101
*
102
* @param container
103
* The container rendering this field
104
* @param font
105
* The font to use in the text field
106
* @param x
107
* The x coordinate of the top left corner of the text field
108
* @param y
109
* The y coordinate of the top left corner of the text field
110
* @param width
111
* The width of the text field
112
* @param height
113
* The height of the text field
114
*/
115
public TextField(GUIContext container, Font font, int x, int y, int width,
116
int height) {
117
super(container);
118
119
this.font = font;
120
121
setLocation(x, y);
122
this.width = width;
123
this.height = height;
124
}
125
126
/**
127
* Indicate if the input events should be consumed by this field
128
*
129
* @param consume True if events should be consumed by this field
130
*/
131
public void setConsumeEvents(boolean consume) {
132
this.consume = consume;
133
}
134
135
/**
136
* Deactivate the key input handling for this field
137
*/
138
public void deactivate() {
139
setFocus(false);
140
}
141
142
/**
143
* Moves the component.
144
*
145
* @param x
146
* X coordinate
147
* @param y
148
* Y coordinate
149
*/
150
public void setLocation(int x, int y) {
151
this.x = x;
152
this.y = y;
153
}
154
155
/**
156
* Returns the position in the X coordinate
157
*
158
* @return x
159
*/
160
public int getX() {
161
return x;
162
}
163
164
/**
165
* Returns the position in the Y coordinate
166
*
167
* @return y
168
*/
169
public int getY() {
170
return y;
171
}
172
173
/**
174
* Get the width of the component
175
*
176
* @return The width of the component
177
*/
178
public int getWidth() {
179
return width;
180
}
181
182
/**
183
* Get the height of the component
184
*
185
* @return The height of the component
186
*/
187
public int getHeight() {
188
return height;
189
}
190
191
/**
192
* Set the background color. Set to null to disable the background
193
*
194
* @param color
195
* The color to use for the background
196
*/
197
public void setBackgroundColor(Color color) {
198
background = color;
199
}
200
201
/**
202
* Set the border color. Set to null to disable the border
203
*
204
* @param color
205
* The color to use for the border
206
*/
207
public void setBorderColor(Color color) {
208
border = color;
209
}
210
211
/**
212
* Set the text color.
213
*
214
* @param color
215
* The color to use for the text
216
*/
217
public void setTextColor(Color color) {
218
text = color;
219
}
220
221
/**
222
* @see org.newdawn.slick.gui.AbstractComponent#render(org.newdawn.slick.gui.GUIContext,
223
* org.newdawn.slick.Graphics)
224
*/
225
public void render(GUIContext container, Graphics g) {
226
if (lastKey != -1) {
227
if (input.isKeyDown(lastKey)) {
228
if (repeatTimer < System.currentTimeMillis()) {
229
repeatTimer = System.currentTimeMillis() + KEY_REPEAT_INTERVAL;
230
keyPressed(lastKey, lastChar);
231
}
232
} else {
233
lastKey = -1;
234
}
235
}
236
Rectangle oldClip = g.getClip();
237
g.setWorldClip(x,y,width, height);
238
239
// Someone could have set a color for me to blend...
240
Color clr = g.getColor();
241
242
if (background != null) {
243
g.setColor(background.multiply(clr));
244
g.fillRect(x, y, width, height);
245
}
246
g.setColor(text.multiply(clr));
247
Font temp = g.getFont();
248
249
int cpos = font.getWidth(value.substring(0, cursorPos));
250
int tx = 0;
251
if (cpos > width) {
252
tx = width - cpos - font.getWidth("_");
253
}
254
255
g.translate(tx + 2, 0);
256
g.setFont(font);
257
g.drawString(value, x + 1, y + 1);
258
259
if (hasFocus() && visibleCursor) {
260
g.drawString("_", x + 1 + cpos + 2, y + 1);
261
}
262
263
g.translate(-tx - 2, 0);
264
265
if (border != null) {
266
g.setColor(border.multiply(clr));
267
g.drawRect(x, y, width, height);
268
}
269
g.setColor(clr);
270
g.setFont(temp);
271
g.clearWorldClip();
272
g.setClip(oldClip);
273
}
274
275
/**
276
* Get the value in the text field
277
*
278
* @return The value in the text field
279
*/
280
public String getText() {
281
return value;
282
}
283
284
/**
285
* Set the value to be displayed in the text field
286
*
287
* @param value
288
* The value to be displayed in the text field
289
*/
290
public void setText(String value) {
291
this.value = value;
292
if (cursorPos > value.length()) {
293
cursorPos = value.length();
294
}
295
}
296
297
/**
298
* Set the position of the cursor
299
*
300
* @param pos
301
* The new position of the cursor
302
*/
303
public void setCursorPos(int pos) {
304
cursorPos = pos;
305
if (cursorPos > value.length()) {
306
cursorPos = value.length();
307
}
308
}
309
310
/**
311
* Indicate whether the mouse cursor should be visible or not
312
*
313
* @param visibleCursor
314
* True if the mouse cursor should be visible
315
*/
316
public void setCursorVisible(boolean visibleCursor) {
317
this.visibleCursor = visibleCursor;
318
}
319
320
/**
321
* Set the length of the allowed input
322
*
323
* @param length
324
* The length of the allowed input
325
*/
326
public void setMaxLength(int length) {
327
maxCharacter = length;
328
if (value.length() > maxCharacter) {
329
value = value.substring(0, maxCharacter);
330
}
331
}
332
333
/**
334
* Do the paste into the field, overrideable for custom behaviour
335
*
336
* @param text The text to be pasted in
337
*/
338
protected void doPaste(String text) {
339
recordOldPosition();
340
341
for (int i=0;i<text.length();i++) {
342
keyPressed(-1, text.charAt(i));
343
}
344
}
345
346
/**
347
* Record the old position and content
348
*/
349
protected void recordOldPosition() {
350
oldText = getText();
351
oldCursorPos = cursorPos;
352
}
353
354
/**
355
* Do the undo of the paste, overrideable for custom behaviour
356
*
357
* @param oldCursorPos before the paste
358
* @param oldText The text before the last paste
359
*/
360
protected void doUndo(int oldCursorPos, String oldText) {
361
if (oldText != null) {
362
setText(oldText);
363
setCursorPos(oldCursorPos);
364
}
365
}
366
367
/**
368
* @see org.newdawn.slick.gui.AbstractComponent#keyPressed(int, char)
369
*/
370
public void keyPressed(int key, char c) {
371
if (hasFocus()) {
372
if (key != -1)
373
{
374
if ((key == Input.KEY_V) &&
375
((input.isKeyDown(Input.KEY_LCONTROL)) || (input.isKeyDown(Input.KEY_RCONTROL)))) {
376
String text = Sys.getClipboard();
377
if (text != null) {
378
doPaste(text);
379
}
380
return;
381
}
382
if ((key == Input.KEY_Z) &&
383
((input.isKeyDown(Input.KEY_LCONTROL)) || (input.isKeyDown(Input.KEY_RCONTROL)))) {
384
if (oldText != null) {
385
doUndo(oldCursorPos, oldText);
386
}
387
return;
388
}
389
390
// alt and control keys don't come through here
391
if (input.isKeyDown(Input.KEY_LCONTROL) || input.isKeyDown(Input.KEY_RCONTROL)) {
392
return;
393
}
394
if (input.isKeyDown(Input.KEY_LALT) || input.isKeyDown(Input.KEY_RALT)) {
395
return;
396
}
397
}
398
399
if (lastKey != key) {
400
lastKey = key;
401
repeatTimer = System.currentTimeMillis() + INITIAL_KEY_REPEAT_INTERVAL;
402
} else {
403
repeatTimer = System.currentTimeMillis() + KEY_REPEAT_INTERVAL;
404
}
405
lastChar = c;
406
407
if (key == Input.KEY_LEFT) {
408
if (cursorPos > 0) {
409
cursorPos--;
410
}
411
// Nobody more will be notified
412
if (consume) {
413
container.getInput().consumeEvent();
414
}
415
} else if (key == Input.KEY_RIGHT) {
416
if (cursorPos < value.length()) {
417
cursorPos++;
418
}
419
// Nobody more will be notified
420
if (consume) {
421
container.getInput().consumeEvent();
422
}
423
} else if (key == Input.KEY_BACK) {
424
if ((cursorPos > 0) && (value.length() > 0)) {
425
if (cursorPos < value.length()) {
426
value = value.substring(0, cursorPos - 1)
427
+ value.substring(cursorPos);
428
} else {
429
value = value.substring(0, cursorPos - 1);
430
}
431
cursorPos--;
432
}
433
// Nobody more will be notified
434
if (consume) {
435
container.getInput().consumeEvent();
436
}
437
} else if (key == Input.KEY_DELETE) {
438
if (value.length() > cursorPos) {
439
value = value.substring(0,cursorPos) + value.substring(cursorPos+1);
440
}
441
// Nobody more will be notified
442
if (consume) {
443
container.getInput().consumeEvent();
444
}
445
} else if ((c < 127) && (c > 31) && (value.length() < maxCharacter)) {
446
if (cursorPos < value.length()) {
447
value = value.substring(0, cursorPos) + c
448
+ value.substring(cursorPos);
449
} else {
450
value = value.substring(0, cursorPos) + c;
451
}
452
cursorPos++;
453
// Nobody more will be notified
454
if (consume) {
455
container.getInput().consumeEvent();
456
}
457
} else if (key == Input.KEY_RETURN) {
458
notifyListeners();
459
// Nobody more will be notified
460
if (consume) {
461
container.getInput().consumeEvent();
462
}
463
}
464
465
}
466
}
467
468
/**
469
* @see org.newdawn.slick.gui.AbstractComponent#setFocus(boolean)
470
*/
471
public void setFocus(boolean focus) {
472
lastKey = -1;
473
474
super.setFocus(focus);
475
}
476
}
477
478