    001/*
    002 * Forge Mod Loader
    003 * Copyright (c) 2012-2013 cpw.
    004 * All rights reserved. This program and the accompanying materials
    005 * are made available under the terms of the GNU Lesser Public License v2.1
    006 * which accompanies this distribution, and is available at
    007 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
    008 *
    009 * Contributors:
    010 *     cpw - implementation
    011 */
    012
    013package cpw.mods.fml.client;
    014
    015import java.util.List;
    016
    017import net.minecraft.client.Minecraft;
    018import net.minecraft.client.gui.GuiButton;
    019import net.minecraft.client.renderer.Tessellator;
    020
    021import org.lwjgl.input.Mouse;
    022import org.lwjgl.opengl.GL11;
    023
    024public abstract class GuiScrollingList
    025{
    026    private final Minecraft client;
    027    protected final int listWidth;
    028    protected final int listHeight;
    029    protected final int top;
    030    protected final int bottom;
    031    private final int right;
    032    protected final int left;
    033    protected final int slotHeight;
    034    private int scrollUpActionId;
    035    private int scrollDownActionId;
    036    protected int mouseX;
    037    protected int mouseY;
    038    private float initialMouseClickY = -2.0F;
    039    private float scrollFactor;
    040    private float scrollDistance;
    041    private int selectedIndex = -1;
    042    private long lastClickTime = 0L;
    043    private boolean field_25123_p = true;
    044    private boolean field_27262_q;
    045    private int field_27261_r;
    046
    047    public GuiScrollingList(Minecraft client, int width, int height, int top, int bottom, int left, int entryHeight)
    048    {
    049        this.client = client;
    050        this.listWidth = width;
    051        this.listHeight = height;
    052        this.top = top;
    053        this.bottom = bottom;
    054        this.slotHeight = entryHeight;
    055        this.left = left;
    056        this.right = width + this.left;
    057    }
    058
    059    public void func_27258_a(boolean p_27258_1_)
    060    {
    061        this.field_25123_p = p_27258_1_;
    062    }
    063
    064    protected void func_27259_a(boolean p_27259_1_, int p_27259_2_)
    065    {
    066        this.field_27262_q = p_27259_1_;
    067        this.field_27261_r = p_27259_2_;
    068
    069        if (!p_27259_1_)
    070        {
    071            this.field_27261_r = 0;
    072        }
    073    }
    074
    075    protected abstract int getSize();
    076
    077    protected abstract void elementClicked(int index, boolean doubleClick);
    078
    079    protected abstract boolean isSelected(int index);
    080
    081    protected int getContentHeight()
    082    {
    083        return this.getSize() * this.slotHeight + this.field_27261_r;
    084    }
    085
    086    protected abstract void drawBackground();
    087
    088    protected abstract void drawSlot(int var1, int var2, int var3, int var4, Tessellator var5);
    089
    090    protected void func_27260_a(int p_27260_1_, int p_27260_2_, Tessellator p_27260_3_) {}
    091
    092    protected void func_27255_a(int p_27255_1_, int p_27255_2_) {}
    093
    094    protected void func_27257_b(int p_27257_1_, int p_27257_2_) {}
    095
    096    public int func_27256_c(int p_27256_1_, int p_27256_2_)
    097
    098    {
    099        int var3 = this.left + 1;
    100        int var4 = this.left + this.listWidth - 7;
    101        int var5 = p_27256_2_ - this.top - this.field_27261_r + (int)this.scrollDistance - 4;
    102        int var6 = var5 / this.slotHeight;
    103        return p_27256_1_ >= var3 && p_27256_1_ <= var4 && var6 >= 0 && var5 >= 0 && var6 < this.getSize() ? var6 : -1;
    104    }
    105
    106    public void registerScrollButtons(List p_22240_1_, int p_22240_2_, int p_22240_3_)
    107    {
    108        this.scrollUpActionId = p_22240_2_;
    109        this.scrollDownActionId = p_22240_3_;
    110    }
    111
    112    private void applyScrollLimits()
    113    {
    114        int var1 = this.getContentHeight() - (this.bottom - this.top - 4);
    115
    116        if (var1 < 0)
    117        {
    118            var1 /= 2;
    119        }
    120
    121        if (this.scrollDistance < 0.0F)
    122        {
    123            this.scrollDistance = 0.0F;
    124        }
    125
    126        if (this.scrollDistance > (float)var1)
    127        {
    128            this.scrollDistance = (float)var1;
    129        }
    130    }
    131
    132    public void actionPerformed(GuiButton button)
    133    {
    134        if (button.enabled)
    135        {
    136            if (button.id == this.scrollUpActionId)
    137            {
    138                this.scrollDistance -= (float)(this.slotHeight * 2 / 3);
    139                this.initialMouseClickY = -2.0F;
    140                this.applyScrollLimits();
    141            }
    142            else if (button.id == this.scrollDownActionId)
    143            {
    144                this.scrollDistance += (float)(this.slotHeight * 2 / 3);
    145                this.initialMouseClickY = -2.0F;
    146                this.applyScrollLimits();
    147            }
    148        }
    149    }
    150
    151    public void drawScreen(int mouseX, int mouseY, float p_22243_3_)
    152    {
    153        this.mouseX = mouseX;
    154        this.mouseY = mouseY;
    155        this.drawBackground();
    156        int listLength = this.getSize();
    157        int scrollBarXStart = this.left + this.listWidth - 6;
    158        int scrollBarXEnd = scrollBarXStart + 6;
    159        int boxLeft = this.left;
    160        int boxRight = scrollBarXStart-1;
    161        int var10;
    162        int var11;
    163        int var13;
    164        int var19;
    165
    166        if (Mouse.isButtonDown(0))
    167        {
    168            if (this.initialMouseClickY == -1.0F)
    169            {
    170                boolean var7 = true;
    171
    172                if (mouseY >= this.top && mouseY <= this.bottom)
    173                {
    174                    var10 = mouseY - this.top - this.field_27261_r + (int)this.scrollDistance - 4;
    175                    var11 = var10 / this.slotHeight;
    176
    177                    if (mouseX >= boxLeft && mouseX <= boxRight && var11 >= 0 && var10 >= 0 && var11 < listLength)
    178                    {
    179                        boolean var12 = var11 == this.selectedIndex && System.currentTimeMillis() - this.lastClickTime < 250L;
    180                        this.elementClicked(var11, var12);
    181                        this.selectedIndex = var11;
    182                        this.lastClickTime = System.currentTimeMillis();
    183                    }
    184                    else if (mouseX >= boxLeft && mouseX <= boxRight && var10 < 0)
    185                    {
    186                        this.func_27255_a(mouseX - boxLeft, mouseY - this.top + (int)this.scrollDistance - 4);
    187                        var7 = false;
    188                    }
    189
    190                    if (mouseX >= scrollBarXStart && mouseX <= scrollBarXEnd)
    191                    {
    192                        this.scrollFactor = -1.0F;
    193                        var19 = this.getContentHeight() - (this.bottom - this.top - 4);
    194
    195                        if (var19 < 1)
    196                        {
    197                            var19 = 1;
    198                        }
    199
    200                        var13 = (int)((float)((this.bottom - this.top) * (this.bottom - this.top)) / (float)this.getContentHeight());
    201
    202                        if (var13 < 32)
    203                        {
    204                            var13 = 32;
    205                        }
    206
    207                        if (var13 > this.bottom - this.top - 8)
    208                        {
    209                            var13 = this.bottom - this.top - 8;
    210                        }
    211
    212                        this.scrollFactor /= (float)(this.bottom - this.top - var13) / (float)var19;
    213                    }
    214                    else
    215                    {
    216                        this.scrollFactor = 1.0F;
    217                    }
    218
    219                    if (var7)
    220                    {
    221                        this.initialMouseClickY = (float)mouseY;
    222                    }
    223                    else
    224                    {
    225                        this.initialMouseClickY = -2.0F;
    226                    }
    227                }
    228                else
    229                {
    230                    this.initialMouseClickY = -2.0F;
    231                }
    232            }
    233            else if (this.initialMouseClickY >= 0.0F)
    234            {
    235                this.scrollDistance -= ((float)mouseY - this.initialMouseClickY) * this.scrollFactor;
    236                this.initialMouseClickY = (float)mouseY;
    237            }
    238        }
    239        else
    240        {
    241            while (Mouse.next())
    242            {
    243                int var16 = Mouse.getEventDWheel();
    244
    245                if (var16 != 0)
    246                {
    247                    if (var16 > 0)
    248                    {
    249                        var16 = -1;
    250                    }
    251                    else if (var16 < 0)
    252                    {
    253                        var16 = 1;
    254                    }
    255
    256                    this.scrollDistance += (float)(var16 * this.slotHeight / 2);
    257                }
    258            }
    259
    260            this.initialMouseClickY = -1.0F;
    261        }
    262
    263        this.applyScrollLimits();
    264        GL11.glDisable(GL11.GL_LIGHTING);
    265        GL11.glDisable(GL11.GL_FOG);
    266        Tessellator var18 = Tessellator.instance;
    267        this.client.renderEngine.bindTexture("/gui/background.png");
    268        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    269        float var17 = 32.0F;
    270        var18.startDrawingQuads();
    271        var18.setColorOpaque_I(2105376);
    272        var18.addVertexWithUV((double)this.left, (double)this.bottom, 0.0D, (double)((float)this.left / var17), (double)((float)(this.bottom + (int)this.scrollDistance) / var17));
    273        var18.addVertexWithUV((double)this.right, (double)this.bottom, 0.0D, (double)((float)this.right / var17), (double)((float)(this.bottom + (int)this.scrollDistance) / var17));
    274        var18.addVertexWithUV((double)this.right, (double)this.top, 0.0D, (double)((float)this.right / var17), (double)((float)(this.top + (int)this.scrollDistance) / var17));
    275        var18.addVertexWithUV((double)this.left, (double)this.top, 0.0D, (double)((float)this.left / var17), (double)((float)(this.top + (int)this.scrollDistance) / var17));
    276        var18.draw();
    277//        boxRight = this.listWidth / 2 - 92 - 16;
    278        var10 = this.top + 4 - (int)this.scrollDistance;
    279
    280        if (this.field_27262_q)
    281        {
    282            this.func_27260_a(boxRight, var10, var18);
    283        }
    284
    285        int var14;
    286
    287        for (var11 = 0; var11 < listLength; ++var11)
    288        {
    289            var19 = var10 + var11 * this.slotHeight + this.field_27261_r;
    290            var13 = this.slotHeight - 4;
    291
    292            if (var19 <= this.bottom && var19 + var13 >= this.top)
    293            {
    294                if (this.field_25123_p && this.isSelected(var11))
    295                {
    296                    var14 = boxLeft;
    297                    int var15 = boxRight;
    298                    GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    299                    GL11.glDisable(GL11.GL_TEXTURE_2D);
    300                    var18.startDrawingQuads();
    301                    var18.setColorOpaque_I(8421504);
    302                    var18.addVertexWithUV((double)var14, (double)(var19 + var13 + 2), 0.0D, 0.0D, 1.0D);
    303                    var18.addVertexWithUV((double)var15, (double)(var19 + var13 + 2), 0.0D, 1.0D, 1.0D);
    304                    var18.addVertexWithUV((double)var15, (double)(var19 - 2), 0.0D, 1.0D, 0.0D);
    305                    var18.addVertexWithUV((double)var14, (double)(var19 - 2), 0.0D, 0.0D, 0.0D);
    306                    var18.setColorOpaque_I(0);
    307                    var18.addVertexWithUV((double)(var14 + 1), (double)(var19 + var13 + 1), 0.0D, 0.0D, 1.0D);
    308                    var18.addVertexWithUV((double)(var15 - 1), (double)(var19 + var13 + 1), 0.0D, 1.0D, 1.0D);
    309                    var18.addVertexWithUV((double)(var15 - 1), (double)(var19 - 1), 0.0D, 1.0D, 0.0D);
    310                    var18.addVertexWithUV((double)(var14 + 1), (double)(var19 - 1), 0.0D, 0.0D, 0.0D);
    311                    var18.draw();
    312                    GL11.glEnable(GL11.GL_TEXTURE_2D);
    313                }
    314
    315                this.drawSlot(var11, boxRight, var19, var13, var18);
    316            }
    317        }
    318
    319        GL11.glDisable(GL11.GL_DEPTH_TEST);
    320        byte var20 = 4;
    321        this.overlayBackground(0, this.top, 255, 255);
    322        this.overlayBackground(this.bottom, this.listHeight, 255, 255);
    323        GL11.glEnable(GL11.GL_BLEND);
    324        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
    325        GL11.glDisable(GL11.GL_ALPHA_TEST);
    326        GL11.glShadeModel(GL11.GL_SMOOTH);
    327        GL11.glDisable(GL11.GL_TEXTURE_2D);
    328        var18.startDrawingQuads();
    329        var18.setColorRGBA_I(0, 0);
    330        var18.addVertexWithUV((double)this.left, (double)(this.top + var20), 0.0D, 0.0D, 1.0D);
    331        var18.addVertexWithUV((double)this.right, (double)(this.top + var20), 0.0D, 1.0D, 1.0D);
    332        var18.setColorRGBA_I(0, 255);
    333        var18.addVertexWithUV((double)this.right, (double)this.top, 0.0D, 1.0D, 0.0D);
    334        var18.addVertexWithUV((double)this.left, (double)this.top, 0.0D, 0.0D, 0.0D);
    335        var18.draw();
    336        var18.startDrawingQuads();
    337        var18.setColorRGBA_I(0, 255);
    338        var18.addVertexWithUV((double)this.left, (double)this.bottom, 0.0D, 0.0D, 1.0D);
    339        var18.addVertexWithUV((double)this.right, (double)this.bottom, 0.0D, 1.0D, 1.0D);
    340        var18.setColorRGBA_I(0, 0);
    341        var18.addVertexWithUV((double)this.right, (double)(this.bottom - var20), 0.0D, 1.0D, 0.0D);
    342        var18.addVertexWithUV((double)this.left, (double)(this.bottom - var20), 0.0D, 0.0D, 0.0D);
    343        var18.draw();
    344        var19 = this.getContentHeight() - (this.bottom - this.top - 4);
    345
    346        if (var19 > 0)
    347        {
    348            var13 = (this.bottom - this.top) * (this.bottom - this.top) / this.getContentHeight();
    349
    350            if (var13 < 32)
    351            {
    352                var13 = 32;
    353            }
    354
    355            if (var13 > this.bottom - this.top - 8)
    356            {
    357                var13 = this.bottom - this.top - 8;
    358            }
    359
    360            var14 = (int)this.scrollDistance * (this.bottom - this.top - var13) / var19 + this.top;
    361
    362            if (var14 < this.top)
    363            {
    364                var14 = this.top;
    365            }
    366
    367            var18.startDrawingQuads();
    368            var18.setColorRGBA_I(0, 255);
    369            var18.addVertexWithUV((double)scrollBarXStart, (double)this.bottom, 0.0D, 0.0D, 1.0D);
    370            var18.addVertexWithUV((double)scrollBarXEnd, (double)this.bottom, 0.0D, 1.0D, 1.0D);
    371            var18.addVertexWithUV((double)scrollBarXEnd, (double)this.top, 0.0D, 1.0D, 0.0D);
    372            var18.addVertexWithUV((double)scrollBarXStart, (double)this.top, 0.0D, 0.0D, 0.0D);
    373            var18.draw();
    374            var18.startDrawingQuads();
    375            var18.setColorRGBA_I(8421504, 255);
    376            var18.addVertexWithUV((double)scrollBarXStart, (double)(var14 + var13), 0.0D, 0.0D, 1.0D);
    377            var18.addVertexWithUV((double)scrollBarXEnd, (double)(var14 + var13), 0.0D, 1.0D, 1.0D);
    378            var18.addVertexWithUV((double)scrollBarXEnd, (double)var14, 0.0D, 1.0D, 0.0D);
    379            var18.addVertexWithUV((double)scrollBarXStart, (double)var14, 0.0D, 0.0D, 0.0D);
    380            var18.draw();
    381            var18.startDrawingQuads();
    382            var18.setColorRGBA_I(12632256, 255);
    383            var18.addVertexWithUV((double)scrollBarXStart, (double)(var14 + var13 - 1), 0.0D, 0.0D, 1.0D);
    384            var18.addVertexWithUV((double)(scrollBarXEnd - 1), (double)(var14 + var13 - 1), 0.0D, 1.0D, 1.0D);
    385            var18.addVertexWithUV((double)(scrollBarXEnd - 1), (double)var14, 0.0D, 1.0D, 0.0D);
    386            var18.addVertexWithUV((double)scrollBarXStart, (double)var14, 0.0D, 0.0D, 0.0D);
    387            var18.draw();
    388        }
    389
    390        this.func_27257_b(mouseX, mouseY);
    391        GL11.glEnable(GL11.GL_TEXTURE_2D);
    392        GL11.glShadeModel(GL11.GL_FLAT);
    393        GL11.glEnable(GL11.GL_ALPHA_TEST);
    394        GL11.glDisable(GL11.GL_BLEND);
    395    }
    396
    397    private void overlayBackground(int p_22239_1_, int p_22239_2_, int p_22239_3_, int p_22239_4_)
    398    {
    399        Tessellator var5 = Tessellator.instance;
    400        this.client.renderEngine.bindTexture("/gui/background.png");
    401        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    402        float var6 = 32.0F;
    403        var5.startDrawingQuads();
    404        var5.setColorRGBA_I(4210752, p_22239_4_);
    405        var5.addVertexWithUV(0.0D, (double)p_22239_2_, 0.0D, 0.0D, (double)((float)p_22239_2_ / var6));
    406        var5.addVertexWithUV((double)this.listWidth + 30, (double)p_22239_2_, 0.0D, (double)((float)(this.listWidth + 30) / var6), (double)((float)p_22239_2_ / var6));
    407        var5.setColorRGBA_I(4210752, p_22239_3_);
    408        var5.addVertexWithUV((double)this.listWidth + 30, (double)p_22239_1_, 0.0D, (double)((float)(this.listWidth + 30) / var6), (double)((float)p_22239_1_ / var6));
    409        var5.addVertexWithUV(0.0D, (double)p_22239_1_, 0.0D, 0.0D, (double)((float)p_22239_1_ / var6));
    410        var5.draw();
    411    }
    412}