diff options
author | syeyoung <cyong06@naver.com> | 2021-07-21 00:08:48 +0900 |
---|---|---|
committer | syeyoung <cyong06@naver.com> | 2021-07-21 00:34:14 +0900 |
commit | a6009e4aef3a8f8b641733d62034bf629afd7053 (patch) | |
tree | e23467327f1e9ddc2ffcdc4604e6d5fbb1ccecf2 /src/main | |
parent | aa804403a1dcc8f9b36672e0e56e591e810147b3 (diff) | |
download | Skyblock-Dungeons-Guide-a6009e4aef3a8f8b641733d62034bf629afd7053.tar.gz Skyblock-Dungeons-Guide-a6009e4aef3a8f8b641733d62034bf629afd7053.tar.bz2 Skyblock-Dungeons-Guide-a6009e4aef3a8f8b641733d62034bf629afd7053.zip |
Add Scroll Bar and Scrollable Panel
Diffstat (limited to 'src/main')
4 files changed, 403 insertions, 1 deletions
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/gui/MPanel.java b/src/main/java/kr/syeyoung/dungeonsguide/gui/MPanel.java index aa949d16..319a7af8 100644 --- a/src/main/java/kr/syeyoung/dungeonsguide/gui/MPanel.java +++ b/src/main/java/kr/syeyoung/dungeonsguide/gui/MPanel.java @@ -104,6 +104,11 @@ public class MPanel { } protected Point lastParentPoint; + + @Getter + @Setter + private boolean ignoreBoundOnClip; + public void render0(ScaledResolution resolution, Point parentPoint, Rectangle parentClip, int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks) { // 0,0 - a a lastParentPoint = parentPoint; @@ -116,7 +121,9 @@ public class MPanel { Rectangle absBound = getBounds().getBounds(); absBound.setLocation(absBound.x + parentPoint.x, absBound.y + parentPoint.y); - Rectangle clip = determineClip(parentClip, absBound); + Rectangle clip; + if (ignoreBoundOnClip) clip = parentClip; + else clip = determineClip(parentClip, absBound); lastAbsClip = clip; if (clip.getSize().height * clip.getSize().width == 0) return; diff --git a/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MList.java b/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MList.java new file mode 100644 index 00000000..de3e4b40 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MList.java @@ -0,0 +1,69 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import net.minecraft.client.gui.Gui; + +import java.awt.*; + +public class MList extends MPanel { + @Getter + private int gap = 5; + + public void setGap(int gap) { + this.gap = gap; + realignChildren(); + } + + private final int gapLineColor = 0xFFFFFFFF; + + protected void realignChildren() { + int y = 0; + for (MPanel childComponent : getChildComponents()) { + Dimension preferedSize = childComponent.getPreferredSize(); + childComponent.setBounds(new Rectangle(0, y, bounds.width, Math.max(10, preferedSize.height))); + y += preferedSize.height; + y += gap; + } + setSize(new Dimension(getSize().width, Math.max(0, y-gap))); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + for (int i = 1; i < getChildComponents().size(); i++) { + MPanel panel = getChildComponents().get(i); + Rectangle bound = panel.getBounds(); + Gui.drawRect(0,bound.y - (gap/2), getBounds().width, bound.y - (gap/2)+1, gapLineColor); + } + } + + @Override + public void add(MPanel child) { + super.add(child); + realignChildren(); + } + + @Override + public void remove(MPanel panel) { + super.remove(panel); + realignChildren(); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MScrollBar.java b/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MScrollBar.java new file mode 100644 index 00000000..ecd94b07 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MScrollBar.java @@ -0,0 +1,145 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.gui.Gui; +import net.minecraft.util.MathHelper; + +import java.awt.*; + +public class MScrollBar extends MPanel { + private final Axis axis; + @Setter + @Getter + private int thumbSize, max, min; + @Setter + @Getter + private int current; + + public void addToCurrent(int dv) { + int current2 = current + dv; + + current = MathHelper.clamp_int(current2, min, max - thumbSize); + if (max - min < thumbSize) current = min; + + if (onUpdate != null) onUpdate.run(); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(axis == Axis.X ? -1 : 20, axis == Axis.Y ? -1 : 20); + } + + @Getter + @Setter + private int background = RenderUtils.blendAlpha(0xFF141414, 0.04f), + thumb = RenderUtils.blendAlpha(0xFF141414, 0.08f), + thumbHover = RenderUtils.blendAlpha(0xFF141414, 0.09f), + thumbClick = RenderUtils.blendAlpha(0xFF141414, 0.14f); + + private Runnable onUpdate; + + public MScrollBar(int min, int max, int thumbSize, int current, Axis axis, Runnable onUpdate) { + this.min = min; this.min = max; this.thumbSize = thumbSize; this.current = current; this.axis = axis; + this.current = MathHelper.clamp_int(current, min, max - thumbSize); + if (max - min < thumbSize) this.current = min; + this.onUpdate = onUpdate; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + // RENDER SUPER NICE SCROLL BAR + Gui.drawRect(0,0,getBounds().width, getBounds().height, background); + double startPerc, endPerc; + if (max - min == 0) { + startPerc =0; endPerc = 1; + } else { + startPerc = (current - min)/((double)max - min); + endPerc = (current+thumbSize - min)/((double)max - min); + } + + int color = thumbHover; + if (getBounds().contains(relMousex0, relMousey0)) color = thumbHover; + if (grabbed) color = thumbClick; + + if (axis == Axis.X) { + int startX = (int) (startPerc * getBounds().width); + int endX = (int) (endPerc * getBounds().width); + endX = Math.max(endX, startX + 20); + + Gui.drawRect(startX,0,endX,getBounds().height, color); + } else if (axis == Axis.Y) { + int startY = (int) (startPerc * getBounds().height); + int endY = (int) (endPerc * getBounds().height); + endY = Math.max(endY, startY + 20); + + Gui.drawRect(0,startY,getBounds().width,endY, color); + } + } + + private int lastX; + private int lastY; + private int actualValue; + private boolean grabbed; + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (!lastAbsClip.contains(absMouseX, absMouseY)) return; + if (getTooltipsOpen() > 0) return; + grabbed = true; + actualValue = current; + lastX = absMouseX; + lastY = absMouseY; + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + if (!grabbed) return; + int dx = absMouseX - lastX, dy = absMouseY - lastY; + + lastX = absMouseX; + lastY = absMouseY; + + int prevVal = current; + + if (axis == Axis.Y) { + actualValue += dy * (max - min) / getBounds().height; + } else if (axis == Axis.X) { + actualValue += dx * (max - min) / getBounds().width; + } + + current = MathHelper.clamp_int(actualValue, min, max - thumbSize); + if (max - min < thumbSize) current = min; + + if (onUpdate != null && prevVal != current) onUpdate.run(); + } + + @Override + public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) { + grabbed= false; + } + + public static enum Axis { + X, Y + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MScrollablePanel.java b/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MScrollablePanel.java new file mode 100644 index 00000000..ffdab32b --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MScrollablePanel.java @@ -0,0 +1,181 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.gui.Gui; +import net.minecraft.util.MathHelper; +import org.w3c.dom.css.Rect; + +import java.awt.*; + +public class MScrollablePanel extends MPanel { + @Getter + private boolean hideScrollBarWhenNotNecessary = false; + + public void setHideScrollBarWhenNotNecessary(boolean hideScrollBarWhenNotNecessary) { + this.hideScrollBarWhenNotNecessary = hideScrollBarWhenNotNecessary; + setBounds(getBounds()); + } + + private final int axis; // 1: Y 2: X 3: both. + + + private Dimension totalContentArea = new Dimension(); + + private MPanel viewPort; + @Getter + private MPanel contentArea; + @Getter + private MScrollBar scrollBarX, scrollBarY; + + private Rectangle contentAreaDim; + + public MScrollablePanel(int axis) { + this.axis = axis; + viewPort = new MPanel(); + scrollBarX = new MScrollBar(0, 1, 1, 0, MScrollBar.Axis.X, this::onScrollBarUpdate); + scrollBarY = new MScrollBar(0, 1, 1, 0, MScrollBar.Axis.Y, this::onScrollBarUpdate); + + if ((axis & 1) > 0) + super.add(scrollBarY); + if ((axis & 2) > 0) + super.add(scrollBarX); + super.add(viewPort); + + + contentArea = new MPanel() { + @Override + public void add(MPanel child) { + super.add(child); + evalulateContentArea(); + } + + @Override + public void remove(MPanel panel) { + super.remove(panel); + evalulateContentArea(); + } + + @Override + public void setBounds(Rectangle bounds) { + if (bounds == null) return; + this.bounds.x = bounds.x; + this.bounds.y = bounds.y; + this.bounds.width = bounds.width; + this.bounds.height = bounds.height; + + onBoundsUpdate(); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + for (MPanel childComponent : childComponents) { + childComponent.resize0(parentWidth, parentHeight); + } + evalulateContentArea(); + } + }; + viewPort.add(contentArea); + contentArea.setIgnoreBoundOnClip(true); + evalulateContentArea(); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + super.render(absMousex, absMousey, relMousex0, relMousey0, partialTicks, scissor); + + boolean hideX = false, hideY = false; + if (bounds.width > contentAreaDim.width && hideScrollBarWhenNotNecessary) hideX = true; + if (bounds.height > contentAreaDim.height && hideScrollBarWhenNotNecessary) hideY = true; + if (axis == 3 && !(hideX && hideY)) { + Gui.drawRect(scrollBarX.getBounds().width, scrollBarY.getBounds().height, getBounds().width, getBounds().height, RenderUtils.blendAlpha(0x141414, 0.03f)); + } + } + + private void evalulateContentArea() { + if (contentArea.getChildComponents().size() == 0) { + contentAreaDim= new Rectangle(0,0,0,0); + return; + } + int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE; + for (MPanel childComponent : contentArea.getChildComponents()) { + Rectangle bounds = childComponent.getBounds(); + if (bounds.x < minX) minX = bounds.x; + if (bounds.x + bounds.width > maxX) maxX = bounds.x + bounds.width; + if (bounds.y < minY) minY = bounds.y; + if (bounds.y + bounds.height > maxY) maxY = bounds.y + bounds.height; + } + contentAreaDim = new Rectangle(minX, minY, maxX - minX, maxY - minY); + scrollBarX.setMin(contentAreaDim.x); + scrollBarX.setMax(contentAreaDim.x + contentAreaDim.width); + scrollBarY.setMin(contentAreaDim.y); + scrollBarY.setMax(contentAreaDim.y + contentAreaDim.height); + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + boolean hideX = false, hideY = false; + if (bounds.width > contentAreaDim.width && hideScrollBarWhenNotNecessary) hideX = true; + if (bounds.height > contentAreaDim.height && hideScrollBarWhenNotNecessary) hideY = true; + + if (axis == 3 && !(hideX || hideY)) { + Dimension preferedX = scrollBarX.getPreferredSize(); + Dimension preferedY = scrollBarY.getPreferredSize(); + scrollBarY.setBounds(new Rectangle(bounds.width - preferedY.width, 0, preferedY.width, bounds.height - preferedX.height)); + scrollBarX.setBounds(new Rectangle(0, bounds.height - preferedX.height, bounds.width - preferedY.width, preferedX.height)); + } else if (axis == 2 || (axis == 3 && hideY)) { + Dimension preferedX = scrollBarX.getPreferredSize(); + scrollBarY.setBounds(new Rectangle(0,0,0,0)); + scrollBarX.setBounds(new Rectangle(0, bounds.height - preferedX.height, bounds.width, preferedX.height)); + } else if (axis == 1 || (axis == 3 && hideX)) { + Dimension preferedY = scrollBarY.getPreferredSize(); + scrollBarX.setBounds(new Rectangle(0,0,0,0)); + scrollBarY.setBounds(new Rectangle(bounds.width - preferedY.width, 0, preferedY.width, bounds.height)); + } + + viewPort.setBounds(new Rectangle(0,0,bounds.width-scrollBarY.getBounds().width, bounds.height - scrollBarX.getBounds().height)); + + scrollBarX.setThumbSize(viewPort.getBounds().width); + scrollBarY.setThumbSize(viewPort.getBounds().height); + } + + + private void onScrollBarUpdate() { + contentArea.setPosition(new Point(-scrollBarX.getCurrent(), -scrollBarY.getCurrent())); + } + + + @Override + public void add(MPanel child) { contentArea.add(child); } + + @Override + public void remove(MPanel panel) { contentArea.remove(panel); } + + @Override + public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if (lastAbsClip.contains(absMouseX, absMouseY) && (axis == 1 || axis == 3)) { + scrollBarY.addToCurrent(MathHelper.clamp_int(scrollAmount, -1, 1) * -30); + } + } +} |