Update selection when the LMB is pressed instead of released

This commit is contained in:
Fingercomp 2025-09-04 00:36:15 +03:00
parent c0eec1fffc
commit 7f0fccae80
No known key found for this signature in database
GPG Key ID: BBC71CEE45D86E37
2 changed files with 39 additions and 24 deletions

View File

@ -36,7 +36,7 @@ trait MouseHandler extends Widget {
case MouseEvent(MouseEvent.State.Pressed, button) =>
startPositions += (button -> UiHandler.mousePosition)
case MouseEvent(MouseEvent.State.Released, button) =>
case event @ MouseEvent(MouseEvent.State.Released, button) =>
val mousePos = UiHandler.mousePosition
val dragStopped = receiveDragEvents && dragButtons.remove(button)
@ -57,19 +57,11 @@ trait MouseHandler extends Widget {
}
if (clicked) {
val time = System.currentTimeMillis()
val info = ClickInfo(mousePos, time, button, 1)
for (lastInfo <- lastClickInfo if lastInfo.isConsecutive(info)) {
if (lastInfo.count < 3) {
info.count = lastInfo.count + 1
}
}
lastClickInfo = Some(info)
handleEvent(ClickEvent(button, mousePos))
val info = ClickInfo(lastClickInfo, mousePos, event)
lastClickInfo = Some(info)
info.count match {
case 2 => handleEvent(DoubleClickEvent(button, mousePos))
case 3 => handleEvent(TripleClickEvent(button, mousePos))
@ -119,7 +111,7 @@ object MouseHandler {
private def withinTolerance(a: Vector2D, b: Vector2D): Boolean = (b - a).lengthSquared < Tolerance * Tolerance
private case class ClickInfo(position: Vector2D, time: Long, button: MouseEvent.Button.Value, var count: Int) {
case class ClickInfo(position: Vector2D, time: Long, button: MouseEvent.Button.Value, var count: Int) {
def isConsecutive(prev: ClickInfo): Boolean = {
val quickEnough = time - prev.time < ConsecutiveClickTimeMillis
val sameButton = button == prev.button
@ -128,4 +120,18 @@ object MouseHandler {
quickEnough && sameButton && closeEnough
}
}
object ClickInfo {
def apply(prev: Option[ClickInfo], position: Vector2D, event: MouseEvent): ClickInfo = {
val info = ClickInfo(position, System.currentTimeMillis(), event.button, 1)
for (prev <- prev if prev.isConsecutive(info)) {
if (prev.count < 3) {
info.count = prev.count + 1
}
}
info
}
}
}

View File

@ -7,12 +7,12 @@ import ocelot.desktop.graphics.{Font, Graphics, IconSource}
import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.event.handlers.MouseHandler
import ocelot.desktop.ui.event.sources.KeyEvents
import ocelot.desktop.ui.event.{DoubleClickEvent, DragEvent, KeyEvent, MouseEvent, TripleClickEvent}
import ocelot.desktop.ui.event.{DragEvent, KeyEvent, MouseEvent}
import ocelot.desktop.ui.widget.TextInput.{Cursor, Selection, Text}
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.traits.HoverAnimation
import ocelot.desktop.util.{BaseWatcher, DrawUtils, Register, Watcher}
import ocelot.desktop.util.animation.ColorAnimation
import ocelot.desktop.util.{BaseWatcher, DrawUtils, Register, Watcher}
import org.lwjgl.input.Keyboard
import java.lang.Character.isWhitespace
@ -40,6 +40,8 @@ class TextInput(val initialText: String = "") extends Widget with MouseHandler w
private var cursorOffset = 0f
private var selectionOffsets: Option[(Int, Int)] = None
private var lastLeftClickInfo = Option.empty[MouseHandler.ClickInfo]
private val enabledRegister = Register.sampling(enabled)
private def selection: Option[Selection] = selectionWatcher.value
@ -49,8 +51,8 @@ class TextInput(val initialText: String = "") extends Widget with MouseHandler w
cursor.onChange = { position =>
cursorOffset = charsWidth(_text.chars, 0, position)
blinkTimer = 0
adjustScroll()
blinkTimer = 0
adjustScroll()
}
selectionWatcher.onChange = { newValue =>
@ -177,14 +179,21 @@ class TextInput(val initialText: String = "") extends Widget with MouseHandler w
root.get.contextMenus.open(menu)
case event @ MouseEvent(MouseEvent.State.Pressed, MouseEvent.Button.Left) if isFocused && mouseInBounds =>
// we can't use MouseHandler's double/triple click events because they are emitted when the button is released,
// whereas we want to update the selection when the button is pressed.
val clickInfo = MouseHandler.ClickInfo(lastLeftClickInfo, UiHandler.mousePosition, event)
lastLeftClickInfo = Some(clickInfo)
clickInfo.count match {
case 1 => selection = None
case 2 => selectWord()
case 3 => selectAll()
}
case MouseEvent(MouseEvent.State.Pressed, _) if isFocused && mouseInBounds =>
selection = None
case DoubleClickEvent(MouseEvent.Button.Left, _) if isFocused && mouseInBounds =>
selectWord()
case TripleClickEvent(MouseEvent.Button.Left, _) if isFocused && mouseInBounds =>
selectAll()
lastLeftClickInfo = None
case DragEvent(DragEvent.State.Start | DragEvent.State.Drag, MouseEvent.Button.Left, mouse) if isFocused =>
val pos = if (mouse.y < bounds.y) {