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

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

/*
 *  ActionOpenWorkspace.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.mellite
package gui

import java.util.concurrent.TimeUnit
import javax.swing.SwingUtilities

import de.sciss.desktop
import de.sciss.desktop.{KeyStrokes, OptionPane, FileDialog, Menu, RecentFiles}
import de.sciss.file._
import de.sciss.lucre.stm.store.BerkeleyDB
import de.sciss.lucre.swing.{CellView, defer}
import de.sciss.lucre.synth.Sys
import de.sciss.synth.proc
import de.sciss.synth.proc.SoundProcesses

import scala.concurrent.duration.Duration
import scala.concurrent.{Future, blocking}
import scala.language.existentials
import scala.swing.event.Key
import scala.swing.{Action, Dialog}
import scala.util.{Failure, Success}

object ActionOpenWorkspace extends Action("Open...") {
  import KeyStrokes._

  private val _recent = RecentFiles(Application.userPrefs("recent-docs")) { folder =>
    perform(folder)
  }

  accelerator = Some(menu1 + Key.O)

  private def dh = Application.documentHandler
  private def fullTitle = "Open Workspace"

  // XXX TODO: should be in another place
  def openGUI[S <: Sys[S]](doc: Workspace[S]): Unit = {
    doc.folder.foreach(recentFiles.add)
    dh.addDocument(doc)
    doc match {
      case cf: Workspace.Confluent =>
        implicit val workspace: Workspace.Confluent  = cf
        implicit val cursor = workspace.system.durable
        GUI.atomic[proc.Durable, Unit](fullTitle, s"Opening cursor window for '${doc.name}'") {
          implicit tx => DocumentCursorsFrame(cf)
        }
      case eph =>
        implicit val workspace: Workspace[S] = eph
        implicit val cursor = eph.cursor
        val nameView = CellView.const[S, String](doc.name)
        GUI.atomic[S, Unit](fullTitle, s"Opening root elements window for '${doc.name}'") {
          implicit tx => FolderFrame[S](name = nameView, isWorkspaceRoot = true)
        }
    }
  }

  def recentFiles: RecentFiles  = _recent
  def recentMenu : Menu.Group   = _recent.menu

  def apply(): Unit = {
    val dlg = FileDialog.folder(title = fullTitle)
    // import TypeCheckedTripleEquals._
    // dlg.setFilter { f => f.isDirectory && f.ext.toLowerCase === Workspace.ext}
    dlg.show(None).foreach(perform)
  }

  private def openView[S <: Sys[S]](doc: Workspace[S]): Unit = ()
// MMM
//    DocumentViewHandler.instance(doc).collectFirst {
//      case dcv: DocumentCursorsView => dcv.window
//    } .foreach(_.front())

  def perform(folder: File): Unit = {
    import de.sciss.equal.Implicits._
    val fOpt = Some(folder)
    dh.documents.find(_.folder === fOpt).fold(doOpen(folder)) { doc =>
      val doc1 = doc.asInstanceOf[Workspace[S] forSome { type S <: Sys[S] }]
      openView(doc1)
    }
  }

  private def doOpen(folder: File): Unit = {
    import SoundProcesses.executionContext
    val config          = BerkeleyDB.Config()
    config.lockTimeout  = Duration(Prefs.dbLockTimeout.getOrElse(Prefs.defaultDbLockTimeout), TimeUnit.MILLISECONDS)
    val fut: Future[WorkspaceLike] = Future(blocking(Workspace.read(folder, config)))

    var opt: OptionPane[Unit] = null
    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(cf : Workspace.Confluent) => openGUI(cf )
          case Success(eph: Workspace.Durable)   => openGUI(eph)
          case Success(eph: Workspace.InMemory)  => openGUI(eph)
          case Failure(e) =>
            Dialog.showMessage(
              message     = s"Unable to create new workspace ${folder.path}\n\n${GUI.formatException(e)}",
              title       = fullTitle,
              messageType = Dialog.Message.Error
            )
          // case _ =>
        }
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy