Skip to content

Commit 76c8c63

Browse files
committed
improve scrollbar drag behaviour
1 parent b1eba09 commit 76c8c63

File tree

5 files changed

+59
-43
lines changed

5 files changed

+59
-43
lines changed

src/main/java/com/cleanroommc/modularui/widget/scroll/HorizontalScrollData.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@ public HorizontalScrollData cancelScrollEdge(boolean cancelScrollEdge) {
3838
return this;
3939
}
4040

41-
@Override
42-
public float getProgress(ScrollArea area, int x, int y) {
43-
return (x - area.x) / (float) getFullVisibleSize(area);
44-
}
45-
4641
@Override
4742
public VerticalScrollData getOtherScrollData(ScrollArea area) {
4843
return area.getScrollY();
@@ -74,7 +69,7 @@ public void drawScrollbar(ScrollArea area) {
7469
int h = getThickness();
7570
GuiDraw.drawRect(x, y, w, h, area.getScrollBarBackgroundColor());
7671

77-
x = ((getFullVisibleSize(area, isOtherActive) - l) * getScroll()) / (getScrollSize() - getVisibleSize(area, isOtherActive));
72+
x = getScrollBarStart(area, l, isOtherActive);
7873
ScrollData data2 = getOtherScrollData(area);
7974
if (data2 != null && isOtherActive && data2.isOnAxisStart()) {
8075
x += data2.getThickness();
@@ -83,13 +78,4 @@ public void drawScrollbar(ScrollArea area) {
8378
w = l;
8479
drawScrollBar(x, y, w, h);
8580
}
86-
87-
@Override
88-
public boolean onMouseClicked(ScrollArea area, int x, int y, int button) {
89-
if (isOnAxisStart() ? y <= area.y + getThickness() : y >= area.ey() - getThickness()) {
90-
this.dragging = true;
91-
return true;
92-
}
93-
return false;
94-
}
9581
}

src/main/java/com/cleanroommc/modularui/widget/scroll/ScrollArea.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.cleanroommc.modularui.api.GuiAxis;
44
import com.cleanroommc.modularui.screen.viewport.GuiContext;
55
import com.cleanroommc.modularui.utils.Color;
6+
import com.cleanroommc.modularui.utils.MathUtils;
67
import com.cleanroommc.modularui.widget.sizer.Area;
78

89
import net.minecraft.client.gui.GuiScreen;
@@ -71,15 +72,13 @@ public boolean mouseClicked(GuiContext context) {
7172
* This method should be invoked to register dragging
7273
*/
7374
public boolean mouseClicked(int x, int y) {
74-
ScrollData data;
7575
if (this.scrollX != null && this.scrollX.isInsideScrollbarArea(this, x, y)) {
76-
data = this.scrollX;
76+
return this.scrollX.onMouseClicked(this, x, y, 0);
7777
} else if (this.scrollY != null && this.scrollY.isInsideScrollbarArea(this, x, y)) {
78-
data = this.scrollY;
78+
return this.scrollY.onMouseClicked(this, y, x, 0);
7979
} else {
8080
return false;
8181
}
82-
return data.onMouseClicked(this, x, y, 0);
8382
}
8483

8584
@SideOnly(Side.CLIENT)
@@ -137,9 +136,11 @@ public void mouseReleased(GuiContext context) {
137136
public void mouseReleased(int x, int y) {
138137
if (this.scrollX != null) {
139138
this.scrollX.dragging = false;
139+
this.scrollX.clickOffset = 0;
140140
}
141141
if (this.scrollY != null) {
142142
this.scrollY.dragging = false;
143+
this.scrollY.clickOffset = 0;
143144
}
144145
}
145146

@@ -154,15 +155,18 @@ public void drag(GuiContext context) {
154155
*/
155156
public void drag(int x, int y) {
156157
ScrollData data;
158+
float progress;
157159
if (this.scrollX != null && this.scrollX.dragging) {
158160
data = this.scrollX;
161+
progress = data.getProgress(this, x, y);
159162
} else if (this.scrollY != null && this.scrollY.dragging) {
160163
data = this.scrollY;
164+
progress = data.getProgress(this, y, x);
161165
} else {
162166
return;
163167
}
164-
float progress = data.getProgress(this, x, y);
165-
data.animateTo(this, (int) (progress * (data.getScrollSize() - data.getVisibleSize(this) + data.getThickness())));
168+
progress = MathUtils.clamp(progress, 0f, 1f);
169+
data.scrollTo(this, (int) (progress * (data.getScrollSize() - data.getVisibleSize(this) + data.getThickness())));
166170
}
167171

168172
public boolean isInsideScrollbarArea(int x, int y) {
@@ -196,12 +200,12 @@ public void setScrollBarBackgroundColor(int scrollBarBackgroundColor) {
196200
*/
197201
@SideOnly(Side.CLIENT)
198202
public void drawScrollbar() {
199-
boolean b = false;
203+
boolean isXActive = false; // micro optimisation
200204
if (this.scrollX != null && this.scrollX.isScrollBarActive(this, false)) {
201-
b = true;
205+
isXActive = true;
202206
this.scrollX.drawScrollbar(this);
203207
}
204-
if (this.scrollY != null && this.scrollY.isScrollBarActive(this, b)) {
208+
if (this.scrollY != null && this.scrollY.isScrollBarActive(this, isXActive)) {
205209
this.scrollY.drawScrollbar(this);
206210
}
207211
}

src/main/java/com/cleanroommc/modularui/widget/scroll/ScrollData.java

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public static ScrollData of(GuiAxis axis, boolean axisStart, int thickness) {
5959
private int scrollSize;
6060
private int scroll;
6161
protected boolean dragging;
62+
protected int clickOffset;
6263

6364
private int animatingTo = 0;
6465
private final Animator scrollAnimator = new Animator(30, Interpolation.QUAD_OUT);
@@ -153,11 +154,18 @@ public final int getVisibleSize(ScrollArea area) {
153154
return getVisibleSize(area, false);
154155
}
155156

157+
public final int getVisibleSize(ScrollArea area, int fullVisibleSize) {
158+
return Math.max(0, fullVisibleSize - area.getPadding().getTotal(this.axis));
159+
}
160+
156161
public final int getVisibleSize(ScrollArea area, boolean isOtherActive) {
157-
return Math.max(0, getFullVisibleSize(area, isOtherActive) - area.getPadding().getTotal(this.axis));
162+
return getVisibleSize(area, getFullVisibleSize(area, isOtherActive));
158163
}
159164

160-
public abstract float getProgress(ScrollArea area, int x, int y);
165+
public float getProgress(ScrollArea area, int mainAxisPos, int crossAxisPos) {
166+
float fullSize = (float) getFullVisibleSize(area);
167+
return (mainAxisPos - area.getPoint(this.axis) - clickOffset) / (fullSize - getScrollBarLength(area));
168+
}
161169

162170
@Nullable
163171
public abstract ScrollData getOtherScrollData(ScrollArea area);
@@ -217,7 +225,8 @@ public final boolean isOtherScrollBarActive(ScrollArea area, boolean isSelfActiv
217225

218226
public int getScrollBarLength(ScrollArea area) {
219227
boolean isOtherActive = isOtherScrollBarActive(area, false);
220-
return (int) (getVisibleSize(area, isOtherActive) * getFullVisibleSize(area, isOtherActive) / (float) this.scrollSize);
228+
int length = (int) (getVisibleSize(area, isOtherActive) * getFullVisibleSize(area, isOtherActive) / (float) this.scrollSize);
229+
return Math.max(length, 4); // min length of 4
221230
}
222231

223232
public abstract boolean isInsideScrollbarArea(ScrollArea area, int x, int y);
@@ -230,6 +239,14 @@ public int getAnimatingTo() {
230239
return this.animatingTo;
231240
}
232241

242+
public int getScrollBarStart(ScrollArea area, int scrollBarLength, int fullVisibleSize) {
243+
return ((fullVisibleSize - scrollBarLength) * getScroll()) / (getScrollSize() - getVisibleSize(area, fullVisibleSize));
244+
}
245+
246+
public int getScrollBarStart(ScrollArea area, int scrollBarLength, boolean isOtherActive) {
247+
return getScrollBarStart(area, scrollBarLength, getFullVisibleSize(area, isOtherActive));
248+
}
249+
233250
@SideOnly(Side.CLIENT)
234251
public abstract void drawScrollbar(ScrollArea area);
235252

@@ -240,5 +257,24 @@ protected void drawScrollBar(int x, int y, int w, int h) {
240257
GuiDraw.drawRect(x + 1, y + 1, w - 2, h - 2, 0xffaaaaaa);
241258
}
242259

243-
public abstract boolean onMouseClicked(ScrollArea area, int x, int y, int button);
260+
public boolean onMouseClicked(ScrollArea area, int mainAxisPos, int crossAxisPos, int button) {
261+
if (isOnAxisStart() ? crossAxisPos <= area.getPoint(this.axis.getOther()) + getThickness() : crossAxisPos >= area.getEndPoint(this.axis.getOther()) - getThickness()) {
262+
this.dragging = true;
263+
this.clickOffset = mainAxisPos;
264+
265+
int scrollBarSize = getScrollBarLength(area);
266+
int start = getScrollBarStart(area, scrollBarSize, false);
267+
int areaStart = area.getPoint(this.axis);
268+
boolean clickInsideBar = mainAxisPos >= areaStart + start && mainAxisPos <= areaStart + start + scrollBarSize;
269+
270+
if (clickInsideBar) {
271+
this.clickOffset = mainAxisPos - areaStart - start; // relative click position inside bar
272+
} else {
273+
this.clickOffset = scrollBarSize / 2; // assume click position in center of bar
274+
}
275+
276+
return true;
277+
}
278+
return false;
279+
}
244280
}

src/main/java/com/cleanroommc/modularui/widget/scroll/VerticalScrollData.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@ public VerticalScrollData cancelScrollEdge(boolean cancelScrollEdge) {
3838
return this;
3939
}
4040

41-
@Override
42-
public float getProgress(ScrollArea area, int x, int y) {
43-
return (y - area.y) / (float) getFullVisibleSize(area);
44-
}
45-
4641
@Override
4742
public HorizontalScrollData getOtherScrollData(ScrollArea area) {
4843
return area.getScrollX();
@@ -74,21 +69,12 @@ public void drawScrollbar(ScrollArea area) {
7469
int h = area.height;
7570
GuiDraw.drawRect(x, y, w, h, area.getScrollBarBackgroundColor());
7671

77-
y = ((getFullVisibleSize(area, isOtherActive) - l) * getScroll()) / (getScrollSize() - getVisibleSize(area, isOtherActive));
72+
y = getScrollBarStart(area, l, isOtherActive);
7873
ScrollData data2 = getOtherScrollData(area);
7974
if (data2 != null && isOtherActive && data2.isOnAxisStart()) {
8075
y += data2.getThickness();
8176
}
8277
h = l;
8378
drawScrollBar(x, y, w, h);
8479
}
85-
86-
@Override
87-
public boolean onMouseClicked(ScrollArea area, int x, int y, int button) {
88-
if (isOnAxisStart() ? x <= area.x + getThickness() : x >= area.ex() - getThickness()) {
89-
this.dragging = true;
90-
return true;
91-
}
92-
return false;
93-
}
9480
}

src/main/java/com/cleanroommc/modularui/widget/sizer/Area.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ public int getPoint(GuiAxis axis) {
137137
return axis.isHorizontal() ? this.x : this.y;
138138
}
139139

140+
public int getEndPoint(GuiAxis axis) {
141+
return axis.isHorizontal() ? this.x + this.width : this.y + this.height;
142+
}
143+
140144
public int getSize(GuiAxis axis) {
141145
return axis.isHorizontal() ? this.width : this.height;
142146
}

0 commit comments

Comments
 (0)