    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    }