mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2025-12-20 02:59:19 +01:00
Select all text on triple-click
This commit is contained in:
parent
4cee456454
commit
c0eec1fffc
@ -2,4 +2,18 @@ package ocelot.desktop.ui.event
|
|||||||
|
|
||||||
import ocelot.desktop.geometry.Vector2D
|
import ocelot.desktop.geometry.Vector2D
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A synthetic event dispatched by [[ocelot.desktop.ui.event.handlers.MouseHandler MouseHandler]] on mouse click.
|
||||||
|
*/
|
||||||
case class ClickEvent(button: MouseEvent.Button.Value, mousePos: Vector2D) extends Event
|
case class ClickEvent(button: MouseEvent.Button.Value, mousePos: Vector2D) extends Event
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A synthetic event dispatched by [[ocelot.desktop.ui.event.handlers.MouseHandler MouseHandler]] on double-click
|
||||||
|
* in addition to (and after) [[ClickEvent]].
|
||||||
|
*/
|
||||||
|
case class DoubleClickEvent(button: MouseEvent.Button.Value, mousePos: Vector2D) extends Event
|
||||||
|
/**
|
||||||
|
* A synthetic event dispatched by [[ocelot.desktop.ui.event.handlers.MouseHandler MouseHandler]] on triple-click
|
||||||
|
* in addition to (and after) [[ClickEvent]].
|
||||||
|
*/
|
||||||
|
case class TripleClickEvent(button: MouseEvent.Button.Value, mousePos: Vector2D) extends Event
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
package ocelot.desktop.ui.event
|
|
||||||
|
|
||||||
import ocelot.desktop.geometry.Vector2D
|
|
||||||
|
|
||||||
case class DoubleClickEvent(button: MouseEvent.Button.Value, mousePos: Vector2D) extends Event
|
|
||||||
@ -2,8 +2,8 @@ package ocelot.desktop.ui.event.handlers
|
|||||||
|
|
||||||
import ocelot.desktop.geometry.Vector2D
|
import ocelot.desktop.geometry.Vector2D
|
||||||
import ocelot.desktop.ui.UiHandler
|
import ocelot.desktop.ui.UiHandler
|
||||||
import ocelot.desktop.ui.event.handlers.MouseHandler.{DoubleClickTimeMillis, Tolerance}
|
import ocelot.desktop.ui.event.handlers.MouseHandler.{ClickInfo, withinTolerance}
|
||||||
import ocelot.desktop.ui.event.{ClickEvent, DoubleClickEvent, DragEvent, MouseEvent}
|
import ocelot.desktop.ui.event.{ClickEvent, DoubleClickEvent, DragEvent, MouseEvent, TripleClickEvent}
|
||||||
import ocelot.desktop.ui.widget.Widget
|
import ocelot.desktop.ui.widget.Widget
|
||||||
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
@ -13,9 +13,7 @@ trait MouseHandler extends Widget {
|
|||||||
private val prevPositions = new mutable.HashMap[MouseEvent.Button.Value, Vector2D]()
|
private val prevPositions = new mutable.HashMap[MouseEvent.Button.Value, Vector2D]()
|
||||||
private val dragButtons = new mutable.HashSet[MouseEvent.Button.Value]()
|
private val dragButtons = new mutable.HashSet[MouseEvent.Button.Value]()
|
||||||
|
|
||||||
private var lastClickPosition: Vector2D = Vector2D.Zero
|
private var lastClickInfo = Option.empty[ClickInfo]
|
||||||
private var lastClickTime: Long = 0
|
|
||||||
private var lastClickButton = MouseEvent.Button.Left
|
|
||||||
|
|
||||||
override def receiveMouseEvents: Boolean = receiveClickEvents || receiveDragEvents
|
override def receiveMouseEvents: Boolean = receiveClickEvents || receiveDragEvents
|
||||||
|
|
||||||
@ -59,24 +57,29 @@ trait MouseHandler extends Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (clicked) {
|
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))
|
handleEvent(ClickEvent(button, mousePos))
|
||||||
|
|
||||||
val inTimeForDoubleClick = System.currentTimeMillis() - lastClickTime < DoubleClickTimeMillis
|
info.count match {
|
||||||
val sameButton = lastClickButton == button
|
case 2 => handleEvent(DoubleClickEvent(button, mousePos))
|
||||||
val roughlySamePosition = withinTolerance(lastClickPosition, mousePos)
|
case 3 => handleEvent(TripleClickEvent(button, mousePos))
|
||||||
if (inTimeForDoubleClick && sameButton && roughlySamePosition) {
|
case _ =>
|
||||||
handleEvent(DoubleClickEvent(button, mousePos))
|
|
||||||
}
|
}
|
||||||
lastClickTime = System.currentTimeMillis()
|
|
||||||
lastClickPosition = mousePos
|
|
||||||
lastClickButton = button
|
|
||||||
}
|
}
|
||||||
|
|
||||||
startPositions.remove(button)
|
startPositions.remove(button)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def withinTolerance(a: Vector2D, b: Vector2D): Boolean = (b - a).lengthSquared < Tolerance * Tolerance
|
|
||||||
|
|
||||||
override def update(): Unit = {
|
override def update(): Unit = {
|
||||||
super.update()
|
super.update()
|
||||||
|
|
||||||
@ -112,5 +115,17 @@ trait MouseHandler extends Widget {
|
|||||||
|
|
||||||
object MouseHandler {
|
object MouseHandler {
|
||||||
private val Tolerance = 8
|
private val Tolerance = 8
|
||||||
private val DoubleClickTimeMillis = 1e3f / 2
|
private val ConsecutiveClickTimeMillis = 1e3f / 2
|
||||||
|
|
||||||
|
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) {
|
||||||
|
def isConsecutive(prev: ClickInfo): Boolean = {
|
||||||
|
val quickEnough = time - prev.time < ConsecutiveClickTimeMillis
|
||||||
|
val sameButton = button == prev.button
|
||||||
|
val closeEnough = withinTolerance(position, prev.position)
|
||||||
|
|
||||||
|
quickEnough && sameButton && closeEnough
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import ocelot.desktop.graphics.{Font, Graphics, IconSource}
|
|||||||
import ocelot.desktop.ui.UiHandler
|
import ocelot.desktop.ui.UiHandler
|
||||||
import ocelot.desktop.ui.event.handlers.MouseHandler
|
import ocelot.desktop.ui.event.handlers.MouseHandler
|
||||||
import ocelot.desktop.ui.event.sources.KeyEvents
|
import ocelot.desktop.ui.event.sources.KeyEvents
|
||||||
import ocelot.desktop.ui.event.{DoubleClickEvent, DragEvent, KeyEvent, MouseEvent}
|
import ocelot.desktop.ui.event.{DoubleClickEvent, DragEvent, KeyEvent, MouseEvent, TripleClickEvent}
|
||||||
import ocelot.desktop.ui.widget.TextInput.{Cursor, Selection, Text}
|
import ocelot.desktop.ui.widget.TextInput.{Cursor, Selection, Text}
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
||||||
import ocelot.desktop.ui.widget.traits.HoverAnimation
|
import ocelot.desktop.ui.widget.traits.HoverAnimation
|
||||||
@ -183,6 +183,9 @@ class TextInput(val initialText: String = "") extends Widget with MouseHandler w
|
|||||||
case DoubleClickEvent(MouseEvent.Button.Left, _) if isFocused && mouseInBounds =>
|
case DoubleClickEvent(MouseEvent.Button.Left, _) if isFocused && mouseInBounds =>
|
||||||
selectWord()
|
selectWord()
|
||||||
|
|
||||||
|
case TripleClickEvent(MouseEvent.Button.Left, _) if isFocused && mouseInBounds =>
|
||||||
|
selectAll()
|
||||||
|
|
||||||
case DragEvent(DragEvent.State.Start | DragEvent.State.Drag, MouseEvent.Button.Left, mouse) if isFocused =>
|
case DragEvent(DragEvent.State.Start | DragEvent.State.Drag, MouseEvent.Button.Left, mouse) if isFocused =>
|
||||||
val pos = if (mouse.y < bounds.y) {
|
val pos = if (mouse.y < bounds.y) {
|
||||||
0
|
0
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user