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