ocelot-desktop/src/main/scala/ocelot/desktop/ui/widget/ChangeSimulationSpeedDialog.scala
2023-06-28 14:58:06 +00:00

115 lines
3.7 KiB
Scala

package ocelot.desktop.ui.widget
import ocelot.desktop.OcelotDesktop
import ocelot.desktop.audio.SoundSource
import ocelot.desktop.geometry.Padding2D
import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.ChangeSimulationSpeedDialog.validateIntervalUs
import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.util.Orientation
import scala.concurrent.duration.{Duration, DurationLong}
class ChangeSimulationSpeedDialog() extends ModalDialog {
private var tickInterval: Option[Duration] = Some(OcelotDesktop.ticker.tickInterval)
private def confirm(): Unit = {
if (tickInterval.isDefined) {
OcelotDesktop.ticker.tickInterval = tickInterval.get
OcelotDesktop.pushToTickerIntervalHistory(tickInterval.get)
}
close()
}
children :+= new PaddingBox(new Widget {
override val layout = new LinearLayout(this, orientation = Orientation.Vertical)
children :+= new PaddingBox(new Label {
override def text = "Change simulation speed"
}, Padding2D(bottom = 16))
private var inputTPS: TextInput = _
private var inputMSPT: TextInput = _
private def formatMSPT(interval: Duration): String = (interval.toMicros / 1000f).toString
private def formatTPS(interval: Duration): String = (1_000_000f / interval.toMicros).toString
inputMSPT = new TextInput(formatMSPT(OcelotDesktop.ticker.tickInterval)) {
focus()
private def parseInput(text: String): Option[Duration] = try {
validateIntervalUs((text.toFloat * 1000).toLong)
} catch {
case _: NumberFormatException => None
}
override def onInput(text: String): Unit = {
tickInterval = parseInput(text).map { interval =>
inputTPS.setInput(formatTPS(interval))
interval
}
}
override def validator(text: String): Boolean = parseInput(text).isDefined
override def onConfirm(): Unit = confirm()
}
inputTPS = new TextInput(formatTPS(OcelotDesktop.ticker.tickInterval)) {
private def parseInput(text: String): Option[Duration] = try {
validateIntervalUs((1_000_000 / text.toFloat).toLong)
} catch {
case _: NumberFormatException => None
}
override def onInput(text: String): Unit = {
tickInterval = parseInput(text).map { interval =>
inputMSPT.setInput(formatMSPT(interval))
interval
}
}
override def validator(text: String): Boolean = parseInput(text).isDefined
override def onConfirm(): Unit = confirm()
}
children :+= new Label {
override def text = "Milliseconds per tick:"
}
children :+= new PaddingBox(inputMSPT, Padding2D(bottom = 8))
children :+= new Label {
override def text = "Ticks per second:"
}
children :+= new PaddingBox(inputTPS, Padding2D(bottom = 8))
children :+= new Widget {
children :+= new Filler
children :+= new PaddingBox(new Button {
override def text: String = "Cancel"
override protected def clickSoundSource: SoundSource = SoundSource.InterfaceClickLow
override def onClick(): Unit = close()
}, Padding2D(right = 8))
children :+= new Button {
override def text: String = "Apply"
override def onClick(): Unit = confirm()
override def enabled: Boolean = tickInterval.nonEmpty
}
}
}, Padding2D.equal(16))
}
object ChangeSimulationSpeedDialog {
private val MaxUpdateInterval = 1.minute
private val MinUpdateInterval = 1.micro
private def validateIntervalUs(us: Long): Option[Duration] = try {
val interval = us.micros
Option.when(interval >= MinUpdateInterval && interval <= MaxUpdateInterval)(interval)
} catch {
case _: IllegalArgumentException => None
}
}