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