Skip to content

Commit

Permalink
improve scrollbar drag behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
brachy84 committed Feb 10, 2025
1 parent b1eba09 commit 76c8c63
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ public HorizontalScrollData cancelScrollEdge(boolean cancelScrollEdge) {
return this;
}

@Override
public float getProgress(ScrollArea area, int x, int y) {
return (x - area.x) / (float) getFullVisibleSize(area);
}

@Override
public VerticalScrollData getOtherScrollData(ScrollArea area) {
return area.getScrollY();
Expand Down Expand Up @@ -74,7 +69,7 @@ public void drawScrollbar(ScrollArea area) {
int h = getThickness();
GuiDraw.drawRect(x, y, w, h, area.getScrollBarBackgroundColor());

x = ((getFullVisibleSize(area, isOtherActive) - l) * getScroll()) / (getScrollSize() - getVisibleSize(area, isOtherActive));
x = getScrollBarStart(area, l, isOtherActive);
ScrollData data2 = getOtherScrollData(area);
if (data2 != null && isOtherActive && data2.isOnAxisStart()) {
x += data2.getThickness();
Expand All @@ -83,13 +78,4 @@ public void drawScrollbar(ScrollArea area) {
w = l;
drawScrollBar(x, y, w, h);
}

@Override
public boolean onMouseClicked(ScrollArea area, int x, int y, int button) {
if (isOnAxisStart() ? y <= area.y + getThickness() : y >= area.ey() - getThickness()) {
this.dragging = true;
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.cleanroommc.modularui.api.GuiAxis;
import com.cleanroommc.modularui.screen.viewport.GuiContext;
import com.cleanroommc.modularui.utils.Color;
import com.cleanroommc.modularui.utils.MathUtils;
import com.cleanroommc.modularui.widget.sizer.Area;

import net.minecraft.client.gui.GuiScreen;
Expand Down Expand Up @@ -71,15 +72,13 @@ public boolean mouseClicked(GuiContext context) {
* This method should be invoked to register dragging
*/
public boolean mouseClicked(int x, int y) {
ScrollData data;
if (this.scrollX != null && this.scrollX.isInsideScrollbarArea(this, x, y)) {
data = this.scrollX;
return this.scrollX.onMouseClicked(this, x, y, 0);
} else if (this.scrollY != null && this.scrollY.isInsideScrollbarArea(this, x, y)) {
data = this.scrollY;
return this.scrollY.onMouseClicked(this, y, x, 0);
} else {
return false;
}
return data.onMouseClicked(this, x, y, 0);
}

@SideOnly(Side.CLIENT)
Expand Down Expand Up @@ -137,9 +136,11 @@ public void mouseReleased(GuiContext context) {
public void mouseReleased(int x, int y) {
if (this.scrollX != null) {
this.scrollX.dragging = false;
this.scrollX.clickOffset = 0;
}
if (this.scrollY != null) {
this.scrollY.dragging = false;
this.scrollY.clickOffset = 0;
}
}

Expand All @@ -154,15 +155,18 @@ public void drag(GuiContext context) {
*/
public void drag(int x, int y) {
ScrollData data;
float progress;
if (this.scrollX != null && this.scrollX.dragging) {
data = this.scrollX;
progress = data.getProgress(this, x, y);
} else if (this.scrollY != null && this.scrollY.dragging) {
data = this.scrollY;
progress = data.getProgress(this, y, x);
} else {
return;
}
float progress = data.getProgress(this, x, y);
data.animateTo(this, (int) (progress * (data.getScrollSize() - data.getVisibleSize(this) + data.getThickness())));
progress = MathUtils.clamp(progress, 0f, 1f);
data.scrollTo(this, (int) (progress * (data.getScrollSize() - data.getVisibleSize(this) + data.getThickness())));
}

public boolean isInsideScrollbarArea(int x, int y) {
Expand Down Expand Up @@ -196,12 +200,12 @@ public void setScrollBarBackgroundColor(int scrollBarBackgroundColor) {
*/
@SideOnly(Side.CLIENT)
public void drawScrollbar() {
boolean b = false;
boolean isXActive = false; // micro optimisation
if (this.scrollX != null && this.scrollX.isScrollBarActive(this, false)) {
b = true;
isXActive = true;
this.scrollX.drawScrollbar(this);
}
if (this.scrollY != null && this.scrollY.isScrollBarActive(this, b)) {
if (this.scrollY != null && this.scrollY.isScrollBarActive(this, isXActive)) {
this.scrollY.drawScrollbar(this);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public static ScrollData of(GuiAxis axis, boolean axisStart, int thickness) {
private int scrollSize;
private int scroll;
protected boolean dragging;
protected int clickOffset;

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

public final int getVisibleSize(ScrollArea area, int fullVisibleSize) {
return Math.max(0, fullVisibleSize - area.getPadding().getTotal(this.axis));
}

public final int getVisibleSize(ScrollArea area, boolean isOtherActive) {
return Math.max(0, getFullVisibleSize(area, isOtherActive) - area.getPadding().getTotal(this.axis));
return getVisibleSize(area, getFullVisibleSize(area, isOtherActive));
}

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

@Nullable
public abstract ScrollData getOtherScrollData(ScrollArea area);
Expand Down Expand Up @@ -217,7 +225,8 @@ public final boolean isOtherScrollBarActive(ScrollArea area, boolean isSelfActiv

public int getScrollBarLength(ScrollArea area) {
boolean isOtherActive = isOtherScrollBarActive(area, false);
return (int) (getVisibleSize(area, isOtherActive) * getFullVisibleSize(area, isOtherActive) / (float) this.scrollSize);
int length = (int) (getVisibleSize(area, isOtherActive) * getFullVisibleSize(area, isOtherActive) / (float) this.scrollSize);
return Math.max(length, 4); // min length of 4
}

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

public int getScrollBarStart(ScrollArea area, int scrollBarLength, int fullVisibleSize) {
return ((fullVisibleSize - scrollBarLength) * getScroll()) / (getScrollSize() - getVisibleSize(area, fullVisibleSize));
}

public int getScrollBarStart(ScrollArea area, int scrollBarLength, boolean isOtherActive) {
return getScrollBarStart(area, scrollBarLength, getFullVisibleSize(area, isOtherActive));
}

@SideOnly(Side.CLIENT)
public abstract void drawScrollbar(ScrollArea area);

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

public abstract boolean onMouseClicked(ScrollArea area, int x, int y, int button);
public boolean onMouseClicked(ScrollArea area, int mainAxisPos, int crossAxisPos, int button) {
if (isOnAxisStart() ? crossAxisPos <= area.getPoint(this.axis.getOther()) + getThickness() : crossAxisPos >= area.getEndPoint(this.axis.getOther()) - getThickness()) {
this.dragging = true;
this.clickOffset = mainAxisPos;

int scrollBarSize = getScrollBarLength(area);
int start = getScrollBarStart(area, scrollBarSize, false);
int areaStart = area.getPoint(this.axis);
boolean clickInsideBar = mainAxisPos >= areaStart + start && mainAxisPos <= areaStart + start + scrollBarSize;

if (clickInsideBar) {
this.clickOffset = mainAxisPos - areaStart - start; // relative click position inside bar
} else {
this.clickOffset = scrollBarSize / 2; // assume click position in center of bar
}

return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ public VerticalScrollData cancelScrollEdge(boolean cancelScrollEdge) {
return this;
}

@Override
public float getProgress(ScrollArea area, int x, int y) {
return (y - area.y) / (float) getFullVisibleSize(area);
}

@Override
public HorizontalScrollData getOtherScrollData(ScrollArea area) {
return area.getScrollX();
Expand Down Expand Up @@ -74,21 +69,12 @@ public void drawScrollbar(ScrollArea area) {
int h = area.height;
GuiDraw.drawRect(x, y, w, h, area.getScrollBarBackgroundColor());

y = ((getFullVisibleSize(area, isOtherActive) - l) * getScroll()) / (getScrollSize() - getVisibleSize(area, isOtherActive));
y = getScrollBarStart(area, l, isOtherActive);
ScrollData data2 = getOtherScrollData(area);
if (data2 != null && isOtherActive && data2.isOnAxisStart()) {
y += data2.getThickness();
}
h = l;
drawScrollBar(x, y, w, h);
}

@Override
public boolean onMouseClicked(ScrollArea area, int x, int y, int button) {
if (isOnAxisStart() ? x <= area.x + getThickness() : x >= area.ex() - getThickness()) {
this.dragging = true;
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ public int getPoint(GuiAxis axis) {
return axis.isHorizontal() ? this.x : this.y;
}

public int getEndPoint(GuiAxis axis) {
return axis.isHorizontal() ? this.x + this.width : this.y + this.height;
}

public int getSize(GuiAxis axis) {
return axis.isHorizontal() ? this.width : this.height;
}
Expand Down

0 comments on commit 76c8c63

Please sign in to comment.