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 /** 621 * setter for the focused field 622 */ 623 public void setFocused(boolean par1) 624 { 625 if (par1 && !this.isFocused) 626 { 627 this.cursorCounter = 0; 628 } 629 630 this.isFocused = par1; 631 } 632 633 /** 634 * getter for the focused field 635 */ 636 public boolean isFocused() 637 { 638 return this.isFocused; 639 } 640 641 /** 642 * the side of the selection that is not the cursor, maye be the same as the cursor 643 */ 644 public int getSelectionEnd() 645 { 646 return this.selectionEnd; 647 } 648 649 /** 650 * returns the width of the textbox depending on if the the box is enabled 651 */ 652 public int getWidth() 653 { 654 return this.getEnableBackgroundDrawing() ? this.width - 8 : this.width; 655 } 656 657 /** 658 * Sets the position of the selection anchor (i.e. position the selection was started at) 659 */ 660 public void setSelectionPos(int par1) 661 { 662 int var2 = this.text.length(); 663 664 if (par1 > var2) 665 { 666 par1 = var2; 667 } 668 669 if (par1 < 0) 670 { 671 par1 = 0; 672 } 673 674 this.selectionEnd = par1; 675 676 if (this.fontRenderer != null) 677 { 678 if (this.field_73816_n > var2) 679 { 680 this.field_73816_n = var2; 681 } 682 683 int var3 = this.getWidth(); 684 String var4 = this.fontRenderer.trimStringToWidth(this.text.substring(this.field_73816_n), var3); 685 int var5 = var4.length() + this.field_73816_n; 686 687 if (par1 == this.field_73816_n) 688 { 689 this.field_73816_n -= this.fontRenderer.trimStringToWidth(this.text, var3, true).length(); 690 } 691 692 if (par1 > var5) 693 { 694 this.field_73816_n += par1 - var5; 695 } 696 else if (par1 <= this.field_73816_n) 697 { 698 this.field_73816_n -= this.field_73816_n - par1; 699 } 700 701 if (this.field_73816_n < 0) 702 { 703 this.field_73816_n = 0; 704 } 705 706 if (this.field_73816_n > var2) 707 { 708 this.field_73816_n = var2; 709 } 710 } 711 } 712 713 /** 714 * if true the textbox can lose focus by clicking elsewhere on the screen 715 */ 716 public void setCanLoseFocus(boolean par1) 717 { 718 this.canLoseFocus = par1; 719 } 720 721 /** 722 * @return {@code true} if this textbox is visible 723 */ 724 public boolean getVisible() 725 { 726 return this.visible; 727 } 728 729 /** 730 * Sets whether or not this textbox is visible 731 */ 732 public void setVisible(boolean par1) 733 { 734 this.visible = par1; 735 } 736 }