de.sciss.mellite.impl.objview.CodeObjView.scala Maven / Gradle / Ivy
/*
* CodeObjView.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.objview
import de.sciss.desktop
import de.sciss.icons.raphael
import de.sciss.lucre.swing.Window
import de.sciss.lucre.synth.Txn
import de.sciss.lucre.{Obj, Source, Txn => LTxn}
import de.sciss.mellite.impl.ObjViewCmdLineParser
import de.sciss.mellite.{CodeFrame, ObjListView, ObjView, UniverseHandler}
import de.sciss.proc.Implicits._
import de.sciss.proc.{Code, Universe}
import de.sciss.swingplus.ComboBox
import org.rogach.scallop
import java.util.Locale
import javax.swing.Icon
import scala.concurrent.Future
import scala.swing.{Component, Label}
object CodeObjView extends ObjListView.Factory {
type E[~ <: LTxn[~]] = Code.Obj[~]
val icon : Icon = ObjViewImpl.raphaelIcon(raphael.Shapes.Code)
val prefix : String = "Code"
def humanName : String = "Source Code"
def tpe : Obj.Type = Code.Obj
def category : String = ObjView.categMisc
def canMakeObj : Boolean = true
def mkListView[T <: Txn[T]](obj: Code.Obj[T])(implicit tx: T): CodeObjView[T] with ObjListView[T] = {
val value = obj.value
new Impl(tx.newHandle(obj), value).initAttrs(obj)
}
final case class Config[T <: LTxn[T]](name: String = prefix, value: Code, const: Boolean = false)
private def defaultCode(tpe: Code.Type): Code =
Code(tpe.id, tpe.defaultSource)
// cf. SP #58
private lazy val codeSeq = Code.types
private lazy val codeNames = codeSeq.map(_.humanName)
private lazy val codeMap : Map[String, Code.Type] =
codeSeq.iterator.map { tpe =>
val nm = tpe.prefix.toLowerCase
nm -> tpe
} .toMap
override def initMakeDialog[T <: Txn[T]](window: Option[desktop.Window])
(implicit universe: Universe[T]): MakeResult[T] = {
import de.sciss.lucre.synth.Executor.executionContext
val ggValue = new ComboBox(codeNames)
val res0 = ObjViewImpl.primitiveConfig[T, Code](window, tpe = prefix, ggValue = ggValue, prepare =
Future {
val tpe = codeSeq(ggValue.selection.index)
defaultCode(tpe)
}
)
val res = res0.map(c => Config[T](name = c.name, value = c.value))
res
}
private implicit val ReadCode: scallop.ValueConverter[Code] = scallop.singleArgConverter { s =>
val tpe = codeMap(s.toLowerCase(Locale.US))
defaultCode(tpe)
}
override def initMakeCmdLine[T <: Txn[T]](args: List[String])(implicit universe: Universe[T]): MakeResult[T] = {
object p extends ObjViewCmdLineParser[Config[T]](this, args) {
val const: Opt[Boolean] = opt (descr = s"Make constant instead of variable")
val value: Opt[Code] = trailArg("type", descr = codeMap.keysIterator.mkString("Code type (", ",", ")"))
}
p.parseFut(Future.successful(Config(name = p.name(), value = p.value(), const = p.const())))
}
def makeObj[T <: Txn[T]](config: Config[T])(implicit tx: T): List[Obj[T]] = {
import config._
val obj0 = Code.Obj.newConst[T](value)
val obj = if (const) obj0 else Code.Obj.newVar[T](obj0)
if (name.nonEmpty) obj.name = name
obj :: Nil
}
final class Impl[T <: Txn[T]](val objH: Source[T, Code.Obj[T]], var value: Code)
extends CodeObjView[T]
with ObjListView /* .Code */[T]
with ObjViewImpl.Impl[T]
with ObjListViewImpl.NonEditable[T] {
override def obj(implicit tx: T): Code.Obj[T] = objH()
def factory: ObjView.Factory = CodeObjView
// def isUpdateVisible(update: Any)(implicit tx: T): Boolean = false
def isViewable = true
override def openView(parent: Option[Window[T]])(implicit tx: T,
handler: UniverseHandler[T]): Option[Window[T]] = {
import de.sciss.mellite.Mellite.compiler
val frame = CodeFrame(obj, bottom = Nil)
Some(frame)
}
def configureListCellRenderer(label: Label): Component = {
label.text = value.tpe.humanName
label
}
}
}
trait CodeObjView[T <: LTxn[T]] extends ObjView[T] {
type Repr = Code.Obj[T]
}