mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2025-12-20 02:59:19 +01:00
Remember the desired cursor position when changing the text
This commit is contained in:
parent
d676a4a5bf
commit
052f61ad43
@ -11,7 +11,7 @@ import ocelot.desktop.ui.event.{DoubleClickEvent, DragEvent, KeyEvent, MouseEven
|
|||||||
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
|
||||||
import ocelot.desktop.util.{DrawUtils, Register, Watcher}
|
import ocelot.desktop.util.{BaseWatcher, DrawUtils, Register, Watcher}
|
||||||
import ocelot.desktop.util.animation.ColorAnimation
|
import ocelot.desktop.util.animation.ColorAnimation
|
||||||
import org.lwjgl.input.Keyboard
|
import org.lwjgl.input.Keyboard
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ class TextInput(val initialText: String = "") extends Widget with MouseHandler w
|
|||||||
// model
|
// model
|
||||||
private val _text: Text = new Text(initialText.codePoints().toArray)
|
private val _text: Text = new Text(initialText.codePoints().toArray)
|
||||||
private val cursor: Cursor = new Cursor()
|
private val cursor: Cursor = new Cursor()
|
||||||
private val selectionWatcher = new Watcher[Option[Selection]](None)
|
private val selectionWatcher = Watcher[Option[Selection]](None)
|
||||||
|
|
||||||
// updated after all events are processed so that event handlers can refer to the previous position.
|
// updated after all events are processed so that event handlers can refer to the previous position.
|
||||||
private val prevCursorPosition = Register.sampling(cursor.position)
|
private val prevCursorPosition = Register.sampling(cursor.position)
|
||||||
@ -47,13 +47,13 @@ class TextInput(val initialText: String = "") extends Widget with MouseHandler w
|
|||||||
selectionWatcher.value = newValue
|
selectionWatcher.value = newValue
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor.onChange(position => {
|
cursor.onChange = { position =>
|
||||||
cursorOffset = charsWidth(_text.chars, 0, position)
|
cursorOffset = charsWidth(_text.chars, 0, position)
|
||||||
blinkTimer = 0
|
blinkTimer = 0
|
||||||
adjustScroll()
|
adjustScroll()
|
||||||
})
|
}
|
||||||
|
|
||||||
selectionWatcher.onChange(newValue => {
|
selectionWatcher.onChange = { newValue =>
|
||||||
selectionOffsets = newValue.map {
|
selectionOffsets = newValue.map {
|
||||||
case Selection.Ordered(start, end) =>
|
case Selection.Ordered(start, end) =>
|
||||||
(
|
(
|
||||||
@ -61,7 +61,7 @@ class TextInput(val initialText: String = "") extends Widget with MouseHandler w
|
|||||||
charsWidth(_text.chars, 0, end),
|
charsWidth(_text.chars, 0, end),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
private val foregroundAnimation = new ColorAnimation(targetForegroundColor, 7f)
|
private val foregroundAnimation = new ColorAnimation(targetForegroundColor, 7f)
|
||||||
private val borderAnimation = new ColorAnimation(targetBorderColor, 7f)
|
private val borderAnimation = new ColorAnimation(targetBorderColor, 7f)
|
||||||
@ -81,7 +81,10 @@ class TextInput(val initialText: String = "") extends Widget with MouseHandler w
|
|||||||
def text_=(value: String): Unit = {
|
def text_=(value: String): Unit = {
|
||||||
_text.chars = value.codePoints().toArray
|
_text.chars = value.codePoints().toArray
|
||||||
selection = None
|
selection = None
|
||||||
cursor.position = cursor.position max 0 min _text.chars.length
|
|
||||||
|
val desiredPosition = cursor.desiredPosition
|
||||||
|
cursor.position = desiredPosition max 0 min _text.chars.length
|
||||||
|
cursor.desiredPosition = desiredPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
private def selectedText: String = selection match {
|
private def selectedText: String = selection match {
|
||||||
@ -448,14 +451,20 @@ class TextInput(val initialText: String = "") extends Widget with MouseHandler w
|
|||||||
}
|
}
|
||||||
|
|
||||||
object TextInput {
|
object TextInput {
|
||||||
class Text(initialValue: Array[Int]) extends Watcher(initialValue) {
|
class Text(initialValue: Array[Int]) extends BaseWatcher(initialValue) {
|
||||||
def chars: Array[Int] = value
|
def chars: Array[Int] = value
|
||||||
def chars_=(newValue: Array[Int]): Unit = value = newValue
|
def chars_=(newValue: Array[Int]): Unit = value = newValue
|
||||||
}
|
}
|
||||||
|
|
||||||
class Cursor(initialValue: Int = 0) extends Watcher(initialValue) {
|
class Cursor(initialValue: Int = 0) extends BaseWatcher(initialValue) {
|
||||||
|
var desiredPosition: Int = initialValue
|
||||||
|
|
||||||
def position: Int = value
|
def position: Int = value
|
||||||
def position_=(newValue: Int): Unit = value = newValue
|
|
||||||
|
def position_=(newValue: Int): Unit = {
|
||||||
|
value = newValue
|
||||||
|
desiredPosition = newValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case class Selection(start: Int, end: Int) {
|
case class Selection(start: Int, end: Int) {
|
||||||
|
|||||||
@ -1,16 +1,15 @@
|
|||||||
package ocelot.desktop.util
|
package ocelot.desktop.util
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps a reference to an object
|
* Keeps a value and tracks its changes.
|
||||||
* and tells whether there were any changes to the value since the last check.
|
|
||||||
*/
|
*/
|
||||||
class Watcher[T](initialValue: T) {
|
abstract class BaseWatcher[T](initialValue: T) {
|
||||||
private var dirty = false
|
private var dirty = false
|
||||||
private var _callback: Option[T => Unit] = None
|
private var _callback: Option[T => Unit] = None
|
||||||
private var _value: T = initialValue
|
private var _value: T = initialValue
|
||||||
|
|
||||||
def value: T = _value
|
protected def value: T = _value
|
||||||
def value_=(newValue: T): Unit = {
|
protected def value_=(newValue: T): Unit = {
|
||||||
dirty = _value != newValue
|
dirty = _value != newValue
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
_callback.foreach(_(newValue))
|
_callback.foreach(_(newValue))
|
||||||
@ -18,7 +17,11 @@ class Watcher[T](initialValue: T) {
|
|||||||
_value = newValue
|
_value = newValue
|
||||||
}
|
}
|
||||||
|
|
||||||
def onChange(callback: T => Unit): Unit = _callback = Some(callback)
|
def onChange: Option[T => Unit] = _callback
|
||||||
|
|
||||||
|
def onChange_=(callback: T => Unit): Unit = {
|
||||||
|
_callback = Some(callback)
|
||||||
|
}
|
||||||
|
|
||||||
def changed(): Boolean = {
|
def changed(): Boolean = {
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
@ -29,5 +32,10 @@ class Watcher[T](initialValue: T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Watcher {
|
object Watcher {
|
||||||
def apply[T](value: T) = new Watcher(value)
|
def apply[T](initialValue: T) = new Watcher(initialValue)
|
||||||
|
|
||||||
|
class Watcher[T](initialValue: T) extends BaseWatcher(initialValue) {
|
||||||
|
override def value: T = super.value
|
||||||
|
override def value_=(newValue: T): Unit = super.value_=(newValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user