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.func_98187_b("/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.func_98187_b("/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}