001 package net.minecraft.src;
002
003 import cpw.mods.fml.common.Side;
004 import cpw.mods.fml.common.asm.SideOnly;
005 import org.lwjgl.opengl.GL11;
006
007 @SideOnly(Side.CLIENT)
008 public class GuiTextField extends Gui
009 {
010 /**
011 * Have the font renderer from GuiScreen to render the textbox text into the screen.
012 */
013 private final FontRenderer fontRenderer;
014 private final int xPos;
015 private final int yPos;
016
017 /** The width of this text field. */
018 private final int width;
019 private final int height;
020
021 /** Have the current text beign edited on the textbox. */
022 private String text = "";
023 private int maxStringLength = 32;
024 private int cursorCounter;
025 private boolean enableBackgroundDrawing = true;
026
027 /**
028 * if true the textbox can lose focus by clicking elsewhere on the screen
029 */
030 private boolean canLoseFocus = true;
031
032 /**
033 * If this value is true along isEnabled, keyTyped will process the keys.
034 */
035 private boolean isFocused = false;
036
037 /**
038 * If this value is true along isFocused, keyTyped will process the keys.
039 */
040 private boolean isEnabled = true;
041 private int field_73816_n = 0;
042 private int cursorPosition = 0;
043
044 /** other selection position, maybe the same as the cursor */
045 private int selectionEnd = 0;
046 private int enabledColor = 14737632;
047 private int disabledColor = 7368816;
048
049 /** True if this textbox is visible */
050 private boolean visible = true;
051
052 public GuiTextField(FontRenderer par1FontRenderer, int par2, int par3, int par4, int par5)
053 {
054 this.fontRenderer = par1FontRenderer;
055 this.xPos = par2;
056 this.yPos = par3;
057 this.width = par4;
058 this.height = par5;
059 }
060
061 /**
062 * Increments the cursor counter
063 */
064 public void updateCursorCounter()
065 {
066 ++this.cursorCounter;
067 }
068
069 /**
070 * Sets the text of the textbox.
071 */
072 public void setText(String par1Str)
073 {
074 if (par1Str.length() > this.maxStringLength)
075 {
076 this.text = par1Str.substring(0, this.maxStringLength);
077 }
078 else
079 {
080 this.text = par1Str;
081 }
082
083 this.setCursorPositionEnd();
084 }
085
086 /**
087 * Returns the text beign edited on the textbox.
088 */
089 public String getText()
090 {
091 return this.text;
092 }
093
094 /**
095 * @return returns the text between the cursor and selectionEnd
096 */
097 public String getSelectedtext()
098 {
099 int var1 = this.cursorPosition < this.selectionEnd ? this.cursorPosition : this.selectionEnd;
100 int var2 = this.cursorPosition < this.selectionEnd ? this.selectionEnd : this.cursorPosition;
101 return this.text.substring(var1, var2);
102 }
103
104 /**
105 * replaces selected text, or inserts text at the position on the cursor
106 */
107 public void writeText(String par1Str)
108 {
109 String var2 = "";
110 String var3 = ChatAllowedCharacters.filerAllowedCharacters(par1Str);
111 int var4 = this.cursorPosition < this.selectionEnd ? this.cursorPosition : this.selectionEnd;
112 int var5 = this.cursorPosition < this.selectionEnd ? this.selectionEnd : this.cursorPosition;
113 int var6 = this.maxStringLength - this.text.length() - (var4 - this.selectionEnd);
114 boolean var7 = false;
115
116 if (this.text.length() > 0)
117 {
118 var2 = var2 + this.text.substring(0, var4);
119 }
120
121 int var8;
122
123 if (var6 < var3.length())
124 {
125 var2 = var2 + var3.substring(0, var6);
126 var8 = var6;
127 }
128 else
129 {
130 var2 = var2 + var3;
131 var8 = var3.length();
132 }
133
134 if (this.text.length() > 0 && var5 < this.text.length())
135 {
136 var2 = var2 + this.text.substring(var5);
137 }
138
139 this.text = var2;
140 this.moveCursorBy(var4 - this.selectionEnd + var8);
141 }
142
143 /**
144 * Deletes the specified number of words starting at the cursor position. Negative numbers will delete words left of
145 * the cursor.
146 */
147 public void deleteWords(int par1)
148 {
149 if (this.text.length() != 0)
150 {
151 if (this.selectionEnd != this.cursorPosition)
152 {
153 this.writeText("");
154 }
155 else
156 {
157 this.deleteFromCursor(this.getNthWordFromCursor(par1) - this.cursorPosition);
158 }
159 }
160 }
161
162 /**
163 * delete the selected text, otherwsie deletes characters from either side of the cursor. params: delete num
164 */
165 public void deleteFromCursor(int par1)
166 {
167 if (this.text.length() != 0)
168 {
169 if (this.selectionEnd != this.cursorPosition)
170 {
171 this.writeText("");
172 }
173 else
174 {
175 boolean var2 = par1 < 0;
176 int var3 = var2 ? this.cursorPosition + par1 : this.cursorPosition;
177 int var4 = var2 ? this.cursorPosition : this.cursorPosition + par1;
178 String var5 = "";
179
180 if (var3 >= 0)
181 {
182 var5 = this.text.substring(0, var3);
183 }
184
185 if (var4 < this.text.length())
186 {
187 var5 = var5 + this.text.substring(var4);
188 }
189
190 this.text = var5;
191
192 if (var2)
193 {
194 this.moveCursorBy(par1);
195 }
196 }
197 }
198 }
199
200 /**
201 * see @getNthNextWordFromPos() params: N, position
202 */
203 public int getNthWordFromCursor(int par1)
204 {
205 return this.getNthWordFromPos(par1, this.getCursorPosition());
206 }
207
208 /**
209 * gets the position of the nth word. N may be negative, then it looks backwards. params: N, position
210 */
211 public int getNthWordFromPos(int par1, int par2)
212 {
213 return this.func_73798_a(par1, this.getCursorPosition(), true);
214 }
215
216 public int func_73798_a(int par1, int par2, boolean par3)
217 {
218 int var4 = par2;
219 boolean var5 = par1 < 0;
220 int var6 = Math.abs(par1);
221
222 for (int var7 = 0; var7 < var6; ++var7)
223 {
224 if (var5)
225 {
226 while (par3 && var4 > 0 && this.text.charAt(var4 - 1) == 32)
227 {
228 --var4;
229 }
230
231 while (var4 > 0 && this.text.charAt(var4 - 1) != 32)
232 {
233 --var4;
234 }
235 }
236 else
237 {
238 int var8 = this.text.length();
239 var4 = this.text.indexOf(32, var4);
240
241 if (var4 == -1)
242 {
243 var4 = var8;
244 }
245 else
246 {
247 while (par3 && var4 < var8 && this.text.charAt(var4) == 32)
248 {
249 ++var4;
250 }
251 }
252 }
253 }
254
255 return var4;
256 }
257
258 /**
259 * Moves the text cursor by a specified number of characters and clears the selection
260 */
261 public void moveCursorBy(int par1)
262 {
263 this.setCursorPosition(this.selectionEnd + par1);
264 }
265
266 /**
267 * sets the position of the cursor to the provided index
268 */
269 public void setCursorPosition(int par1)
270 {
271 this.cursorPosition = par1;
272 int var2 = this.text.length();
273
274 if (this.cursorPosition < 0)
275 {
276 this.cursorPosition = 0;
277 }
278
279 if (this.cursorPosition > var2)
280 {
281 this.cursorPosition = var2;
282 }
283
284 this.setSelectionPos(this.cursorPosition);
285 }
286
287 /**
288 * sets the cursors position to the beginning
289 */
290 public void setCursorPositionZero()
291 {
292 this.setCursorPosition(0);
293 }
294
295 /**
296 * sets the cursors position to after the text
297 */
298 public void setCursorPositionEnd()
299 {
300 this.setCursorPosition(this.text.length());
301 }
302
303 /**
304 * Call this method from you GuiScreen to process the keys into textbox.
305 */
306 public boolean textboxKeyTyped(char par1, int par2)
307 {
308 if (this.isEnabled && this.isFocused)
309 {
310 switch (par1)
311 {
312 case 1:
313 this.setCursorPositionEnd();
314 this.setSelectionPos(0);
315 return true;
316 case 3:
317 GuiScreen.setClipboardString(this.getSelectedtext());
318 return true;
319 case 22:
320 this.writeText(GuiScreen.getClipboardString());
321 return true;
322 case 24:
323 GuiScreen.setClipboardString(this.getSelectedtext());
324 this.writeText("");
325 return true;
326 default:
327 switch (par2)
328 {
329 case 14:
330 if (GuiScreen.isCtrlKeyDown())
331 {
332 this.deleteWords(-1);
333 }
334 else
335 {
336 this.deleteFromCursor(-1);
337 }
338
339 return true;
340 case 199:
341 if (GuiScreen.isShiftKeyDown())
342 {
343 this.setSelectionPos(0);
344 }
345 else
346 {
347 this.setCursorPositionZero();
348 }
349
350 return true;
351 case 203:
352 if (GuiScreen.isShiftKeyDown())
353 {
354 if (GuiScreen.isCtrlKeyDown())
355 {
356 this.setSelectionPos(this.getNthWordFromPos(-1, this.getSelectionEnd()));
357 }
358 else
359 {
360 this.setSelectionPos(this.getSelectionEnd() - 1);
361 }
362 }
363 else if (GuiScreen.isCtrlKeyDown())
364 {
365 this.setCursorPosition(this.getNthWordFromCursor(-1));
366 }
367 else
368 {
369 this.moveCursorBy(-1);
370 }
371
372 return true;
373 case 205:
374 if (GuiScreen.isShiftKeyDown())
375 {
376 if (GuiScreen.isCtrlKeyDown())
377 {
378 this.setSelectionPos(this.getNthWordFromPos(1, this.getSelectionEnd()));
379 }
380 else
381 {
382 this.setSelectionPos(this.getSelectionEnd() + 1);
383 }
384 }
385 else if (GuiScreen.isCtrlKeyDown())
386 {
387 this.setCursorPosition(this.getNthWordFromCursor(1));
388 }
389 else
390 {
391 this.moveCursorBy(1);
392 }
393
394 return true;
395 case 207:
396 if (GuiScreen.isShiftKeyDown())
397 {
398 this.setSelectionPos(this.text.length());
399 }
400 else
401 {
402 this.setCursorPositionEnd();
403 }
404
405 return true;
406 case 211:
407 if (GuiScreen.isCtrlKeyDown())
408 {
409 this.deleteWords(1);
410 }
411 else
412 {
413 this.deleteFromCursor(1);
414 }
415
416 return true;
417 default:
418 if (ChatAllowedCharacters.isAllowedCharacter(par1))
419 {
420 this.writeText(Character.toString(par1));
421 return true;
422 }
423 else
424 {
425 return false;
426 }
427 }
428 }
429 }
430 else
431 {
432 return false;
433 }
434 }
435
436 /**
437 * Args: x, y, buttonClicked
438 */
439 public void mouseClicked(int par1, int par2, int par3)
440 {
441 boolean var4 = par1 >= this.xPos && par1 < this.xPos + this.width && par2 >= this.yPos && par2 < this.yPos + this.height;
442
443 if (this.canLoseFocus)
444 {
445 this.setFocused(this.isEnabled && var4);
446 }
447
448 if (this.isFocused && par3 == 0)
449 {
450 int var5 = par1 - this.xPos;
451
452 if (this.enableBackgroundDrawing)
453 {
454 var5 -= 4;
455 }
456
457 String var6 = this.fontRenderer.trimStringToWidth(this.text.substring(this.field_73816_n), this.getWidth());
458 this.setCursorPosition(this.fontRenderer.trimStringToWidth(var6, var5).length() + this.field_73816_n);
459 }
460 }
461
462 /**
463 * Draws the textbox
464 */
465 public void drawTextBox()
466 {
467 if (this.getVisible())
468 {
469 if (this.getEnableBackgroundDrawing())
470 {
471 drawRect(this.xPos - 1, this.yPos - 1, this.xPos + this.width + 1, this.yPos + this.height + 1, -6250336);
472 drawRect(this.xPos, this.yPos, this.xPos + this.width, this.yPos + this.height, -16777216);
473 }
474
475 int var1 = this.isEnabled ? this.enabledColor : this.disabledColor;
476 int var2 = this.cursorPosition - this.field_73816_n;
477 int var3 = this.selectionEnd - this.field_73816_n;
478 String var4 = this.fontRenderer.trimStringToWidth(this.text.substring(this.field_73816_n), this.getWidth());
479 boolean var5 = var2 >= 0 && var2 <= var4.length();
480 boolean var6 = this.isFocused && this.cursorCounter / 6 % 2 == 0 && var5;
481 int var7 = this.enableBackgroundDrawing ? this.xPos + 4 : this.xPos;
482 int var8 = this.enableBackgroundDrawing ? this.yPos + (this.height - 8) / 2 : this.yPos;
483 int var9 = var7;
484
485 if (var3 > var4.length())
486 {
487 var3 = var4.length();
488 }
489
490 if (var4.length() > 0)
491 {
492 String var10 = var5 ? var4.substring(0, var2) : var4;
493 var9 = this.fontRenderer.drawStringWithShadow(var10, var7, var8, var1);
494 }
495
496 boolean var13 = this.cursorPosition < this.text.length() || this.text.length() >= this.getMaxStringLength();
497 int var11 = var9;
498
499 if (!var5)
500 {
501 var11 = var2 > 0 ? var7 + this.width : var7;
502 }
503 else if (var13)
504 {
505 var11 = var9 - 1;
506 --var9;
507 }
508
509 if (var4.length() > 0 && var5 && var2 < var4.length())
510 {
511 this.fontRenderer.drawStringWithShadow(var4.substring(var2), var9, var8, var1);
512 }
513
514 if (var6)
515 {
516 if (var13)
517 {
518 Gui.drawRect(var11, var8 - 1, var11 + 1, var8 + 1 + this.fontRenderer.FONT_HEIGHT, -3092272);
519 }
520 else
521 {
522 this.fontRenderer.drawStringWithShadow("_", var11, var8, var1);
523 }
524 }
525
526 if (var3 != var2)
527 {
528 int var12 = var7 + this.fontRenderer.getStringWidth(var4.substring(0, var3));
529 this.drawCursorVertical(var11, var8 - 1, var12 - 1, var8 + 1 + this.fontRenderer.FONT_HEIGHT);
530 }
531 }
532 }
533
534 /**
535 * draws the vertical line cursor in the textbox
536 */
537 private void drawCursorVertical(int par1, int par2, int par3, int par4)
538 {
539 int var5;
540
541 if (par1 < par3)
542 {
543 var5 = par1;
544 par1 = par3;
545 par3 = var5;
546 }
547
548 if (par2 < par4)
549 {
550 var5 = par2;
551 par2 = par4;
552 par4 = var5;
553 }
554
555 Tessellator var6 = Tessellator.instance;
556 GL11.glColor4f(0.0F, 0.0F, 255.0F, 255.0F);
557 GL11.glDisable(GL11.GL_TEXTURE_2D);
558 GL11.glEnable(GL11.GL_COLOR_LOGIC_OP);
559 GL11.glLogicOp(GL11.GL_OR_REVERSE);
560 var6.startDrawingQuads();
561 var6.addVertex((double)par1, (double)par4, 0.0D);
562 var6.addVertex((double)par3, (double)par4, 0.0D);
563 var6.addVertex((double)par3, (double)par2, 0.0D);
564 var6.addVertex((double)par1, (double)par2, 0.0D);
565 var6.draw();
566 GL11.glDisable(GL11.GL_COLOR_LOGIC_OP);
567 GL11.glEnable(GL11.GL_TEXTURE_2D);
568 }
569
570 public void setMaxStringLength(int par1)
571 {
572 this.maxStringLength = par1;
573
574 if (this.text.length() > par1)
575 {
576 this.text = this.text.substring(0, par1);
577 }
578 }
579
580 /**
581 * returns the maximum number of character that can be contained in this textbox
582 */
583 public int getMaxStringLength()
584 {
585 return this.maxStringLength;
586 }
587
588 /**
589 * returns the current position of the cursor
590 */
591 public int getCursorPosition()
592 {
593 return this.cursorPosition;
594 }
595
596 /**
597 * get enable drawing background and outline
598 */
599 public boolean getEnableBackgroundDrawing()
600 {
601 return this.enableBackgroundDrawing;
602 }
603
604 /**
605 * enable drawing background and outline
606 */
607 public void setEnableBackgroundDrawing(boolean par1)
608 {
609 this.enableBackgroundDrawing = par1;
610 }
611
612 /**
613 * Sets the text colour for this textbox (disabled text will not use this colour)
614 */
615 public void setTextColor(int par1)
616 {
617 this.enabledColor = par1;
618 }
619
620 public void func_82266_h(int par1)
621 {
622 this.disabledColor = par1;
623 }
624
625 /**
626 * setter for the focused field
627 */
628 public void setFocused(boolean par1)
629 {
630 if (par1 && !this.isFocused)
631 {
632 this.cursorCounter = 0;
633 }
634
635 this.isFocused = par1;
636 }
637
638 /**
639 * getter for the focused field
640 */
641 public boolean isFocused()
642 {
643 return this.isFocused;
644 }
645
646 public void func_82265_c(boolean par1)
647 {
648 this.isEnabled = par1;
649 }
650
651 /**
652 * the side of the selection that is not the cursor, maye be the same as the cursor
653 */
654 public int getSelectionEnd()
655 {
656 return this.selectionEnd;
657 }
658
659 /**
660 * returns the width of the textbox depending on if the the box is enabled
661 */
662 public int getWidth()
663 {
664 return this.getEnableBackgroundDrawing() ? this.width - 8 : this.width;
665 }
666
667 /**
668 * Sets the position of the selection anchor (i.e. position the selection was started at)
669 */
670 public void setSelectionPos(int par1)
671 {
672 int var2 = this.text.length();
673
674 if (par1 > var2)
675 {
676 par1 = var2;
677 }
678
679 if (par1 < 0)
680 {
681 par1 = 0;
682 }
683
684 this.selectionEnd = par1;
685
686 if (this.fontRenderer != null)
687 {
688 if (this.field_73816_n > var2)
689 {
690 this.field_73816_n = var2;
691 }
692
693 int var3 = this.getWidth();
694 String var4 = this.fontRenderer.trimStringToWidth(this.text.substring(this.field_73816_n), var3);
695 int var5 = var4.length() + this.field_73816_n;
696
697 if (par1 == this.field_73816_n)
698 {
699 this.field_73816_n -= this.fontRenderer.trimStringToWidth(this.text, var3, true).length();
700 }
701
702 if (par1 > var5)
703 {
704 this.field_73816_n += par1 - var5;
705 }
706 else if (par1 <= this.field_73816_n)
707 {
708 this.field_73816_n -= this.field_73816_n - par1;
709 }
710
711 if (this.field_73816_n < 0)
712 {
713 this.field_73816_n = 0;
714 }
715
716 if (this.field_73816_n > var2)
717 {
718 this.field_73816_n = var2;
719 }
720 }
721 }
722
723 /**
724 * if true the textbox can lose focus by clicking elsewhere on the screen
725 */
726 public void setCanLoseFocus(boolean par1)
727 {
728 this.canLoseFocus = par1;
729 }
730
731 /**
732 * @return {@code true} if this textbox is visible
733 */
734 public boolean getVisible()
735 {
736 return this.visible;
737 }
738
739 /**
740 * Sets whether or not this textbox is visible
741 */
742 public void setVisible(boolean par1)
743 {
744 this.visible = par1;
745 }
746 }