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.OpenWorkspace.scala Maven / Gradle / Ivy
/*
* OpenWorkspace.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
import de.sciss.desktop.{Desktop, FileDialog, KeyStrokes, Menu, OptionPane, RecentFiles, Util}
import de.sciss.file._
import de.sciss.lucre.Cursor
import de.sciss.lucre.expr.CellView
import de.sciss.lucre.store.BerkeleyDB
import de.sciss.lucre.swing.LucreSwing.defer
import de.sciss.lucre.synth.{AnyTxn, Executor, Txn}
import de.sciss.proc.{Confluent, Durable, Universe, Workspace}
import de.sciss.{desktop, proc}
import java.io.FileNotFoundException
import java.net.URI
import java.util.concurrent.TimeUnit
import javax.swing.SwingUtilities
import scala.concurrent.duration.Duration
import scala.concurrent.{Future, blocking}
import scala.swing.event.Key
import scala.swing.{Action, Dialog}
import scala.util.{Failure, Success, Try}
object OpenWorkspace {
// N.B.: we want `OpenWorkspace` to be usable in headless mode,
// therefore all UI things have to be lazily initialized
private lazy val _recent = RecentFiles(Application.userPrefs("recent-docs")) { folder =>
perform(folder.toURI)
}
object action extends Action("Open...") {
import KeyStrokes._
accelerator = Some(menu1 + Key.O)
private var lastDir = Option.empty[File]
def apply(): Unit = {
val dlg = FileDialog.folder(init = lastDir, title = fullTitle)
// import TypeCheckedTripleEquals._
// dlg.setFilter { f => f.isDirectory && f.ext.toLowerCase === Workspace.ext}
dlg.show(None).foreach { f =>
lastDir = f.parentOption
perform(f.toURI)
}
}
}
private def dh = Application.documentHandler
private def fullTitle = "Open Workspace"
private[this] lazy val _init: Unit =
Desktop.addListener {
case Desktop.OpenFiles(_, files) =>
// println(s"TODO: $open; EDT? ${java.awt.EventQueue.isDispatchThread}")
files.foreach { f =>
OpenWorkspace.perform(f.toURI)
}
}
def install(): Unit = _init
// XXX TODO: should be in another place
def openGUI[T <: Txn[T]](universe: Universe[T]): Unit = {
universe.workspace.folder.foreach { uri =>
val dirOpt = Try(new File(uri)).toOption
dirOpt.foreach(recentFiles.add)
}
dh.addDocument(universe)
universe.workspace match {
case cf: Workspace.Confluent =>
implicit val workspace: Workspace.Confluent = cf
implicit val cursor: Cursor[Durable.Txn] = workspace.system.durable
GUI.step[proc.Durable.Txn](fullTitle, s"Opening cursor window for '${cf.name}'") { implicit tx =>
implicit val u: Universe[Confluent.Txn] = universe.cast[Confluent.Txn]
DocumentCursorsFrame(cf)
}
case eph =>
implicit val cursor: Cursor[T] = eph.cursor
val nameView = CellView.const[T, String](eph.name)
GUI.step[T](fullTitle, s"Opening root elements window for '${eph.name}'") { implicit tx =>
// implicit val universe: Universe[T] = Universe(GenContext[T](), Scheduler[T](), Mellite.auralSystem)
implicit val u: Universe[T] = universe
implicit val handler: UniverseHandler[T] = UniverseHandler[T]()
FolderFrame[T](name = nameView, isWorkspaceRoot = true)
}
}
}
def recentFiles: RecentFiles = _recent
def recentMenu : Menu.Group = _recent.menu
// private def openView[T <: Txn[T]](universe: Universe[T]): Unit = ()
//// MMM
//// DocumentViewHandler.instance(doc).collectFirst {
//// case dcv: DocumentCursorsView => dcv.window
//// } .foreach(_.front())
def perform(folder: URI): Future[Universe[_]] = {
// val fOpt = Some(folder)
dh.documents.find(_.workspace.folder.contains(folder)).fold(open(folder, headless = false)) { u =>
// val u1 = u.asInstanceOf[Universe[T] forSome { type T <: Txn[T] }]
// openView(u1)
Mellite.withUniverse(u)(Future.successful)
}
}
def open(folder: URI, headless: Boolean): Future[Universe[_]] = {
import Executor.executionContext
val config = BerkeleyDB.Config()
val fFolder = new File(folder)
val fOpen = new File(fFolder, "open")
val fut: Future[Universe[_]] = {
// this check is actually performed by WorkspacePlatformImpl later,
// but if we fail here, we avoid the creation of `je.info.0` and `je.lck` files
// by `BerkeleyDB.factory`.
if (!fOpen.isFile) Future.failed(new FileNotFoundException(s"Not a workspace: ${fFolder.getPath}"))
else {
config.allowCreate = true // issue #179
// config.readOnly = true
config.lockTimeout = Duration(Prefs.dbLockTimeout.getOrElse(Prefs.defaultDbLockTimeout), TimeUnit.MILLISECONDS)
val ds = BerkeleyDB.factory(fFolder, config)
Future[Universe[_]] { // IntelliJ highlight bug
val w = blocking {
Workspace.read(folder, ds, meta = Mellite.meta).cast[AnyTxn]
}
Mellite.mkUniverse[w.Tx](w)
}
}
}
var opt: OptionPane[Unit] = null
if (!headless) desktop.Util.delay(1000) {
if (!fut.isCompleted) {
opt = OptionPane.message(message = s"Reading '$folder'…")
opt.show(None, "Open Workspace")
}
}
fut.onComplete { tr =>
defer {
if (opt != null) {
val w = SwingUtilities.getWindowAncestor(opt.peer)
if (w != null) w.dispose()
}
tr match {
case Success(u) => if (!headless) {
openGUI(u.cast[AnyTxn])
}
// case Success(cf : Workspace.Confluent) => openGUI(cf )
// case Success(eph: Workspace.Durable) => openGUI(eph)
// case Success(eph: Workspace.InMemory) => openGUI(eph)
case Failure(e) =>
val message = s"Unable to create new workspace ${folder.getPath}\n\n${Util.formatException(e)}"
if (headless) {
Console.err.println(message)
} else {
Dialog.showMessage(
message = message,
title = fullTitle,
messageType = Dialog.Message.Error
)
}
}
}
}
fut
}
}