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

de.sciss.mellite.impl.widget.WidgetFrameImpl.scala Maven / Gradle / Ivy

/*
 *  WidgetFrameImpl.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.widget

import de.sciss.lucre.BooleanObj
import de.sciss.lucre.edit.UndoManager
import de.sciss.lucre.expr.CellView
import de.sciss.lucre.swing.LucreSwing.deferTx
import de.sciss.lucre.swing.View
import de.sciss.lucre.synth.Txn
import de.sciss.mellite.impl.code.CodeFrameBase
import de.sciss.mellite.impl.code.CodeFrameImpl.titleView
import de.sciss.mellite.impl.{WindowImpl, WorkspaceWindowImpl}
import de.sciss.mellite.{CodeView, UniverseHandler, WidgetEditorFrame, WidgetEditorView, WidgetRenderFrame, WidgetRenderView}
import de.sciss.proc.Widget

import scala.collection.immutable.{Seq => ISeq}
import scala.swing.Action

object WidgetFrameImpl {
  def editor[T <: Txn[T]](obj: Widget[T], bottom: ISeq[View[T]])
                         (implicit tx: T, handler: UniverseHandler[T]): WidgetEditorFrame[T] =
    handler(obj, WidgetEditorFrame) {
      implicit val undo: UndoManager[T] = UndoManager()
      val showEditor  = obj.attr.$[BooleanObj](Widget.attrEditMode).forall(_.value)
      val view        = WidgetEditorView(obj, showEditor = showEditor, bottom = bottom)
      val res         = new EditorFrameImpl[T](view, tx).init()
      trackTitle(res, view.renderer, codeViewOpt = Some(view.codeView))
      res
    }

  def render[T <: Txn[T]](obj: Widget[T])
                         (implicit tx: T, handler: UniverseHandler[T]): WidgetRenderFrame[T] =
    handler(obj, WidgetRenderFrame)(newRenderFrame(obj))

  private def newRenderFrame[T <: Txn[T]](obj: Widget[T])
                         (implicit tx: T, handler: UniverseHandler[T]): WidgetRenderFrame[T] = {
    implicit val undoManagerTx: UndoManager[T] = UndoManager()
    val view  = WidgetRenderView(obj)
    val res   = new RenderFrameImpl[T](view).init()
    trackTitle(res, view, codeViewOpt = None)
    res
  }

  private def trackTitle[T <: Txn[T]](win: WindowImpl[T], renderer: WidgetRenderView[T],
                                      codeViewOpt: Option[CodeView[T, Widget.Graph]])(implicit tx: T): Unit = {
    val wd = renderer.widget
    val tv = codeViewOpt match {
      case Some(codeView) =>
        val contextName = "" // Widget.Code.humanName
        titleView(wd, codeView, contextName = contextName)
      case None =>
        CellView.name(wd)
    }
    win.setTitle(tv)
  }

  // ---- frame impl ----

  private final class RenderFrameImpl[T <: Txn[T]](val view: WidgetRenderView[T])
                                                  (implicit val handler: UniverseHandler[T])
    extends WidgetRenderFrame[T] with WorkspaceWindowImpl[T] {

    override def key: Key = WidgetRenderFrame

    override def newWindow()(implicit tx: T): WidgetRenderFrame[T] =
      newRenderFrame(view.obj)
  }

  private final class EditorFrameImpl[T <: Txn[T]](val view: WidgetEditorView[T], tx0: T)
                                                  (implicit val handler: UniverseHandler[T])
    extends WorkspaceWindowImpl[T] with CodeFrameBase[T] with WidgetEditorFrame[T] {
    
    import view.cursor

    protected def codeView: CodeView[T, _]      = view.codeView
    protected def renderer: WidgetRenderView[T] = view.renderer
    
    private[this] var rUndoName   = Option.empty[String]
    private[this] var rRedoName   = Option.empty[String]

    private[this] val rUndoObs = renderer.undoManager.react { implicit tx => upd =>
      deferTx {
        rUndoName = upd.undoName
        rRedoName = upd.redoName
        val tb = view.currentTab
        if (tb == WidgetEditorView.RendererTab) {
          undoAction.update(tb)
          redoAction.update(tb)
        }
      }
    } (tx0)

    // XXX TODO
    override def supportsNewWindow: Boolean = false

    override def newWindow()(implicit tx: T): Repr[T] = throw new UnsupportedOperationException

    override def dispose()(implicit tx: T): Unit = {
      super.dispose()
      rUndoObs.dispose()
    }

    override protected def initGUI(): Unit = {
      super.initGUI()
      mkExamplesMenu(Widget.Code.examples)
      view.addListener {
        case WidgetEditorView.TabChange(tb) =>
          undoAction.update(tb)
          redoAction.update(tb)
      }
    }

    private object undoAction extends Action("Undo") {
      enabled = false

      def update(tb: WidgetEditorView.Tab): Unit = {
        val undoName = tb match {
          case WidgetEditorView.EditorTab   => None // XXX TODO
          case WidgetEditorView.RendererTab => rUndoName
        }
        enabled = rUndoName.isDefined
        text    = undoName.fold("Undo")(n => s"Undo $n")
      }

      def apply(): Unit =
        view.currentTab match {
          case WidgetEditorView.EditorTab   => () // XXX TODO
          case WidgetEditorView.RendererTab =>
            val u = renderer.undoManager
            cursor.step { implicit tx =>
              if (u.canUndo) u.undo()
            }
        }
    }

    private object redoAction extends Action("Redo") {
      enabled = false

      def update(tb: WidgetEditorView.Tab): Unit = {
        val redoName = tb match {
          case WidgetEditorView.EditorTab   => None // XXX TODO
          case WidgetEditorView.RendererTab => rRedoName
        }
        enabled = rRedoName.isDefined
        text    = redoName.fold("Redo")(n => s"Redo $n")
      }

      def apply(): Unit =
        view.currentTab match {
          case WidgetEditorView.EditorTab   => () // XXX TODO
          case WidgetEditorView.RendererTab =>
            val u = renderer.undoManager
            cursor.step { implicit tx =>
              if (u.canRedo) u.redo()
            }
        }
    }

    override protected def undoRedoActions: Option[(Action, Action)] = {
      Some((undoAction, redoAction))
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy