package codechicken.core.gui; import codechicken.lib.math.MathHelper; import codechicken.lib.vec.Rectangle4i; import java.awt.*; public abstract class GuiScrollPane extends GuiWidget { protected int scrollclicky = -1; protected float scrollpercent; protected int scrollmousey; protected float percentscrolled; public int marginleft; public int margintop; public int marginright; public int marginbottom; public GuiScrollPane(int x, int y, int width, int height) { super(x, y, width, height); } public void setMargins(int left, int top, int right, int bottom) { marginleft = left; margintop = top; marginright = right; marginbottom = bottom; } public Rectangle windowBounds() { return new Rectangle(x + marginleft, y + margintop, width - marginleft - marginright, height - margintop - marginbottom); } public abstract int contentHeight(); public Dimension scrollbarDim() { int h = (int) ((windowBounds().getHeight() / contentHeight()) * height); return new Dimension(5, h > height ? height : h < height / 15 ? height / 15 : h); } public Rectangle scrollbarBounds() { Dimension dim = scrollbarDim(); return new Rectangle(x + width - dim.width, y + (int) ((height - dim.height) * percentscrolled + 0.4999), dim.width, dim.height); } public void scrollUp() { scroll(-5); } public void scrollDown() { scroll(5); } public void scroll(int i) { percentscrolled += i * height / (float) (2 * contentHeight()); calculatePercentScrolled(); } public void calculatePercentScrolled() { int barempty = height - scrollbarDim().height; if (isScrolling()) { int scrolldiff = scrollmousey - scrollclicky; percentscrolled = scrolldiff / (float) barempty + scrollpercent; } percentscrolled = (float) MathHelper.clip(percentscrolled, 0, 1); } public boolean isScrolling() { return scrollclicky >= 0; } public boolean hasScrollbar() { return contentHeight() > height; } /** * @return -1 for left, 0 for none, 1 for right */ public int scrollbarGuideAlignment() { return -1; } public void showSlot(int sloty, int slotHeight) { Rectangle w = windowBounds(); if (sloty + slotHeight > w.y + w.height) { int diff = sloty - (w.y + w.height - slotHeight); percentscrolled += diff / (double) (contentHeight() - w.height); calculatePercentScrolled(); } else if (sloty < w.y) { int diff = w.y - sloty; percentscrolled -= diff / (double) (contentHeight() - w.height); calculatePercentScrolled(); } } @Override public void mouseClicked(int mx, int my, int button) { Rectangle sbar = scrollbarBounds(); Rectangle w = windowBounds(); int barempty = height - sbar.height; if (button == 0 && sbar.height < height && //the scroll bar can move (not full length) mx >= sbar.x && mx <= sbar.x + sbar.width && my >= y && my <= y + height)//in the scroll pane { if (my < sbar.y) { percentscrolled = (my - y) / (float) barempty; calculatePercentScrolled(); } else if (my > sbar.y + sbar.height) { percentscrolled = (my - y - sbar.height + 1) / (float) barempty; calculatePercentScrolled(); } else { scrollclicky = my; scrollpercent = percentscrolled; scrollmousey = my; } } else if (w.contains(mx, my)) { slotDown(mx - w.x, my - w.y + scrolledPixels(), button); } } /** * Mouse down on slot area * Coordinates relative to slot content area */ public void slotDown(int mx, int my, int button) { } /** * Mouse up on slot area * Coordinates relative to slot content area */ public void slotUp(int mx, int my, int button) { } @Override public void mouseReleased(int mx, int my, int button) { Rectangle w = windowBounds(); if (isScrolling() && button == 0)//we were scrolling and we released mouse { scrollclicky = -1; } else if (w.contains(mx, my)) { slotUp(mx - w.x, my - w.y + scrolledPixels(), button); } } @Override public void mouseDragged(int mousex, int mousey, int button, long time) { if (isScrolling()) { int scrolldiff = mousey - scrollclicky; int sbarh = scrollbarDim().height; int barupallowed = (int) ((height - sbarh) * scrollpercent + 0.5); int bardownallowed = (height - sbarh) - barupallowed; if (-scrolldiff > barupallowed) { scrollmousey = scrollclicky - barupallowed; } else if (scrolldiff > bardownallowed) { scrollmousey = scrollclicky + bardownallowed; } else { scrollmousey = mousey; } calculatePercentScrolled(); } } public int scrolledPixels() { int scrolled = (int) ((contentHeight() - windowBounds().height) * percentscrolled + 0.5); if (scrolled < 0) { scrolled = 0; } return scrolled; } public Rectangle4i bounds() { return new Rectangle4i(x, y, width, height); } public boolean contains(int mx, int my) { return bounds().contains(mx, my); } @Override public void draw(int mx, int my, float frame) { Rectangle w = windowBounds(); drawBackground(frame); drawContent(mx - w.x, my + scrolledPixels() - w.y, frame); drawOverlay(frame); drawScrollbar(frame); } public void drawBackground(float frame) { drawRect(x, y, x + width, y + height, 0xff000000); } public abstract void drawContent(int mx, int my, float frame); public void drawOverlay(float frame) { //outlines drawRect(x, y - 1, x + width, y, 0xffa0a0a0);//top drawRect(x, y + height, x + width, y + height + 1, 0xffa0a0a0);//bottom drawRect(x - 1, y - 1, x, y + height + 1, 0xffa0a0a0);//left drawRect(x + width, y - 1, x + width + 1, y + height + 1, 0xffa0a0a0);//right } public void drawScrollbar(float frame) { Rectangle r = scrollbarBounds(); drawRect(r.x, r.y, r.x + r.width, r.y + r.height, 0xFF8B8B8B);//corners drawRect(r.x, r.y, r.x + r.width - 1, r.y + r.height - 1, 0xFFF0F0F0);//topleft up drawRect(r.x + 1, r.y + 1, r.x + r.width, r.y + r.height, 0xFF555555);//bottom right down drawRect(r.x + 1, r.y + 1, r.x + r.width - 1, r.y + r.height - 1, 0xFFC6C6C6);//scrollbar int algn = scrollbarGuideAlignment(); if (algn != 0) { drawRect(algn > 0 ? r.x + r.width : r.x - 1, y, r.x, y + height, 0xFF808080);//lineguide } } }