From 6907959d57777b2d3875d0e570d835f0ba9c1b57 Mon Sep 17 00:00:00 2001
From: Falkreon <falkreon@gmail.com>
Date: Wed, 28 Aug 2019 02:59:58 -0500
Subject: Dramatically improved scrollbars, coordinate fixes

---
 .../cotton/gui/client/ClientCottonScreen.java      |  30 +----
 .../cottonmc/cotton/gui/widget/WListPanel.java     | 132 +++++++++++----------
 .../github/cottonmc/cotton/gui/widget/WPanel.java  |  18 +++
 .../cottonmc/cotton/gui/widget/WScrollBar.java     |  67 +++--------
 .../github/cottonmc/cotton/gui/widget/WWidget.java |   7 ++
 5 files changed, 115 insertions(+), 139 deletions(-)

(limited to 'src/main/java')

diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/ClientCottonScreen.java b/src/main/java/io/github/cottonmc/cotton/gui/client/ClientCottonScreen.java
index 80ee311..16921cf 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/ClientCottonScreen.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/ClientCottonScreen.java
@@ -93,16 +93,6 @@ public class ClientCottonScreen extends Screen {
 	@Override
 	public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
 		if (description.getRootPanel()==null) return super.mouseClicked(mouseX, mouseY, mouseButton);
-		/*
-		boolean result = super.mouseClicked(mouseX, mouseY, mouseButton);
-		int containerX = (int)mouseX-left;
-		int containerY = (int)mouseY-top;
-		if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return result;
-		lastResponder = description.getRootPanel().onMouseDown(containerX, containerY, mouseButton);
-		
-		return result;*/
-		
-		
 		WWidget focus = description.getFocus();
 		if (focus!=null) {
 			
@@ -122,7 +112,8 @@ public class ClientCottonScreen extends Screen {
 		int containerY = (int)mouseY-top;
 		if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return result;
 		if (lastResponder==null) {
-			lastResponder = description.getRootPanel().onMouseDown(containerX, containerY, mouseButton);
+			lastResponder = description.getRootPanel().hit(containerX, containerY);
+			if (lastResponder!=null) lastResponder.onMouseDown(containerX-lastResponder.getAbsoluteX(), containerY-lastResponder.getAbsoluteY(), mouseButton);
 		} else {
 			//This is a drag instead
 		}
@@ -133,16 +124,6 @@ public class ClientCottonScreen extends Screen {
 	@Override
 	public boolean mouseReleased(double mouseX, double mouseY, int mouseButton) {
 		if (description.getRootPanel()==null) return super.mouseReleased(mouseX, mouseY, mouseButton);
-		/*
-		boolean result = super.mouseReleased(mouseX, mouseY, mouseButton);
-		int containerX = (int)mouseX-left;
-		int containerY = (int)mouseY-top;
-		if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return result;
-		
-		WWidget responder = description.getRootPanel().onMouseUp(containerX, containerY, mouseButton);
-		if (responder!=null && responder==lastResponder) description.getRootPanel().onClick(containerX, containerY, mouseButton);
-		lastResponder = null;
-		return result;*/
 		boolean result = super.mouseReleased(mouseX, mouseY, mouseButton);
 		int containerX = (int)mouseX-left;
 		int containerY = (int)mouseY-top;
@@ -163,13 +144,6 @@ public class ClientCottonScreen extends Screen {
 	@Override
 	public boolean mouseDragged(double mouseX, double mouseY, int mouseButton, double unknown_1, double unknown_2) {
 		if (description.getRootPanel()==null) return super.mouseDragged(mouseX, mouseY, mouseButton, unknown_1, unknown_2);
-		/*
-		boolean result = super.mouseDragged(mouseX, mouseY, mouseButton, unknown_1, unknown_2);
-		int containerX = (int)mouseX-left;
-		int containerY = (int)mouseY-top;
-		if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return result;
-		description.getRootPanel().onMouseDrag(containerX, containerY, mouseButton);
-		return result;*/
 		boolean result = super.mouseDragged(mouseX, mouseY, mouseButton, unknown_1, unknown_2);
 		
 		int containerX = (int)mouseX-left;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WListPanel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WListPanel.java
index 7d4c830..abb403e 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WListPanel.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WListPanel.java
@@ -40,7 +40,7 @@ public class WListPanel<D, W extends WWidget> extends WPanel {
 	}
 	
 	@Override
-	public void paintBackground(int x, int y) {
+	public void paintBackground(int x, int y, int mouseX, int mouseY) {
 		if (getBackgroundPainter()!=null) {
 			getBackgroundPainter().paintBackground(x, y, this);
 		} else {
@@ -58,75 +58,83 @@ public class WListPanel<D, W extends WWidget> extends WPanel {
 	}
 	
 	@Override
-		public void layout() {
-			//super.layout();
-			
-			System.out.println("Validating");
-			
-			//Recompute cellHeight if needed
-			if (!fixedHeight) {
-				if (unconfigured.isEmpty()) {
-					if (configured.isEmpty()) {
-						W exemplar = supplier.get();
-						unconfigured.add(exemplar);
-						if (!exemplar.canResize()) cellHeight = exemplar.getHeight();
-					} else {
-						W exemplar = configured.values().iterator().next();
-						if (!exemplar.canResize()) cellHeight = exemplar.getHeight();
-					}
+	public void layout() {
+		
+		this.children.clear();
+		this.children.add(scrollBar);
+		scrollBar.setLocation(this.width-scrollBar.getWidth(), 0);
+		scrollBar.setSize(8, this.height);
+		//scrollBar.window = 6;
+		scrollBar.setMaxValue(data.size());
+		
+		//super.layout();
+		
+		//System.out.println("Validating");
+		
+		//Recompute cellHeight if needed
+		if (!fixedHeight) {
+			if (unconfigured.isEmpty()) {
+				if (configured.isEmpty()) {
+					W exemplar = supplier.get();
+					unconfigured.add(exemplar);
+					if (!exemplar.canResize()) cellHeight = exemplar.getHeight();
 				} else {
-					W exemplar = unconfigured.get(0);
+					W exemplar = configured.values().iterator().next();
 					if (!exemplar.canResize()) cellHeight = exemplar.getHeight();
 				}
+			} else {
+				W exemplar = unconfigured.get(0);
+				if (!exemplar.canResize()) cellHeight = exemplar.getHeight();
 			}
-			if (cellHeight<4) cellHeight=4;
-			
-			int layoutHeight = this.getHeight()-(margin*2);
-			int cellsHigh = layoutHeight / cellHeight;
-			
-			
-			//System.out.println("Adding children...");
-			
-			this.children.clear();
-			this.children.add(scrollBar);
-			scrollBar.setLocation(this.width-scrollBar.getWidth(), 0);
-			scrollBar.setSize(8, this.height);
-			
-			//Fix up the scrollbar handle and track metrics
-			scrollBar.window = cellsHigh;
-			scrollBar.setMaxValue(data.size());
-			int scrollOffset = scrollBar.value;
-			//System.out.println(scrollOffset);
-			
-			int presentCells = Math.min(data.size()-scrollOffset, cellsHigh);
-			
-			if (presentCells>0) {
-				for(int i=0; i<presentCells; i++) {
-					int index = i+scrollOffset;
-					D d = data.get(index);
-					W w = configured.get(d);
-					if (w==null) {
-						if (unconfigured.isEmpty()) {
-							w = supplier.get();
-						} else {
-							w = unconfigured.remove(0);
-						}
-						configurator.accept(d, w);
-						configured.put(d, w);
-					}
-					
-					//At this point, w is nonnull and configured by d
-					if (w.canResize()) {
-						w.setSize(this.width-(margin*2) - scrollBar.getWidth(), cellHeight);
+		}
+		if (cellHeight<4) cellHeight=4;
+		
+		int layoutHeight = this.getHeight()-(margin*2);
+		int cellsHigh = layoutHeight / cellHeight;
+		
+		
+		//System.out.println("Adding children...");
+		
+		//this.children.clear();
+		//this.children.add(scrollBar);
+		//scrollBar.setLocation(this.width-scrollBar.getWidth(), 0);
+		//scrollBar.setSize(8, this.height);
+		
+		//Fix up the scrollbar handle and track metrics
+		scrollBar.window = cellsHigh;
+		//scrollBar.setMaxValue(data.size());
+		int scrollOffset = scrollBar.value;
+		//System.out.println(scrollOffset);
+		
+		int presentCells = Math.min(data.size()-scrollOffset, cellsHigh);
+		
+		if (presentCells>0) {
+			for(int i=0; i<presentCells; i++) {
+				int index = i+scrollOffset;
+				D d = data.get(index);
+				W w = configured.get(d);
+				if (w==null) {
+					if (unconfigured.isEmpty()) {
+						w = supplier.get();
+					} else {
+						w = unconfigured.remove(0);
 					}
-					w.x = margin;
-					w.y = margin + (cellHeight * i);
-					this.children.add(w);
+					configurator.accept(d, w);
+					configured.put(d, w);
+				}
+				
+				//At this point, w is nonnull and configured by d
+				if (w.canResize()) {
+					w.setSize(this.width-(margin*2) - scrollBar.getWidth(), cellHeight);
 				}
+				w.x = margin;
+				w.y = margin + (cellHeight * i);
+				this.children.add(w);
 			}
-			
-			//System.out.println("Children: "+children.size());
 		}
+		
+		//System.out.println("Children: "+children.size());
+	}
 	
 	public WListPanel<D, W> setListItemHeight(int height) {
 		cellHeight = height;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java
index 599df5d..cda638d 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java
@@ -119,6 +119,24 @@ public abstract class WPanel extends WWidget {
 		}
 	}*/
 	
+	/**
+	 * Finds the most specific child node at this location.
+	 */
+	@Override
+	public WWidget hit(int x, int y) {
+		if (children.isEmpty()) return this;
+		for(int i=children.size()-1; i>=0; i--) { //Backwards so topmost widgets get priority
+			WWidget child = children.get(i);
+			if (    x>=child.getX() &&
+					y>=child.getY() &&
+					x<child.getX()+child.getWidth() &&
+					y<child.getY()+child.getHeight()) {
+				return child.hit(x, y);
+			}
+		}
+		return this;
+	}
+	
 	@Override
 	public void validate(GuiDescription c) {
 		layout();
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java
index bcab40a..524b0d2 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java
@@ -1,11 +1,6 @@
 package io.github.cottonmc.cotton.gui.widget;
 
-import org.lwjgl.glfw.GLFW;
-
 import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.util.InputUtil;
-import net.minecraft.client.util.Window;
 
 public class WScrollBar extends WWidget {
 	protected Axis axis = Axis.HORIZONTAL;
@@ -37,39 +32,34 @@ public class WScrollBar extends WWidget {
 		}
 	}
 	
-	@Override
-	public void paintForeground(int x, int y, int mouseX, int mouseY) {
-		super.paintForeground(x, y, mouseX, mouseY);
-		
-		//Sneakily update bar position
-		if (sliding) {
-			adjustSlider(mouseX+x, mouseY+y);
-		}
-	}
-	
 	/**
 	 * Gets the on-axis size of the scrollbar handle in gui pixels 
 	 */
 	public int getHandleSize() {
 		float percentage = (window>=maxValue) ? 1f : window / (float)maxValue;
 		int bar = (axis==Axis.HORIZONTAL) ? width-2 : height-2;
-		return (int)(percentage*bar);
+		int result = (int)(percentage*bar);
+		if (result<6) result = 6;
+		return result;
 	}
 	
 	/**
 	 * Gets the number of pixels the scrollbar handle is able to move along its track from one end to the other.
 	 */
 	public int getMovableDistance() {
-		//int logicalDistance = maxValue-window;
-		//if (logicalDistance<0) logicalDistance = 0;
-		//float percentage = logicalDistance / (float)maxValue;
 		int bar = (axis==Axis.HORIZONTAL) ? width-2 : height-2;
 		return bar-getHandleSize();
-		//return (int)(percentage*bar);
+	}
+	
+	public int pixelsToValues(int pixels) {
+		int bar = (axis==Axis.HORIZONTAL) ? width-2 : height-2;
+		//int bar = getMovableDistance();
+		float percent = pixels / (float)bar;
+		return (int)(percent*(maxValue-window));
 	}
 	
 	public int getHandlePosition() {
-		float percent = value / (float)Math.max(maxValue, 1);
+		float percent = value / (float)Math.max(maxValue-window, 1);
 		return (int)(percent * getMovableDistance());
 	}
 	
@@ -82,9 +72,6 @@ public class WScrollBar extends WWidget {
 	}
 	
 	protected void adjustSlider(int x, int y) {
-		if (InputUtil.isKeyPressed(MinecraftClient.getInstance().window.getHandle(), GLFW.GLFW_MOUSE_BUTTON_LEFT)) {
-			System.out.println("LEFT BUTTON PRESS");
-		}
 		
 		int delta = 0;
 		if (axis==Axis.HORIZONTAL) {
@@ -93,9 +80,9 @@ public class WScrollBar extends WWidget {
 			delta = y-anchor;
 		}
 		
-		float percentMoved = (delta / (float)getMovableDistance());
-		int valueDelta = (int)(percentMoved * maxValue);
+		int valueDelta = pixelsToValues(delta);
 		int valueNew = anchorValue + valueDelta;
+		
 		if (valueNew>getMaxScrollValue()) valueNew = getMaxScrollValue();
 		if (valueNew<0) valueNew = 0;
 		this.value = valueNew;
@@ -106,37 +93,20 @@ public class WScrollBar extends WWidget {
 		//TODO: Clicking before or after the handle should jump instead of scrolling
 		
 		if (axis==Axis.HORIZONTAL) {
-			anchor = x-this.x;
+			anchor = x;
 			anchorValue = value;
 		} else {
-			anchor = y-this.y;
+			anchor = y;
 			anchorValue = value;
 		}
 		sliding = true;
-		System.out.println("Start sliding");
 		return this;
 	}
-	/*
+	
 	@Override
 	public void onMouseDrag(int x, int y, int button) {
-		int delta = 0;
-		if (axis==Axis.HORIZONTAL) {
-			delta = x-anchor;
-		} else {
-			delta = y-anchor;
-		}
-		
-		float percentMoved = (delta / (float)getMovableDistance());
-		int valueDelta = (int)(percentMoved * maxValue);
-		int valueNew = anchorValue + valueDelta;
-		if (valueNew>getMaxScrollValue()) valueNew = getMaxScrollValue();
-		if (valueNew<0) valueNew = 0;
-		this.value = valueNew;
-		
-		//System.out.println("Anchor: "+anchor+", Delta: "+delta+", PercentMoved: "+percentMoved+", ValueDelta: "+valueDelta);
-		
-		super.onMouseDrag(x, y, button);
-	}*/
+		adjustSlider(x, y);
+	}
 	
 	@Override
 	public WWidget onMouseUp(int x, int y, int button) {
@@ -144,7 +114,6 @@ public class WScrollBar extends WWidget {
 		anchor = -1;
 		anchorValue = -1;
 		sliding = false;
-		System.out.println("Stop sliding");
 		return this;
 	}
 	
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java
index 67c16d1..1314f88 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java
@@ -230,4 +230,11 @@ public class WWidget {
 	 */
 	public void addInformation(List<String> information) {
 	}
+	
+	/**
+	 * Find the most specific child node at this location. For non-panel widgets, returns this widget.
+	 */
+	public WWidget hit(int x, int y) {
+		return this;
+	}
 }
-- 
cgit