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