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}