All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.sciss.mellite.gui.ActionArtifactLocation.scala Maven / Gradle / Ivy

/*
 *  ActionArtifactLocation.scala
 *  (Mellite)
 *
 *  Copyright (c) 2012-2016 Hanns Holger Rutz. All rights reserved.
 *
 *  This software is published under the GNU General Public License v3+
 *
 *
 *  For further information, please contact Hanns Holger Rutz at
 *  [email protected]
 */

package de.sciss
package mellite
package gui

import de.sciss.desktop.{FileDialog, OptionPane, Window}
import de.sciss.file._
import de.sciss.lucre.artifact.{Artifact, ArtifactLocation}
import de.sciss.lucre.stm
import de.sciss.lucre.stm.{Obj, Sys}
import de.sciss.swingplus.Labeled
import de.sciss.synth.proc
import de.sciss.synth.proc.Folder

import scala.collection.immutable.{IndexedSeq => Vec}
import scala.swing.Dialog
import scala.util.Try

import proc.Implicits._

object ActionArtifactLocation {
  //  sealed trait QueryResult
  //  case class Cancel extends QueryResult
  //  case clstm.Source[S#Tx, Folder[S]]ass Select(elem: )

  // case class NewConfig(name: String, directory: File)

  //  def queryOrCreate[S <: Sys[S]](
  //                          root: stm.Source[S#Tx, Folder[S]], file: File,
  //                          folder: Option[stm.Source[S#Tx, Folder[S]]] = None,
  //                          window: Option[desktop.Window] = None)
  //                        (implicit cursor: stm.Cursor[S]): Option[stm.Source[S#Tx, ArtifactLocation[S]]] = {
  //    query(root = root, file = file, window = window).map { either =>
  //      either.fold(identity) { case (name, directory) => create(name = name, directory = directory) }
  //    }

  type LocationSource [S <: Sys[S]] = stm.Source[S#Tx, ArtifactLocation[S]]
  type QueryResult    [S <: Sys[S]] = Either[LocationSource[S], (String, File)]

  def merge[S <: Sys[S]](result: QueryResult[S])
                        (implicit tx: S#Tx): Option[(Option[Obj[S]], ArtifactLocation[S])] = {
    val (list0, loc) = result match {
      case Left(source) => (None, source())
      case Right((name, directory)) =>
        val locM = create(name, directory)
        (Some(locM), locM)
    }
    Some(list0 -> loc) // loc.modifiableOption.map(list0 -> _)
  }

  def query[S <: Sys[S]](
                          root: stm.Source[S#Tx, Folder[S]], file: File,
                          window: Option[desktop.Window] = None)
                        (implicit cursor: stm.Cursor[S]): Option[QueryResult[S]] = {

    def createNew(): Option[(String, File)] = queryNew(child = Some(file), window = window)

    val options = find(root = root, file = file, window = window)

    options match {
      case Vec() => createNew().map(Right.apply)
      case Vec(Labeled(source)) => Some(Left(source))

      case _ =>
        val ggList = new swingplus.ListView(options)
        ggList.selection.intervalMode = swingplus.ListView.IntervalMode.Single
        ggList.selection.indices += 0
        val opt = OptionPane.apply(message = ggList, messageType = OptionPane.Message.Question,
          optionType = OptionPane.Options.OkCancel, entries = Seq("Ok", "New Location", "Cancel"))
        opt.title = s"Choose Location for ${file.name}"
        val optRes = opt.show(window).id
        // println(s"res = $optRes, ok = ${OptionPane.Result.Ok.id}, cancel = ${OptionPane.Result.Cancel.id}")
        import equal.Implicits._
        if (optRes === 0) {
          ggList.selection.items.headOption.map(v => Left(v.value))
        } else if (optRes === 1) {
          createNew().map(Right.apply)
        } else {
          None
        }
    }
  }

  def find[S <: Sys[S]](
         root: stm.Source[S#Tx, Folder[S]], file: File,
         window: Option[desktop.Window] = None)
        (implicit cursor: stm.Cursor[S]): Vec[Labeled[LocationSource[S]]] = {

    val options: Vec[Labeled[LocationSource[S]]] = cursor.step { implicit tx =>
      /* @tailrec */ def loop(xs: List[Obj[S]], res: Vec[Labeled[LocationSource[S]]]): Vec[Labeled[LocationSource[S]]] =
        xs match {
          case head :: tail =>
            val res1 = head match {
              case objT: ArtifactLocation[S] =>
                val parent = objT.directory
                if (Try(Artifact.relativize(parent, file)).isSuccess) {
                  res :+ Labeled(tx.newHandle(objT))(objT.name)
                } else res

              case objT: Folder[S] =>
                loop(objT.iterator.toList, res)

              case _ => res
            }
            loop(tail, res1)

          case Nil => res
      }

      val _options = loop(root().iterator.toList, Vector.empty)
      _options
    }

    options
  }

  def queryNew(child: Option[File] = None, window: Option[Window] = None): Option[(String, File)] = {
    val dlg = FileDialog.folder(init = child.flatMap(_.parentOption), title = "Choose Artifact Base Location")
    dlg.show(None) match {
      case Some(dir) =>
        child match {
          case Some(file) if Try(Artifact.relativize(dir, file)).isFailure => queryNew(child, window) // try again
          case _ =>
            val res = Dialog.showInput[String](null,
              "Enter initial store name:", "New Artifact Location",
              Dialog.Message.Question, initial = dir.name)
            res.map(_ -> dir)
        }
      case _=> None
    }
  }

  def create[S <: Sys[S]](name: String, directory: File)(implicit tx: S#Tx): ArtifactLocation[S] = {
    val peer  = ArtifactLocation.newVar[S](directory)
    peer.name = name
    peer
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy