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.document.FolderEditorViewImpl.scala Maven / Gradle / Ivy
/*
* FolderEditorViewImpl.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.document
import de.sciss.desktop
import de.sciss.desktop.{KeyStrokes, Window}
import de.sciss.lucre.edit.{EditFolder, UndoManager}
import de.sciss.lucre.synth.Txn
import de.sciss.lucre.{Copy, Expr, Folder, Obj, StringObj, expr}
import de.sciss.mellite.impl.component.CollectionViewImpl
import de.sciss.mellite.{FolderEditorView, FolderView, ObjView, UniverseHandler, ViewState}
import de.sciss.proc.{ObjKeys, Universe}
import de.sciss.swingplus.{ComboBox, GroupPanel, Spinner}
import javax.swing.SpinnerNumberModel
import scala.swing.Swing.EmptyIcon
import scala.swing.event.Key
import scala.swing.{Action, Alignment, CheckBox, Dialog, Label, Swing, TextField}
object FolderEditorViewImpl extends FolderEditorView.Companion {
def install(): Unit =
FolderEditorView.peer = this
def apply[T <: Txn[T]](folder: Folder[T])(implicit tx: T, handler: UniverseHandler[T],
undoManager: UndoManager[T]): FolderEditorView[T] = {
import handler.universe
val peer = FolderView(folder)
val view = new Impl[T](peer)
view.init()
}
private final class Impl[T <: Txn[T]](val peer: FolderView[T])
(implicit protected val universeHandler: UniverseHandler[T],
val undoManager: UndoManager[T])
extends CollectionViewImpl[T] with FolderEditorView[T]
{
impl =>
override implicit val universe: Universe[T] = universeHandler.universe
override def obj(implicit tx: T): Folder[T] = peer.obj
override def viewState: Set[ViewState] = peer.viewState
protected type InsertConfig = peer.SelectionImpl // FolderView.Selection[T]
private def selection: InsertConfig = impl.peer.selectionImpl
protected def prepareInsertDialog(f: ObjView.Factory): Option[InsertConfig] =
Some(selection)
protected def prepareInsertCmdLine(args: List[String]): Option[(InsertConfig, List[String])] =
Some((selection, args))
protected override def editInsert(f: ObjView.Factory, xs: List[Obj[T]], config: InsertConfig)
(implicit tx: T): Boolean = {
val (parent, idx) = impl.peer.insertionPointOf(config)
val numObj = xs.size
undoManager.capture("Create Objects") {
xs.zipWithIndex.foreach { case (child, ci) =>
EditFolder.insertUndo(/*f.prefix,*/ parent, index = idx + ci, child = child)
if (ci == numObj - 1) peer.select(child)
}
}
xs.nonEmpty
}
def dispose()(implicit tx: T): Unit =
peer.dispose()
protected lazy val actionDelete: Action = Action(null) {
val sel = peer.selection
cursor.step { implicit tx =>
undoManager.capture("Delete Elements") {
sel.foreach { nodeView =>
val parent = nodeView.parent
val childH = nodeView.modelData
val child = childH()
val idx = parent.indexOf(child)
if (idx < 0) {
println("WARNING: Parent folder of object not found")
} else {
EditFolder.removeAtUndo[T](/*nodeView.renderData.humanName,*/ parent, idx /*, child*/)
}
}
}
}
}
protected def initGUI2(): Unit = {
peer.addListener {
case FolderView.SelectionChanged(_, sel) =>
selectionChanged(sel.map(_.renderData))
actionDuplicate.enabled = sel.nonEmpty
}
}
lazy val actionDuplicate: Action = new Action("Duplicate...") {
accelerator = Some(KeyStrokes.menu1 + Key.D)
enabled = impl.peer.selection.nonEmpty
private var appendText = "-1"
private var count = 1
private var append = true
private var attrMode = 0 // 0 - deep copy, 1 - shallow copy, 2 - share, 3 - empty
private def incLast(x: String, c: Int): String = {
val p = "\\d+".r
val m = p.pattern.matcher(x)
var start = -1
var end = -1
while (m.find()) {
start = m.start()
end = m.end()
}
if (start < 0) x else {
val (pre, tmp) = x.splitAt(start)
val (old, suf) = tmp.splitAt(end - start)
s"$pre${old.toInt + c}$suf"
}
}
def apply(): Unit = {
val sel = impl.peer.selection
val numSel = sel.size
if (numSel == 0) return
sel.map(view => view.renderData.name)
val txtInfo = s"Duplicate ${if (numSel == 1) s"'${sel.head.renderData.name}'" else s"$numSel Objects"}"
val lbInfo = new Label(txtInfo)
lbInfo.border = Swing.EmptyBorder(0, 0, 8, 0)
val ggName = new TextField(6)
ggName.text = appendText
val mCount = new SpinnerNumberModel(count, 1, 0x4000, 1)
val ggCount = new Spinner(mCount)
val lbName = new CheckBox("Append to Name:")
lbName.selected = append
val lbCount = new Label("Number of Copies:" , EmptyIcon, Alignment.Right)
val lbAttr = new Label("Attribute Map")
val ggAttr = new ComboBox(Seq("Deep Copy", "Shallow Copy", "Share", "Empty"))
ggAttr.selection.index = attrMode
val box = new GroupPanel {
horizontal = Par(
lbInfo,
Seq(
Par(lbName, lbCount, lbAttr),
Par(ggName, ggCount, ggAttr),
)
)
vertical = Seq(
lbInfo,
Par(Baseline)(lbName , ggName ),
Par(Baseline)(lbCount , ggCount ),
Par(Baseline)(lbAttr , ggAttr ),
)
}
val pane = desktop.OptionPane.confirmation(box, optionType = Dialog.Options.OkCancel,
messageType = Dialog.Message.Question, focus = Some(ggCount))
pane.title = "Duplicate"
val window = Window.find(component)
val res = pane.show(window)
import de.sciss.equal.Implicits._
if (res === Dialog.Result.Ok) {
// save state
count = mCount.getNumber.intValue()
appendText = ggName.text
append = lbName.selected
attrMode = ggAttr.selection.index
// lazy val regex = "\\d+".r // do _not_ catch leading minus character
cursor.step { implicit tx =>
undoManager.capture(txtInfo) {
sel.flatMap { nodeView =>
val p = nodeView.parent
val orig = nodeView.modelData()
val idx = p.indexOf(orig)
val copies = List.tabulate(count) { n =>
// val cpy = Obj.copy[T, T, Obj](orig)
val cpy = {
val context = Copy[T, T]()
val aDeep = attrMode == 0
val aShallow = attrMode == 1
val aShare = attrMode == 2
val res = if (aDeep) context.apply(orig) else context.copyPlain(orig)
context.finish()
if (aShallow || aShare) {
val attrIn = orig.attr
val attrOut = res .attr
attrIn.keysIterator.foreach {
case ObjKeys.attrName => () // handled later
case key =>
attrIn.get(key).foreach {
case ex: Expr[T, _] if aShallow =>
ex.tpe match {
case tpe: Expr.Type[_, _] =>
val exT = ex.asInstanceOf[tpe.E[T]] // XXX TODO what else can we do
val exVl = tpe.Var.unapply(exT) match {
case Some(vr) => vr()
case None => exT
}
val exVr = tpe.newVar[T](exVl).asInstanceOf[Obj[T]] // XXX TODO what else can we do
attrOut.put(key, exVr)
case _ =>
attrOut.put(key, ex)
}
case other =>
attrOut.put(key, other)
}
}
}
res
}
if (append || attrMode != 0) {
orig.attr.$[StringObj](ObjKeys.attrName).foreach { oldName =>
// val imp = ExprImplicits[T]
import expr.Ops._
val suffix = if (append) incLast(appendText, n) else ""
val newName = oldName ++ suffix
cpy.attr.put(ObjKeys.attrName, StringObj.newVar(newName))
}
// cpy.attr.name = s"${cpy.attr.name}$suffix"
}
EditFolder.insert(/*"Copy",*/ p, idx + n + 1, cpy)
}
copies
}
}
}
}
}
}
def selectedObjects: List[ObjView[T]] = peer.selection.map(_.renderData)
}
}