mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-11-15 17:54:50 +00:00
419 lines
13 KiB
Java
419 lines
13 KiB
Java
package codechicken.nei.scroll;
|
|
|
|
import java.awt.Point;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.function.Predicate;
|
|
|
|
import org.lwjgl.input.Keyboard;
|
|
import org.lwjgl.opengl.GL11;
|
|
|
|
import codechicken.lib.gui.GuiDraw;
|
|
import codechicken.lib.vec.Rectangle4i;
|
|
import codechicken.nei.NEIClientUtils;
|
|
import codechicken.nei.Widget;
|
|
import codechicken.nei.WidgetContainer;
|
|
import codechicken.nei.scroll.ScrollBar.OverflowType;
|
|
import codechicken.nei.scroll.ScrollBar.ScrollPlace;
|
|
import codechicken.nei.scroll.ScrollBar.ScrollType;
|
|
|
|
public class ScrollContainer extends WidgetContainer {
|
|
|
|
/** The mouse scroll wheel scroll speed */
|
|
protected static final int MOUSE_SCROLL_SPEED = 16;
|
|
|
|
/** The keyboard arrow keys scroll speed */
|
|
protected static final int KEYBOARD_SCROLL_SPEED = 36;
|
|
|
|
/** The scrollbar will fade away over this many ticks */
|
|
protected static final int FADE_TICKS = 24;
|
|
|
|
protected int xScroll = 0;
|
|
protected int yScroll = 0;
|
|
|
|
protected int actualWidth = 0;
|
|
protected int actualHeight = 0;
|
|
|
|
protected int marginInline = 0;
|
|
protected int marginBlock = 0;
|
|
|
|
protected final Map<Widget, Point> relativePostion = new HashMap<>();
|
|
protected ScrollBar horizontalScrollBar;
|
|
protected ScrollBar verticalScrollBar;
|
|
protected int fade = 0;
|
|
|
|
public Rectangle4i boundsOutside() {
|
|
int width = this.w;
|
|
int height = this.h;
|
|
|
|
if (canScrollVertical() && (this.verticalScrollBar.getOverflowType() == OverflowType.SCROLL
|
|
|| this.verticalScrollBar.getOverflowType() == OverflowType.AUTO)) {
|
|
width += this.verticalScrollBar.getMargin();
|
|
|
|
if (this.verticalScrollBar.getScrollPlace() == ScrollPlace.OUTSIDE) {
|
|
width += this.verticalScrollBar.getScrollbarSize();
|
|
}
|
|
}
|
|
|
|
if (canScrollHorizontal() && (this.horizontalScrollBar.getOverflowType() == OverflowType.SCROLL
|
|
|| this.horizontalScrollBar.getOverflowType() == OverflowType.AUTO)) {
|
|
height += this.horizontalScrollBar.getMargin();
|
|
|
|
if (this.horizontalScrollBar.getScrollPlace() == ScrollPlace.OUTSIDE) {
|
|
height += this.horizontalScrollBar.getScrollbarSize();
|
|
}
|
|
}
|
|
|
|
return new Rectangle4i(x, y, width, height);
|
|
}
|
|
|
|
public Rectangle4i boundsInside() {
|
|
return new Rectangle4i(x, y, getVisibleWidth(), getVisibleHeight());
|
|
}
|
|
|
|
@Override
|
|
public void clear() {
|
|
super.clear();
|
|
this.relativePostion.clear();
|
|
}
|
|
|
|
@Override
|
|
public boolean removeIf(Predicate<Widget> filter) {
|
|
this.relativePostion.keySet().removeIf(filter);
|
|
return super.removeIf(filter);
|
|
}
|
|
|
|
public void addWidget(Widget widget) {
|
|
super.addWidget(widget);
|
|
this.relativePostion.put(widget, new Point(widget.x, widget.y));
|
|
}
|
|
|
|
public Point getWidgetPosition(Widget widget) {
|
|
return this.relativePostion.get(widget);
|
|
}
|
|
|
|
public void setMarginInline(int marginInline) {
|
|
this.marginInline = marginInline;
|
|
}
|
|
|
|
public void setMarginBlock(int marginBlock) {
|
|
this.marginBlock = marginBlock;
|
|
}
|
|
|
|
public int getMarginInline() {
|
|
return this.marginInline;
|
|
}
|
|
|
|
public int getMarginBlock() {
|
|
return this.marginBlock;
|
|
}
|
|
|
|
public int getVisibleWidth() {
|
|
|
|
if (canScrollVertical() && this.verticalScrollBar.getScrollPlace() == ScrollPlace.INSIDE
|
|
&& (this.verticalScrollBar.getOverflowType() == OverflowType.SCROLL
|
|
|| this.verticalScrollBar.getOverflowType() == OverflowType.AUTO)) {
|
|
return this.w - this.verticalScrollBar.getScrollbarSize();
|
|
}
|
|
|
|
return this.w;
|
|
}
|
|
|
|
public int getActualWidth() {
|
|
return this.actualWidth;
|
|
}
|
|
|
|
public boolean setHorizontalScrollOffset(int offset) {
|
|
|
|
if (!canScrollHorizontal() && this.w < getActualWidth()) {
|
|
offset = 0;
|
|
}
|
|
|
|
final int scroll = this.xScroll;
|
|
this.xScroll = Math.max(0, Math.min(getActualWidth() - getVisibleWidth(), offset));
|
|
|
|
if (scroll != this.xScroll) {
|
|
|
|
for (Widget widget : this.widgets) {
|
|
widget.x += scroll - this.xScroll;
|
|
}
|
|
|
|
this.fade = FADE_TICKS;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public int getHorizontalScrollOffset() {
|
|
return this.xScroll;
|
|
}
|
|
|
|
public boolean canScrollHorizontal() {
|
|
return this.horizontalScrollBar != null
|
|
&& (this.horizontalScrollBar.getOverflowType() != OverflowType.NONE && this.w < getActualWidth()
|
|
|| this.horizontalScrollBar.getOverflowType() == OverflowType.SCROLL);
|
|
}
|
|
|
|
public ScrollBar getHorizontalScroll() {
|
|
return this.horizontalScrollBar;
|
|
}
|
|
|
|
public ScrollContainer setHorizontalScroll() {
|
|
return setHorizontalScroll(ScrollBar.defaultScrollBar());
|
|
}
|
|
|
|
public ScrollContainer setHorizontalScroll(ScrollBar scrollBar) {
|
|
this.horizontalScrollBar = scrollBar;
|
|
|
|
if (this.horizontalScrollBar != null) {
|
|
this.horizontalScrollBar.setScrollType(ScrollType.HORIZONTAL);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
public int getVisibleHeight() {
|
|
|
|
if (canScrollHorizontal() && this.horizontalScrollBar.getScrollPlace() == ScrollPlace.INSIDE
|
|
&& (this.horizontalScrollBar.getOverflowType() == OverflowType.SCROLL
|
|
|| this.horizontalScrollBar.getOverflowType() == OverflowType.AUTO)) {
|
|
return this.h - this.horizontalScrollBar.getScrollbarSize();
|
|
}
|
|
|
|
return this.h;
|
|
}
|
|
|
|
public int getActualHeight() {
|
|
return this.actualHeight;
|
|
}
|
|
|
|
public boolean setVerticalScrollOffset(int offset) {
|
|
|
|
if (!canScrollVertical() && this.h < getActualHeight()) {
|
|
offset = 0;
|
|
}
|
|
|
|
final int scroll = this.yScroll;
|
|
this.yScroll = Math.max(0, Math.min(getActualHeight() - getVisibleHeight(), offset));
|
|
|
|
if (scroll != this.yScroll) {
|
|
|
|
for (Widget widget : this.widgets) {
|
|
widget.y += scroll - this.yScroll;
|
|
}
|
|
|
|
this.fade = FADE_TICKS;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public int getVerticalScrollOffset() {
|
|
return this.yScroll;
|
|
}
|
|
|
|
public boolean canScrollVertical() {
|
|
return this.verticalScrollBar != null
|
|
&& (this.verticalScrollBar.getOverflowType() != OverflowType.NONE && this.h < getActualHeight()
|
|
|| this.verticalScrollBar.getOverflowType() == OverflowType.SCROLL);
|
|
}
|
|
|
|
public ScrollBar getVerticalScroll() {
|
|
return this.verticalScrollBar;
|
|
}
|
|
|
|
public ScrollContainer setVerticalScroll() {
|
|
return setVerticalScroll(ScrollBar.defaultScrollBar());
|
|
}
|
|
|
|
public ScrollContainer setVerticalScroll(ScrollBar scrollBar) {
|
|
this.verticalScrollBar = scrollBar;
|
|
|
|
if (this.verticalScrollBar != null) {
|
|
this.verticalScrollBar.setScrollType(ScrollType.VERTICAL);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public void draw(int mousex, int mousey) {
|
|
final boolean canScrollVertical = canScrollVertical();
|
|
final boolean canScrollHorizontal = canScrollHorizontal();
|
|
|
|
if (canScrollVertical || canScrollHorizontal) {
|
|
GuiHelper.useScissor(
|
|
this.x,
|
|
this.y,
|
|
getVisibleWidth(),
|
|
getVisibleHeight(),
|
|
() -> drawContent(mousex, mousey));
|
|
|
|
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
|
|
|
if (canScrollVertical) {
|
|
this.verticalScrollBar.draw(this, mousex, mousey, getScrollBarOpacity());
|
|
}
|
|
|
|
if (canScrollHorizontal) {
|
|
this.horizontalScrollBar.draw(this, mousex, mousey, getScrollBarOpacity());
|
|
}
|
|
|
|
GL11.glPopAttrib();
|
|
} else {
|
|
drawContent(mousex, mousey);
|
|
}
|
|
|
|
}
|
|
|
|
protected void drawContent(int mousex, int mousey) {
|
|
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
|
GL11.glPushMatrix();
|
|
GL11.glColor4f(1, 1, 1, 1);
|
|
|
|
super.draw(mousex, mousey);
|
|
|
|
GL11.glPopMatrix();
|
|
GL11.glPopAttrib();
|
|
}
|
|
|
|
private float getScrollBarOpacity() {
|
|
return Math.min(2f * this.fade, FADE_TICKS) / FADE_TICKS;
|
|
}
|
|
|
|
@Override
|
|
public void update() {
|
|
this.actualHeight = 0;
|
|
this.actualWidth = 0;
|
|
|
|
for (Map.Entry<Widget, Point> entry : this.relativePostion.entrySet()) {
|
|
entry.getKey().x = entry.getValue().x;
|
|
entry.getKey().y = entry.getValue().y;
|
|
}
|
|
|
|
super.update();
|
|
|
|
for (Widget widget : this.widgets) {
|
|
this.actualWidth = Math.max(this.actualWidth, widget.x + widget.w + this.marginInline * 2);
|
|
this.actualHeight = Math.max(this.actualHeight, widget.y + widget.h + this.marginBlock * 2);
|
|
|
|
widget.x += this.marginInline + this.x - this.xScroll;
|
|
widget.y += this.marginBlock + this.y - this.yScroll;
|
|
}
|
|
|
|
if (this.fade > 0) {
|
|
final Point mouse = GuiDraw.getMousePosition();
|
|
|
|
if (canScrollVertical() && (this.verticalScrollBar.isMouseDragged()
|
|
|| this.verticalScrollBar.trackBounds(this).contains(mouse.x, mouse.y))) {
|
|
this.fade = FADE_TICKS;
|
|
} else if (canScrollHorizontal() && (this.horizontalScrollBar.isMouseDragged()
|
|
|| this.horizontalScrollBar.trackBounds(this).contains(mouse.x, mouse.y))) {
|
|
this.fade = FADE_TICKS;
|
|
} else {
|
|
this.fade--;
|
|
}
|
|
}
|
|
|
|
setHorizontalScrollOffset(this.xScroll);
|
|
setVerticalScrollOffset(this.yScroll);
|
|
}
|
|
|
|
@Override
|
|
public boolean onMouseWheel(int direction, int mousex, int mousey) {
|
|
|
|
if (super.onMouseWheel(direction, mousex, mousey)) {
|
|
return true;
|
|
}
|
|
|
|
if (boundsOutside().contains(mousex, mousey)) {
|
|
|
|
if (canScrollHorizontal() && (NEIClientUtils.shiftKey()
|
|
|| this.horizontalScrollBar.trackBounds(this).contains(mousex, mousey))) {
|
|
this.horizontalScrollBar.setScrollOffset(this, this.xScroll - direction * MOUSE_SCROLL_SPEED);
|
|
return true;
|
|
}
|
|
|
|
if (canScrollVertical()) {
|
|
this.verticalScrollBar.setScrollOffset(this, this.yScroll - direction * MOUSE_SCROLL_SPEED);
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean handleClick(int mousex, int mousey, int button) {
|
|
|
|
if (canScrollVertical() && this.verticalScrollBar.onClick(this, mousex, mousey, button)) {
|
|
return true;
|
|
}
|
|
|
|
if (canScrollHorizontal() && this.horizontalScrollBar.onClick(this, mousex, mousey, button)) {
|
|
return true;
|
|
}
|
|
|
|
if (super.handleClick(mousex, mousey, button)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void mouseDragged(int mousex, int mousey, int button, long heldTime) {
|
|
|
|
if (canScrollVertical() && this.verticalScrollBar.onMouseDragged(this, mousex, mousey, button, heldTime)) {
|
|
return;
|
|
}
|
|
|
|
if (canScrollHorizontal() && this.horizontalScrollBar.onMouseDragged(this, mousex, mousey, button, heldTime)) {
|
|
return;
|
|
}
|
|
|
|
super.mouseDragged(mousex, mousey, button, heldTime);
|
|
}
|
|
|
|
@Override
|
|
public void mouseUp(int mousex, int mousey, int button) {
|
|
|
|
if (canScrollVertical()) {
|
|
this.verticalScrollBar.onClickReleased(this, mousex, mousey, button);
|
|
}
|
|
|
|
if (canScrollHorizontal()) {
|
|
this.horizontalScrollBar.onClickReleased(this, mousex, mousey, button);
|
|
}
|
|
|
|
super.mouseUp(mousex, mousey, button);
|
|
}
|
|
|
|
@Override
|
|
public boolean handleKeyPress(int keyCode, char keyChar) {
|
|
|
|
if (this.isFocused()) {
|
|
switch (keyCode) {
|
|
case Keyboard.KEY_UP:
|
|
return canScrollVertical()
|
|
&& this.verticalScrollBar.setScrollOffset(this, this.yScroll - KEYBOARD_SCROLL_SPEED);
|
|
case Keyboard.KEY_DOWN:
|
|
return canScrollVertical()
|
|
&& this.verticalScrollBar.setScrollOffset(this, this.yScroll + KEYBOARD_SCROLL_SPEED);
|
|
case Keyboard.KEY_LEFT:
|
|
return canScrollHorizontal()
|
|
&& this.horizontalScrollBar.setScrollOffset(this, this.xScroll - KEYBOARD_SCROLL_SPEED);
|
|
case Keyboard.KEY_RIGHT:
|
|
return canScrollHorizontal()
|
|
&& this.horizontalScrollBar.setScrollOffset(this, this.xScroll + KEYBOARD_SCROLL_SPEED);
|
|
}
|
|
}
|
|
|
|
return super.handleKeyPress(keyCode, keyChar);
|
|
}
|
|
|
|
}
|