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