From 21a7922a957abb78119c479145355b089b62b17c Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Thu, 18 Dec 2025 23:16:08 +0200 Subject: [PATCH] mouseClicked refactor + documentation --- .../client/gui/util/GuiScriptTextArea.java | 34 ++++++++----------- .../client/gui/util/script/ScrollState.java | 13 +++++++ .../gui/util/script/SelectionState.java | 31 +++++++++++++++++ 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java b/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java index ce7ca6a9c..0986b6add 100644 --- a/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java +++ b/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java @@ -1162,22 +1162,29 @@ public class GuiScriptTextArea extends GuiNpcTextField { // ==================== MOUSE HANDLING ==================== public void mouseClicked(int xMouse, int yMouse, int mouseButton) { + // Determine whether click occurred inside the text area bounds this.active = xMouse >= this.x && xMouse < this.x + this.width && yMouse >= this.y && yMouse < this.y + this.height; if (this.active) { + // Compute logical click position in text and reset selection/caret int clickPos = this.getSelectionPos(xMouse, yMouse); selection.reset(clickPos); selection.markActivity(); + + // Prepare click state (left button starts most interactions) this.clicked = mouseButton == 0; this.doubleClicked = false; this.tripleClicked = false; long time = System.currentTimeMillis(); + + // Prefer delegating scrollbar-start logic to ScrollState. If the click + // is on the scrollbar area and the scrollbar can be dragged, we start + // click-scrolling mode and cancel the normal text click-drag behavior. if (this.clicked && this.container.linesCount * this.container.lineHeight > this.height && xMouse > this.x + this.width - 8) { + // We consumed the mouse-down as a scrollbar drag start this.clicked = false; - scroll.setClickScrolling(true); - double linesCountD = Math.max(1, (double) this.container.linesCount); - int thumbTop = (int) (this.y + 1f * scroll.getScrollPos() / linesCountD * (this.height - 4)) + 1; - scroll.setScrollbarDragOffset(yMouse - thumbTop); + scroll.startScrollbarDrag(yMouse,this.y,this.height,container.linesCount); } else { + // Handle double/triple click selection counting if (time - this.lastClicked < 300L) { this.clickCount++; } else { @@ -1185,24 +1192,13 @@ public class GuiScriptTextArea extends GuiNpcTextField { } if (this.clickCount == 2) { - // Double-click: select word under cursor (restore prior behavior) + // Double-click: select the word under the caret using the container's word regex this.doubleClicked = true; - Matcher m = this.container.regexWord.matcher(this.text); - while (m.find()) { - if (selection.getCursorPosition() >= m.start() && selection.getCursorPosition() <= m.end()) { - selection.setSelection(m.start(), m.end()); - break; - } - } + selection.selectWordAtCursor(this.text, this.container.regexWord); } else if (this.clickCount >= 3) { - // Triple-click: select entire line + // Triple-click: select the entire logical line that contains the caret this.tripleClicked = true; - for (LineData line : container.lines) { - if (selection.getCursorPosition() >= line.start && selection.getCursorPosition() <= line.end) { - selection.setSelection(line.start, line.end); - break; - } - } + selection.selectLineAtCursor(container.lines); this.clickCount = 0; } } diff --git a/src/main/java/noppes/npcs/client/gui/util/script/ScrollState.java b/src/main/java/noppes/npcs/client/gui/util/script/ScrollState.java index da9ac067f..b092cd7fe 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/ScrollState.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/ScrollState.java @@ -193,4 +193,17 @@ public class ScrollState { setScrollbarDragOffset(0); } } + + /** + * Attempt to start a scrollbar drag if the mouse down occurred on the scrollbar thumb area. + * Returns true if drag was initiated (caller should cancel normal text-click drag behavior). + */ + public void startScrollbarDrag(int yMouse, int areaY, int areaHeight, int linesCount) { + // Thumb width in GuiScriptTextArea is 6px (posX..posX+5), so check clicks near the right edge + // Start click-scrolling mode and set initial drag offset relative to thumb top. + setClickScrolling(true); + double linesCountD = Math.max(1, (double) linesCount); + int thumbTop = (int) (areaY + 1f * getScrollPos() / linesCountD * (areaHeight - 4)) + 1; + setScrollbarDragOffset(yMouse - thumbTop); + } } \ No newline at end of file diff --git a/src/main/java/noppes/npcs/client/gui/util/script/SelectionState.java b/src/main/java/noppes/npcs/client/gui/util/script/SelectionState.java index d03008905..03644ad2e 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/SelectionState.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/SelectionState.java @@ -2,6 +2,7 @@ package noppes.npcs.client.gui.util.script; import noppes.npcs.client.gui.util.script.JavaTextContainer.LineData; import java.util.List; +import java.util.regex.Pattern; /** * Manages cursor position, text selection, and related operations. @@ -189,4 +190,34 @@ public class SelectionState { endSelection = startSelection = cursorPosition = newPosition; markActivity(); } + + /** + * Select the word surrounding the current cursor position using the provided regex. + * The regex should match word tokens; the implementation finds the token which + * contains the cursor and selects its start..end. + */ + public void selectWordAtCursor(String text, Pattern wordPattern) { + if (text == null || wordPattern == null) return; + java.util.regex.Matcher m = wordPattern.matcher(text); + while (m.find()) { + if (cursorPosition >= m.start() && cursorPosition <= m.end()) { + setSelection(m.start(), m.end()); + return; + } + } + } + + /** + * Select the entire line containing the cursor. `lines` is the parsed + * line data from `JavaTextContainer` where each LineData has start/end indices. + */ + public void selectLineAtCursor(List lines) { + if (lines == null) return; + for (LineData line : lines) { + if (isCursorOnLine(lines.indexOf(line), line, lines.size())) { + setSelection(line.start, line.end); + return; + } + } + } } \ No newline at end of file