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    }