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

de.sciss.mellite.ActionNewWorkspace.scala Maven / Gradle / Ivy

/*
 *  ActionNewWorkspace.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.{FileDialog, KeyStrokes, OptionPane, Util}
import de.sciss.equal.Implicits._
import de.sciss.file._
import de.sciss.lucre.store.BerkeleyDB
import de.sciss.lucre.synth.{InMemory, Txn}
import de.sciss.lucre.{DataStore, Workspace}
import de.sciss.proc
import de.sciss.proc.Universe

import java.net.URI
import java.util.concurrent.TimeUnit
import scala.concurrent.duration.Duration
import scala.swing.event.Key
import scala.swing.{Action, Button, Label}
import scala.util.control.NonFatal

object ActionNewWorkspace extends Action("Workspace...") {
  import KeyStrokes._

  accelerator = Some(menu1 + shift + Key.N)

  private def deleteRecursive(f: File): Boolean = {
    if (f.isDirectory) {
      val arr = f.listFiles()
      var i = 0
      while (i < arr.length) {
        val f1 = arr(i)
        if (!deleteRecursive(f1)) return false
        i += 1
      }
    }
    f.delete()
  }

  private def fullTitle = "New Workspace"

  def apply(): Unit = {
    val tpeMessage = new Label("""Workspaces can be confluent or ephemeral.


|A confluent workspace keeps a trace of its history.


|An ephemeral workspace does not remember its history.
|An ephemeral workspace can either durable (stored on disk) or purely in-memory. |""".stripMargin ) val tpeEntries = Seq(("Confluent", Key.C), ("Durable", Key.D), ("In-Memory", Key.I)) .map { case (txt, key) => val b = new Button(txt) b.mnemonic = key b } val tpeDlg = OptionPane.buttons(message = tpeMessage, options = tpeEntries, initial = 1) tpeDlg.title = fullTitle val tpeRes = tpeDlg.show(title = fullTitle) if (tpeRes < 0) return val confluent = tpeRes == 0 val inMemory = tpeRes == 2 if (inMemory) performInMemory() else if (confluent) performConfluent() else performDurable() } def performInMemory(): (proc.Workspace.InMemory, Universe[InMemory.Txn]) = { val w = proc.Workspace.InMemory(meta = Mellite.meta) val u = Mellite.mkUniverse(w) OpenWorkspace.openGUI(u) (w, u) } def performDurable(): Option[(proc.Workspace.Durable, Universe[proc.Durable.Txn])] = create[proc.Durable.Txn, proc.Workspace.Durable] { (folder, config) => proc.Workspace.Durable.empty(folder, config, meta = Mellite.meta) } def performConfluent(): Option[(proc.Workspace.Confluent, Universe[proc.Confluent.Txn])] = create[proc.Confluent.Txn, proc.Workspace.Confluent] { (folder, config) => proc.Workspace.Confluent.empty(folder, config, meta = Mellite.meta) } private def selectFile(): Option[URI] = { val fileDlg = FileDialog.save(title = "Location for New Workspace") fileDlg.show(None).flatMap { folder0 => val name = folder0.name val folder = if (folder0.ext.toLowerCase == proc.Workspace.ext) folder0 else folder0.parent / s"$name.${proc.Workspace.ext}" val folderURI = folder.toURI val folderOpt = Some(folderURI) val isOpen = Application.documentHandler.documents.exists(_.workspace.folder === folderOpt) if (isOpen) { val optOvr = OptionPane.message( message = s"Workspace ${folder.path} already exists and is currently open.", messageType = OptionPane.Message.Error ) optOvr.title = fullTitle optOvr.show() None } else if (!folder.exists()) folderOpt else { val optOvr = OptionPane.confirmation( message = s"Workspace ${folder.path} already exists.\nAre you sure you want to overwrite it?", optionType = OptionPane.Options.OkCancel, messageType = OptionPane.Message.Warning ) optOvr.title = fullTitle val resOvr = optOvr.show() val isOk = resOvr === OptionPane.Result.Ok if (!isOk) None else if (deleteRecursive(folder)) folderOpt else { val optUnable = OptionPane.message( message = s"Unable to delete existing workspace ${folder.path}", messageType = OptionPane.Message.Error ) optUnable.title = fullTitle optUnable.show() None } } } } private def create[T <: Txn[T], A <: Workspace[T]](fun: (URI, DataStore.Factory) => A): Option[(A, Universe[T])] = selectFile().flatMap { folder => try { val config = BerkeleyDB.Config() config.allowCreate = true val ds = BerkeleyDB.factory(new File(folder), config) config.lockTimeout = Duration(Prefs.dbLockTimeout.getOrElse(Prefs.defaultDbLockTimeout), TimeUnit.MILLISECONDS) val w = fun(folder, ds) val u = Mellite.mkUniverse(w) OpenWorkspace.openGUI(u) Some((w, u)) } catch { case NonFatal(e) => val optUnable = OptionPane.message( message = s"Unable to create new workspace ${folder.getPath} \n\n${Util.formatException(e)}", messageType = OptionPane.Message.Error ) optUnable.title = fullTitle optUnable.show() None } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy