    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 i, boolean flag);
    121
    122    /**
    123     * returns true if the element passed in is currently selected
    124     */
    125    protected abstract boolean isSelected(int i);
    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 i, int j, int k, int l, Tessellator tessellator);
    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 k = this.width / 2 - 110;
    148        int l = this.width / 2 + 110;
    149        int i1 = par2 - this.top - this.field_77242_t + (int)this.amountScrolled - 4;
    150        int j1 = i1 / this.slotHeight;
    151        return par1 >= k && par1 <= l && j1 >= 0 && i1 >= 0 && j1 < this.getSize() ? j1 : -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 i = this.func_77209_d();
    169
    170        if (i < 0)
    171        {
    172            i /= 2;
    173        }
    174
    175        if (this.amountScrolled < 0.0F)
    176        {
    177            this.amountScrolled = 0.0F;
    178        }
    179
    180        if (this.amountScrolled > (float)i)
    181        {
    182            this.amountScrolled = (float)i;
    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 k = this.getSize();
    226        int l = this.getScrollBarX();
    227        int i1 = l + 6;
    228        int j1;
    229        int k1;
    230        int l1;
    231        int i2;
    232        int j2;
    233
    234        if (Mouse.isButtonDown(0))
    235        {
    236            if (this.initialClickY == -1.0F)
    237            {
    238                boolean flag = true;
    239
    240                if (par2 >= this.top && par2 <= this.bottom)
    241                {
    242                    int k2 = this.width / 2 - 110;
    243                    j1 = this.width / 2 + 110;
    244                    k1 = par2 - this.top - this.field_77242_t + (int)this.amountScrolled - 4;
    245                    l1 = k1 / this.slotHeight;
    246
    247                    if (par1 >= k2 && par1 <= j1 && l1 >= 0 && k1 >= 0 && l1 < k)
    248                    {
    249                        boolean flag1 = l1 == this.selectedElement && Minecraft.getSystemTime() - this.lastClicked < 250L;
    250                        this.elementClicked(l1, flag1);
    251                        this.selectedElement = l1;
    252                        this.lastClicked = Minecraft.getSystemTime();
    253                    }
    254                    else if (par1 >= k2 && par1 <= j1 && k1 < 0)
    255                    {
    256                        this.func_77224_a(par1 - k2, par2 - this.top + (int)this.amountScrolled - 4);
    257                        flag = false;
    258                    }
    259
    260                    if (par1 >= l && par1 <= i1)
    261                    {
    262                        this.scrollMultiplier = -1.0F;
    263                        j2 = this.func_77209_d();
    264
    265                        if (j2 < 1)
    266                        {
    267                            j2 = 1;
    268                        }
    269
    270                        i2 = (int)((float)((this.bottom - this.top) * (this.bottom - this.top)) / (float)this.getContentHeight());
    271
    272                        if (i2 < 32)
    273                        {
    274                            i2 = 32;
    275                        }
    276
    277                        if (i2 > this.bottom - this.top - 8)
    278                        {
    279                            i2 = this.bottom - this.top - 8;
    280                        }
    281
    282                        this.scrollMultiplier /= (float)(this.bottom - this.top - i2) / (float)j2;
    283                    }
    284                    else
    285                    {
    286                        this.scrollMultiplier = 1.0F;
    287                    }
    288
    289                    if (flag)
    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 l2 = Mouse.getEventDWheel();
    314
    315                if (l2 != 0)
    316                {
    317                    if (l2 > 0)
    318                    {
    319                        l2 = -1;
    320                    }
    321                    else if (l2 < 0)
    322                    {
    323                        l2 = 1;
    324                    }
    325
    326                    this.amountScrolled += (float)(l2 * 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 tessellator = Tessellator.instance;
    337        drawContainerBackground(tessellator);
    338        j1 = this.width / 2 - 92 - 16;
    339        k1 = this.top + 4 - (int)this.amountScrolled;
    340
    341        if (this.field_77243_s)
    342        {
    343            this.func_77222_a(j1, k1, tessellator);
    344        }
    345
    346        int i3;
    347
    348        for (l1 = 0; l1 < k; ++l1)
    349        {
    350            j2 = k1 + l1 * this.slotHeight + this.field_77242_t;
    351            i2 = this.slotHeight - 4;
    352
    353            if (j2 <= this.bottom && j2 + i2 >= this.top)
    354            {
    355                if (this.showSelectionBox && this.isSelected(l1))
    356                {
    357                    i3 = this.width / 2 - 110;
    358                    int j3 = this.width / 2 + 110;
    359                    GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    360                    GL11.glDisable(GL11.GL_TEXTURE_2D);
    361                    tessellator.startDrawingQuads();
    362                    tessellator.setColorOpaque_I(8421504);
    363                    tessellator.addVertexWithUV((double)i3, (double)(j2 + i2 + 2), 0.0D, 0.0D, 1.0D);
    364                    tessellator.addVertexWithUV((double)j3, (double)(j2 + i2 + 2), 0.0D, 1.0D, 1.0D);
    365                    tessellator.addVertexWithUV((double)j3, (double)(j2 - 2), 0.0D, 1.0D, 0.0D);
    366                    tessellator.addVertexWithUV((double)i3, (double)(j2 - 2), 0.0D, 0.0D, 0.0D);
    367                    tessellator.setColorOpaque_I(0);
    368                    tessellator.addVertexWithUV((double)(i3 + 1), (double)(j2 + i2 + 1), 0.0D, 0.0D, 1.0D);
    369                    tessellator.addVertexWithUV((double)(j3 - 1), (double)(j2 + i2 + 1), 0.0D, 1.0D, 1.0D);
    370                    tessellator.addVertexWithUV((double)(j3 - 1), (double)(j2 - 1), 0.0D, 1.0D, 0.0D);
    371                    tessellator.addVertexWithUV((double)(i3 + 1), (double)(j2 - 1), 0.0D, 0.0D, 0.0D);
    372                    tessellator.draw();
    373                    GL11.glEnable(GL11.GL_TEXTURE_2D);
    374                }
    375
    376                this.drawSlot(l1, j1, j2, i2, tessellator);
    377            }
    378        }
    379
    380        GL11.glDisable(GL11.GL_DEPTH_TEST);
    381        byte b0 = 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        tessellator.startDrawingQuads();
    390        tessellator.setColorRGBA_I(0, 0);
    391        tessellator.addVertexWithUV((double)this.left, (double)(this.top + b0), 0.0D, 0.0D, 1.0D);
    392        tessellator.addVertexWithUV((double)this.right, (double)(this.top + b0), 0.0D, 1.0D, 1.0D);
    393        tessellator.setColorRGBA_I(0, 255);
    394        tessellator.addVertexWithUV((double)this.right, (double)this.top, 0.0D, 1.0D, 0.0D);
    395        tessellator.addVertexWithUV((double)this.left, (double)this.top, 0.0D, 0.0D, 0.0D);
    396        tessellator.draw();
    397        tessellator.startDrawingQuads();
    398        tessellator.setColorRGBA_I(0, 255);
    399        tessellator.addVertexWithUV((double)this.left, (double)this.bottom, 0.0D, 0.0D, 1.0D);
    400        tessellator.addVertexWithUV((double)this.right, (double)this.bottom, 0.0D, 1.0D, 1.0D);
    401        tessellator.setColorRGBA_I(0, 0);
    402        tessellator.addVertexWithUV((double)this.right, (double)(this.bottom - b0), 0.0D, 1.0D, 0.0D);
    403        tessellator.addVertexWithUV((double)this.left, (double)(this.bottom - b0), 0.0D, 0.0D, 0.0D);
    404        tessellator.draw();
    405        j2 = this.func_77209_d();
    406
    407        if (j2 > 0)
    408        {
    409            i2 = (this.bottom - this.top) * (this.bottom - this.top) / this.getContentHeight();
    410
    411            if (i2 < 32)
    412            {
    413                i2 = 32;
    414            }
    415
    416            if (i2 > this.bottom - this.top - 8)
    417            {
    418                i2 = this.bottom - this.top - 8;
    419            }
    420
    421            i3 = (int)this.amountScrolled * (this.bottom - this.top - i2) / j2 + this.top;
    422
    423            if (i3 < this.top)
    424            {
    425                i3 = this.top;
    426            }
    427
    428            tessellator.startDrawingQuads();
    429            tessellator.setColorRGBA_I(0, 255);
    430            tessellator.addVertexWithUV((double)l, (double)this.bottom, 0.0D, 0.0D, 1.0D);
    431            tessellator.addVertexWithUV((double)i1, (double)this.bottom, 0.0D, 1.0D, 1.0D);
    432            tessellator.addVertexWithUV((double)i1, (double)this.top, 0.0D, 1.0D, 0.0D);
    433            tessellator.addVertexWithUV((double)l, (double)this.top, 0.0D, 0.0D, 0.0D);
    434            tessellator.draw();
    435            tessellator.startDrawingQuads();
    436            tessellator.setColorRGBA_I(8421504, 255);
    437            tessellator.addVertexWithUV((double)l, (double)(i3 + i2), 0.0D, 0.0D, 1.0D);
    438            tessellator.addVertexWithUV((double)i1, (double)(i3 + i2), 0.0D, 1.0D, 1.0D);
    439            tessellator.addVertexWithUV((double)i1, (double)i3, 0.0D, 1.0D, 0.0D);
    440            tessellator.addVertexWithUV((double)l, (double)i3, 0.0D, 0.0D, 0.0D);
    441            tessellator.draw();
    442            tessellator.startDrawingQuads();
    443            tessellator.setColorRGBA_I(12632256, 255);
    444            tessellator.addVertexWithUV((double)l, (double)(i3 + i2 - 1), 0.0D, 0.0D, 1.0D);
    445            tessellator.addVertexWithUV((double)(i1 - 1), (double)(i3 + i2 - 1), 0.0D, 1.0D, 1.0D);
    446            tessellator.addVertexWithUV((double)(i1 - 1), (double)i3, 0.0D, 1.0D, 0.0D);
    447            tessellator.addVertexWithUV((double)l, (double)i3, 0.0D, 0.0D, 0.0D);
    448            tessellator.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 tessellator = Tessellator.instance;
    469        this.mc.renderEngine.func_98187_b(BACKGROUND_IMAGE);
    470        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    471        float f = 32.0F;
    472        tessellator.startDrawingQuads();
    473        tessellator.setColorRGBA_I(4210752, par4);
    474        tessellator.addVertexWithUV(0.0D, (double)par2, 0.0D, 0.0D, (double)((float)par2 / f));
    475        tessellator.addVertexWithUV((double)this.width, (double)par2, 0.0D, (double)((float)this.width / f), (double)((float)par2 / f));
    476        tessellator.setColorRGBA_I(4210752, par3);
    477        tessellator.addVertexWithUV((double)this.width, (double)par1, 0.0D, (double)((float)this.width / f), (double)((float)par1 / f));
    478        tessellator.addVertexWithUV(0.0D, (double)par1, 0.0D, 0.0D, (double)((float)par1 / f));
    479        tessellator.draw();
    480    }
    481
    482    protected void drawContainerBackground(Tessellator tess)
    483    {
    484        this.mc.renderEngine.func_98187_b(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}