All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
de.sciss.mellite.impl.state.TimelineViewState.scala Maven / Gradle / Ivy
/*
* TimelineViewState.scala
* (Mellite)
*
* Copyright (c) 2012-2023 Hanns Holger Rutz. All rights reserved.
*
* This software is published under the GNU Affero General Public License v3+
*
*
* For further information, please contact Hanns Holger Rutz at
* [email protected]
*/
package de.sciss.mellite.impl.state
import de.sciss.audiowidgets.{TimelineModel, TransportCatch}
import de.sciss.lucre.swing.LucreSwing.requireEDT
import de.sciss.lucre.{BooleanObj, DoubleObj, LongObj, Obj, SpanLikeObj, SpanObj, Txn}
import de.sciss.mellite.{GUI, ViewState}
import de.sciss.numbers.Implicits._
import de.sciss.span.Span
import scala.math.sqrt
import scala.swing.Slider
object TimelineViewState {
final val Key_Position = "tl-pos"
final val Key_Visible = "tl-vis"
final val Key_Selection = "tl-sel"
final val Key_Catch = "catch"
final val Key_VisualBoost = "vis-boost"
// final val Default_VisualBoostMin = 1.0
// final val Default_VisualBoostMax = 512.0
}
/** Tracks view state for a Timeline based object with transport.
* Tracks timeline position, visible and selected span, as well as visual boost and transport catch.
*/
class TimelineViewState[T <: Txn[T]](
keyPosition : String = TimelineViewState.Key_Position,
keyVisible : String = TimelineViewState.Key_Visible,
keySelection : String = TimelineViewState.Key_Selection,
keyCatch : String = TimelineViewState.Key_Catch,
keyVisualBoost: String = TimelineViewState.Key_VisualBoost,
visBoostMin : Double = GUI.Default_VisualBoostMin,
visBoostMax : Double = GUI.Default_VisualBoostMax,
) {
@volatile
private var statePosition = 0L
private var dirtyPosition = false
@volatile
private var stateVisible = Span(0L, 0L)
private var dirtyVisible = false
@volatile
private var stateSelection = Span.Void: Span.SpanOrVoid
private var dirtySelection = false
@volatile
private var stateCatch = true
private var dirtyCatch = false
@volatile
private var stateVisualBoost = sqrt(visBoostMin * visBoostMax)
private var dirtyVisualBoost = false
def entries(set0: Set[ViewState] = Set.empty): Set[ViewState] = {
requireEDT()
var res = set0
if (dirtyPosition ) res += ViewState(keyPosition , LongObj , statePosition )
if (dirtyVisible ) res += ViewState(keyVisible , SpanObj , stateVisible )
if (dirtySelection ) res += ViewState(keySelection , SpanLikeObj , stateSelection )
if (dirtyCatch ) res += ViewState(keyCatch , BooleanObj , stateCatch )
if (dirtyVisualBoost) res += ViewState(keyVisualBoost , DoubleObj , stateVisualBoost)
res
}
def init(tAttr: Obj.AttrMap[T])(implicit tx: T): Unit = {
tAttr.$[LongObj](keyPosition).foreach { v =>
statePosition = v.value
}
tAttr.$[SpanObj](keyVisible).foreach { v =>
stateVisible = v.value
}
tAttr.$[SpanLikeObj](keySelection).foreach { v =>
v.value match {
case sp: Span => stateSelection = sp
case _ =>
}
}
tAttr.$[BooleanObj](keyCatch).foreach { v =>
stateCatch = v.value
}
tAttr.$[DoubleObj](keyVisualBoost).foreach { v =>
stateVisualBoost = v.value
}
}
/**
* @param visBoost can be `null` if it does not apply
*/
def initGUI(tlm: TimelineModel.Modifiable, cch: TransportCatch, visBoost: Slider): Unit = {
tlm.position = statePosition
if (stateVisible.nonEmpty) {
tlm.visible = stateVisible
}
tlm.selection = stateSelection
tlm.addListener {
case TimelineModel.Position (_, p) =>
statePosition = p.now
dirtyPosition = true
case TimelineModel.Visible(_, sp) =>
stateVisible = sp.now
dirtyVisible = true
case TimelineModel.Selection(_, sp) =>
stateSelection = sp.now
dirtySelection = true
}
cch.catchEnabled = stateCatch
cch.addListener {
case b =>
stateCatch = b
dirtyCatch = true
}
if (visBoost != null) {
if (stateVisualBoost >= visBoostMin && stateVisualBoost <= visBoostMax) {
val visBoostView0 = (stateVisualBoost.expLin(
visBoostMin, visBoostMax, visBoost.min, visBoost.max) + 0.5).toInt
.clip(visBoost.min, visBoost.max)
visBoost.value = visBoostView0
}
visBoost.peer.addChangeListener { _ =>
val visBoostModel = visBoost.value.linExp(visBoost.min, visBoost.max, visBoostMin, visBoostMax)
if (stateVisualBoost != visBoostModel) {
stateVisualBoost = visBoostModel
dirtyVisualBoost = true
}
}
}
}
}