de.sciss.lucre.swing.impl.NumericOptionSpinnerModel.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lucreswing_2.13.0-M5 Show documentation
Show all versions of lucreswing_2.13.0-M5 Show documentation
Swing support for Lucre, and common views
The newest version!
/*
* NumericOptionSpinnerModel.scala
* (LucreSwing)
*
* Copyright (c) 2014-2019 Hanns Holger Rutz. All rights reserved.
*
* This software is published under the GNU Lesser General Public License v2.1+
*
*
* For further information, please contact Hanns Holger Rutz at
* [email protected]
*/
package de.sciss.lucre.swing
package impl
import java.io.Serializable
import javax.swing.AbstractSpinnerModel
class NumericOptionSpinnerModel[A](value0: Option[A], minimum0: Option[A], maximum0: Option[A], stepSize0: A)
(implicit num: Numeric[A])
extends AbstractSpinnerModel with Serializable {
private var _value = value0
private var _minimum = minimum0
private var _maximum = maximum0
private var _stepSize = stepSize0
def value: Option[A] = _value
def value_=(v: Option[A]): Unit = if (_value != v) {
_value = v
fireStateChanged()
}
def minimum: Option[A] = _minimum
def minimum_=(value: Option[A]): Unit = if (_minimum != value) {
_minimum = value
fireStateChanged()
}
def maximum: Option[A] = _maximum
def maximum_=(value: Option[A]): Unit = if (_maximum != value) {
_maximum = value
fireStateChanged()
}
def stepSize: A = _stepSize
def stepSize_=(value: A): Unit = if (_stepSize != value) {
_stepSize = value
fireStateChanged()
}
// dir == `true` means increase, dir == `false` means decrease
// if value is None or will exceeds bounds, returns None else Some
private def incrValue(dir: Boolean): Option[A] = _value.flatMap { v =>
val newValue = num.plus(v, if (dir) _stepSize else num.negate(_stepSize))
val tooLarge = maximum.exists(m => num.compare(newValue, m) > 0)
val tooSmall = minimum.exists(m => num.compare(newValue, m) < 0)
if (tooLarge || tooSmall) None else Some(newValue)
}
/** Returns the next number in the sequence.
*
* @return value + stepSize
or null
if the sum
* exceeds maximum
.
*/
def getNextValue: AnyRef = {
val res = incrValue(dir = true)
if (res.isDefined) res else null
}
/** Returns the previous number in the sequence.
*
* @return value - stepSize
, or
* null
if the sum is less
* than minimum
.
*/
def getPreviousValue: AnyRef = {
val res = incrValue(dir = false)
if (res.isDefined) res else null
}
def getValue: AnyRef = _value
/** Sets the current value for this sequence. If value
is
* null
, or not an Option
, an
* IllegalArgumentException
is thrown. No
* bounds checking is done here.
*
* This method fires a ChangeEvent
if the value has changed.
*
* @param v the current (non null
) Option
* for this sequence
* @throws IllegalArgumentException if value
is
* null
or not a Option
*/
def setValue(v: AnyRef): Unit = {
if ((v == null) || !v.isInstanceOf[Option[_]]) {
val s1 = if (v == null) "" else s" (${v.getClass.getSimpleName})"
throw new IllegalArgumentException(s"Illegal value $v$s1")
}
value = v.asInstanceOf[Option[A]]
}
}