    001package net.minecraft.client.gui;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.util.List;
    006import net.minecraft.client.Minecraft;
    007import net.minecraft.client.renderer.Tessellator;
    008import org.lwjgl.input.Mouse;
    009import org.lwjgl.opengl.GL11;
    010
    011@SideOnly(Side.CLIENT)
    012public abstract class GuiSlot
    013{
    014    private final Minecraft mc;
    015
    016    /**
    017     * The width of the GuiScreen. Affects the container rendering, but not the overlays.
    018     */
    019    private int width;
    020
    021    /**
    022     * The height of the GuiScreen. Affects the container rendering, but not the overlays or the scrolling.
    023     */
    024    private int height;
    025
    026    /** The top of the slot container. Affects the overlays and scrolling. */
    027    protected int top;
    028
    029    /** The bottom of the slot container. Affects the overlays and scrolling. */
    030    protected int bottom;
    031    private int right;
    032    private int left;
    033
    034    /** The height of a slot. */
    035    protected final int slotHeight;
    036
    037    /** button id of the button used to scroll up */
    038    private int scrollUpButtonID;
    039
    040    /** the buttonID of the button used to scroll down */
    041    private int scrollDownButtonID;
    042
    043    /** X axis position of the mouse */
    044    protected int mouseX;
    045
    046    /** Y axis position of the mouse */
    047    protected int mouseY;
    048
    049    /** where the mouse was in the window when you first clicked to scroll */
    050    private float initialClickY = -2.0F;
    051
    052    /**
    053     * what to multiply the amount you moved your mouse by(used for slowing down scrolling when over the items and no on
    054     * scroll bar)
    055     */
    056    private float scrollMultiplier;
    057
    058    /** how far down this slot has been scrolled */
    059    private float amountScrolled;
    060
    061    /** the element in the list that was selected */
    062    private int selectedElement = -1;
    063
    064    /** the time when this button was last clicked. */
    065    private long lastClicked = 0L;
    066
    067    /** true if a selected element in this gui will show an outline box */
    068    private boolean showSelectionBox = true;
    069    private boolean field_77243_s;
    070    private int field_77242_t;
    071
    072    public String BACKGROUND_IMAGE = "/gui/background.png";
    073
    074    public GuiSlot(Minecraft par1Minecraft, int par2, int par3, int par4, int par5, int par6)
    075    {
    076        this.mc = par1Minecraft;
    077        this.width = par2;
    078        this.height = par3;
    079        this.top = par4;
    080        this.bottom = par5;
    081        this.slotHeight = par6;
    082        this.left = 0;
    083        this.right = par2;
    084    }
    085
    086    public void func_77207_a(int par1, int par2, int par3, int par4)
    087    {
    088        this.width = par1;
    089        this.height = par2;
    090        this.top = par3;
    091        this.bottom = par4;
    092        this.left = 0;
    093        this.right = par1;
    094    }
    095
    096    public void setShowSelectionBox(boolean par1)
    097    {
    098        this.showSelectionBox = par1;
    099    }
    100
    101    protected void func_77223_a(boolean par1, int par2)
    102    {
    103        this.field_77243_s = par1;
    104        this.field_77242_t = par2;
    105
    106        if (!par1)
    107        {
    108            this.field_77242_t = 0;
    109        }
    110    }
    111
    112    /**
    113     * Gets the size of the current slot list.
    114     */
    115    protected abstract int getSize();
    116
    117    /**
    118     * the element in the slot that was clicked, boolean for wether it was double clicked or not
    119     */
    120    protected abstract void elementClicked(int var1, boolean var2);
    121
    122    /**
    123     * returns true if the element passed in is currently selected
    124     */
    125    protected abstract boolean isSelected(int var1);
    126
    127    /**
    128     * return the height of the content being scrolled
    129     */
    130    protected int getContentHeight()
    131    {
    132        return this.getSize() * this.slotHeight + this.field_77242_t;
    133    }
    134
    135    protected abstract void drawBackground();
    136
    137    protected abstract void drawSlot(int var1, int var2, int var3, int var4, Tessellator var5);
    138
    139    protected void func_77222_a(int par1, int par2, Tessellator par3Tessellator) {}
    140
    141    protected void func_77224_a(int par1, int par2) {}
    142
    143    protected void func_77215_b(int par1, int par2) {}
    144
    145    public int func_77210_c(int par1, int par2)
    146    {
    147        int var3 = this.width / 2 - 110;
    148        int var4 = this.width / 2 + 110;
    149        int var5 = par2 - this.top - this.field_77242_t + (int)this.amountScrolled - 4;
    150        int var6 = var5 / this.slotHeight;
    151        return par1 >= var3 && par1 <= var4 && var6 >= 0 && var5 >= 0 && var6 < this.getSize() ? var6 : -1;
    152    }
    153
    154    /**
    155     * Registers the IDs that can be used for the scrollbar's buttons.
    156     */
    157    public void registerScrollButtons(List par1List, int par2, int par3)
    158    {
    159        this.scrollUpButtonID = par2;
    160        this.scrollDownButtonID = par3;
    161    }
    162
    163    /**
    164     * stop the thing from scrolling out of bounds
    165     */
    166    private void bindAmountScrolled()
    167    {
    168        int var1 = this.func_77209_d();
    169
    170        if (var1 < 0)
    171        {
    172            var1 /= 2;
    173        }
    174
    175        if (this.amountScrolled < 0.0F)
    176        {
    177            this.amountScrolled = 0.0F;
    178        }
    179
    180        if (this.amountScrolled > (float)var1)
    181        {
    182            this.amountScrolled = (float)var1;
    183        }
    184    }
    185
    186    public int func_77209_d()
    187    {
    188        return this.getContentHeight() - (this.bottom - this.top - 4);
    189    }
    190
    191    public void func_77208_b(int par1)
    192    {
    193        this.amountScrolled += (float)par1;
    194        this.bindAmountScrolled();
    195        this.initialClickY = -2.0F;
    196    }
    197
    198    public void actionPerformed(GuiButton par1GuiButton)
    199    {
    200        if (par1GuiButton.enabled)
    201        {
    202            if (par1GuiButton.id == this.scrollUpButtonID)
    203            {
    204                this.amountScrolled -= (float)(this.slotHeight * 2 / 3);
    205                this.initialClickY = -2.0F;
    206                this.bindAmountScrolled();
    207            }
    208            else if (par1GuiButton.id == this.scrollDownButtonID)
    209            {
    210                this.amountScrolled += (float)(this.slotHeight * 2 / 3);
    211                this.initialClickY = -2.0F;
    212                this.bindAmountScrolled();
    213            }
    214        }
    215    }
    216
    217    /**
    218     * draws the slot to the screen, pass in mouse's current x and y and partial ticks
    219     */
    220    public void drawScreen(int par1, int par2, float par3)
    221    {
    222        this.mouseX = par1;
    223        this.mouseY = par2;
    224        this.drawBackground();
    225        int var4 = this.getSize();
    226        int var5 = this.getScrollBarX();
    227        int var6 = var5 + 6;
    228        int var9;
    229        int var10;
    230        int var11;
    231        int var13;
    232        int var19;
    233
    234        if (Mouse.isButtonDown(0))
    235        {
    236            if (this.initialClickY == -1.0F)
    237            {
    238                boolean var7 = true;
    239
    240                if (par2 >= this.top && par2 <= this.bottom)
    241                {
    242                    int var8 = this.width / 2 - 110;
    243                    var9 = this.width / 2 + 110;
    244                    var10 = par2 - this.top - this.field_77242_t + (int)this.amountScrolled - 4;
    245                    var11 = var10 / this.slotHeight;
    246
    247                    if (par1 >= var8 && par1 <= var9 && var11 >= 0 && var10 >= 0 && var11 < var4)
    248                    {
    249                        boolean var12 = var11 == this.selectedElement && Minecraft.getSystemTime() - this.lastClicked < 250L;
    250                        this.elementClicked(var11, var12);
    251                        this.selectedElement = var11;
    252                        this.lastClicked = Minecraft.getSystemTime();
    253                    }
    254                    else if (par1 >= var8 && par1 <= var9 && var10 < 0)
    255                    {
    256                        this.func_77224_a(par1 - var8, par2 - this.top + (int)this.amountScrolled - 4);
    257                        var7 = false;
    258                    }
    259
    260                    if (par1 >= var5 && par1 <= var6)
    261                    {
    262                        this.scrollMultiplier = -1.0F;
    263                        var19 = this.func_77209_d();
    264
    265                        if (var19 < 1)
    266                        {
    267                            var19 = 1;
    268                        }
    269
    270                        var13 = (int)((float)((this.bottom - this.top) * (this.bottom - this.top)) / (float)this.getContentHeight());
    271
    272                        if (var13 < 32)
    273                        {
    274                            var13 = 32;
    275                        }
    276
    277                        if (var13 > this.bottom - this.top - 8)
    278                        {
    279                            var13 = this.bottom - this.top - 8;
    280                        }
    281
    282                        this.scrollMultiplier /= (float)(this.bottom - this.top - var13) / (float)var19;
    283                    }
    284                    else
    285                    {
    286                        this.scrollMultiplier = 1.0F;
    287                    }
    288
    289                    if (var7)
    290                    {
    291                        this.initialClickY = (float)par2;
    292                    }
    293                    else
    294                    {
    295                        this.initialClickY = -2.0F;
    296                    }
    297                }
    298                else
    299                {
    300                    this.initialClickY = -2.0F;
    301                }
    302            }
    303            else if (this.initialClickY >= 0.0F)
    304            {
    305                this.amountScrolled -= ((float)par2 - this.initialClickY) * this.scrollMultiplier;
    306                this.initialClickY = (float)par2;
    307            }
    308        }
    309        else
    310        {
    311            while (!this.mc.gameSettings.touchscreen && Mouse.next())
    312            {
    313                int var16 = Mouse.getEventDWheel();
    314
    315                if (var16 != 0)
    316                {
    317                    if (var16 > 0)
    318                    {
    319                        var16 = -1;
    320                    }
    321                    else if (var16 < 0)
    322                    {
    323                        var16 = 1;
    324                    }
    325
    326                    this.amountScrolled += (float)(var16 * this.slotHeight / 2);
    327                }
    328            }
    329
    330            this.initialClickY = -1.0F;
    331        }
    332
    333        this.bindAmountScrolled();
    334        GL11.glDisable(GL11.GL_LIGHTING);
    335        GL11.glDisable(GL11.GL_FOG);
    336        Tessellator var18 = Tessellator.instance;
    337        drawContainerBackground(var18);
    338        var9 = this.width / 2 - 92 - 16;
    339        var10 = this.top + 4 - (int)this.amountScrolled;
    340
    341        if (this.field_77243_s)
    342        {
    343            this.func_77222_a(var9, var10, var18);
    344        }
    345
    346        int var14;
    347
    348        for (var11 = 0; var11 < var4; ++var11)
    349        {
    350            var19 = var10 + var11 * this.slotHeight + this.field_77242_t;
    351            var13 = this.slotHeight - 4;
    352
    353            if (var19 <= this.bottom && var19 + var13 >= this.top)
    354            {
    355                if (this.showSelectionBox && this.isSelected(var11))
    356                {
    357                    var14 = this.width / 2 - 110;
    358                    int var15 = this.width / 2 + 110;
    359                    GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    360                    GL11.glDisable(GL11.GL_TEXTURE_2D);
    361                    var18.startDrawingQuads();
    362                    var18.setColorOpaque_I(8421504);
    363                    var18.addVertexWithUV((double)var14, (double)(var19 + var13 + 2), 0.0D, 0.0D, 1.0D);
    364                    var18.addVertexWithUV((double)var15, (double)(var19 + var13 + 2), 0.0D, 1.0D, 1.0D);
    365                    var18.addVertexWithUV((double)var15, (double)(var19 - 2), 0.0D, 1.0D, 0.0D);
    366                    var18.addVertexWithUV((double)var14, (double)(var19 - 2), 0.0D, 0.0D, 0.0D);
    367                    var18.setColorOpaque_I(0);
    368                    var18.addVertexWithUV((double)(var14 + 1), (double)(var19 + var13 + 1), 0.0D, 0.0D, 1.0D);
    369                    var18.addVertexWithUV((double)(var15 - 1), (double)(var19 + var13 + 1), 0.0D, 1.0D, 1.0D);
    370                    var18.addVertexWithUV((double)(var15 - 1), (double)(var19 - 1), 0.0D, 1.0D, 0.0D);
    371                    var18.addVertexWithUV((double)(var14 + 1), (double)(var19 - 1), 0.0D, 0.0D, 0.0D);
    372                    var18.draw();
    373                    GL11.glEnable(GL11.GL_TEXTURE_2D);
    374                }
    375
    376                this.drawSlot(var11, var9, var19, var13, var18);
    377            }
    378        }
    379
    380        GL11.glDisable(GL11.GL_DEPTH_TEST);
    381        byte var20 = 4;
    382        this.overlayBackground(0, this.top, 255, 255);
    383        this.overlayBackground(this.bottom, this.height, 255, 255);
    384        GL11.glEnable(GL11.GL_BLEND);
    385        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
    386        GL11.glDisable(GL11.GL_ALPHA_TEST);
    387        GL11.glShadeModel(GL11.GL_SMOOTH);
    388        GL11.glDisable(GL11.GL_TEXTURE_2D);
    389        var18.startDrawingQuads();
    390        var18.setColorRGBA_I(0, 0);
    391        var18.addVertexWithUV((double)this.left, (double)(this.top + var20), 0.0D, 0.0D, 1.0D);
    392        var18.addVertexWithUV((double)this.right, (double)(this.top + var20), 0.0D, 1.0D, 1.0D);
    393        var18.setColorRGBA_I(0, 255);
    394        var18.addVertexWithUV((double)this.right, (double)this.top, 0.0D, 1.0D, 0.0D);
    395        var18.addVertexWithUV((double)this.left, (double)this.top, 0.0D, 0.0D, 0.0D);
    396        var18.draw();
    397        var18.startDrawingQuads();
    398        var18.setColorRGBA_I(0, 255);
    399        var18.addVertexWithUV((double)this.left, (double)this.bottom, 0.0D, 0.0D, 1.0D);
    400        var18.addVertexWithUV((double)this.right, (double)this.bottom, 0.0D, 1.0D, 1.0D);
    401        var18.setColorRGBA_I(0, 0);
    402        var18.addVertexWithUV((double)this.right, (double)(this.bottom - var20), 0.0D, 1.0D, 0.0D);
    403        var18.addVertexWithUV((double)this.left, (double)(this.bottom - var20), 0.0D, 0.0D, 0.0D);
    404        var18.draw();
    405        var19 = this.func_77209_d();
    406
    407        if (var19 > 0)
    408        {
    409            var13 = (this.bottom - this.top) * (this.bottom - this.top) / this.getContentHeight();
    410
    411            if (var13 < 32)
    412            {
    413                var13 = 32;
    414            }
    415
    416            if (var13 > this.bottom - this.top - 8)
    417            {
    418                var13 = this.bottom - this.top - 8;
    419            }
    420
    421            var14 = (int)this.amountScrolled * (this.bottom - this.top - var13) / var19 + this.top;
    422
    423            if (var14 < this.top)
    424            {
    425                var14 = this.top;
    426            }
    427
    428            var18.startDrawingQuads();
    429            var18.setColorRGBA_I(0, 255);
    430            var18.addVertexWithUV((double)var5, (double)this.bottom, 0.0D, 0.0D, 1.0D);
    431            var18.addVertexWithUV((double)var6, (double)this.bottom, 0.0D, 1.0D, 1.0D);
    432            var18.addVertexWithUV((double)var6, (double)this.top, 0.0D, 1.0D, 0.0D);
    433            var18.addVertexWithUV((double)var5, (double)this.top, 0.0D, 0.0D, 0.0D);
    434            var18.draw();
    435            var18.startDrawingQuads();
    436            var18.setColorRGBA_I(8421504, 255);
    437            var18.addVertexWithUV((double)var5, (double)(var14 + var13), 0.0D, 0.0D, 1.0D);
    438            var18.addVertexWithUV((double)var6, (double)(var14 + var13), 0.0D, 1.0D, 1.0D);
    439            var18.addVertexWithUV((double)var6, (double)var14, 0.0D, 1.0D, 0.0D);
    440            var18.addVertexWithUV((double)var5, (double)var14, 0.0D, 0.0D, 0.0D);
    441            var18.draw();
    442            var18.startDrawingQuads();
    443            var18.setColorRGBA_I(12632256, 255);
    444            var18.addVertexWithUV((double)var5, (double)(var14 + var13 - 1), 0.0D, 0.0D, 1.0D);
    445            var18.addVertexWithUV((double)(var6 - 1), (double)(var14 + var13 - 1), 0.0D, 1.0D, 1.0D);
    446            var18.addVertexWithUV((double)(var6 - 1), (double)var14, 0.0D, 1.0D, 0.0D);
    447            var18.addVertexWithUV((double)var5, (double)var14, 0.0D, 0.0D, 0.0D);
    448            var18.draw();
    449        }
    450
    451        this.func_77215_b(par1, par2);
    452        GL11.glEnable(GL11.GL_TEXTURE_2D);
    453        GL11.glShadeModel(GL11.GL_FLAT);
    454        GL11.glEnable(GL11.GL_ALPHA_TEST);
    455        GL11.glDisable(GL11.GL_BLEND);
    456    }
    457
    458    protected int getScrollBarX()
    459    {
    460        return this.width / 2 + 124;
    461    }
    462
    463    /**
    464     * Overlays the background to hide scrolled items
    465     */
    466    protected void overlayBackground(int par1, int par2, int par3, int par4)
    467    {
    468        Tessellator var5 = Tessellator.instance;
    469        GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.mc.renderEngine.getTexture(BACKGROUND_IMAGE));
    470        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    471        float var6 = 32.0F;
    472        var5.startDrawingQuads();
    473        var5.setColorRGBA_I(4210752, par4);
    474        var5.addVertexWithUV(0.0D, (double)par2, 0.0D, 0.0D, (double)((float)par2 / var6));
    475        var5.addVertexWithUV((double)this.width, (double)par2, 0.0D, (double)((float)this.width / var6), (double)((float)par2 / var6));
    476        var5.setColorRGBA_I(4210752, par3);
    477        var5.addVertexWithUV((double)this.width, (double)par1, 0.0D, (double)((float)this.width / var6), (double)((float)par1 / var6));
    478        var5.addVertexWithUV(0.0D, (double)par1, 0.0D, 0.0D, (double)((float)par1 / var6));
    479        var5.draw();
    480    }
    481
    482    protected void drawContainerBackground(Tessellator tess)
    483    {
    484        GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.renderEngine.getTexture(BACKGROUND_IMAGE));
    485        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    486        float height = 32.0F;
    487        tess.startDrawingQuads();
    488        tess.setColorOpaque_I(2105376);
    489        tess.addVertexWithUV((double)left,  (double)bottom, 0.0D, (double)(left  / height), (double)((bottom + (int)amountScrolled) / height));
    490        tess.addVertexWithUV((double)right, (double)bottom, 0.0D, (double)(right / height), (double)((bottom + (int)amountScrolled) / height));
    491        tess.addVertexWithUV((double)right, (double)top,    0.0D, (double)(right / height), (double)((top    + (int)amountScrolled) / height));
    492        tess.addVertexWithUV((double)left,  (double)top,    0.0D, (double)(left  / height), (double)((top    + (int)amountScrolled) / height));
    493        tess.draw();
    494    }
    495}