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

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

/*
 *  TrackTools.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.awt.Cursor
import javax.swing.Icon
import javax.swing.undo.UndoableEdit

import de.sciss.lucre.stm
import de.sciss.lucre.synth.Sys
import de.sciss.mellite.gui.impl.ProcObjView
import de.sciss.mellite.gui.impl.tracktool.{AuditionImpl, CursorImpl, FadeImpl, FunctionImpl, GainImpl, MoveImpl, MuteImpl, PaletteImpl, PatchImpl, ResizeImpl, ToolsImpl}
import de.sciss.model.{Change, Model}
import de.sciss.span.Span
import de.sciss.synth.proc.FadeSpec

import scala.annotation.switch
import scala.collection.immutable.{IndexedSeq => Vec}
import scala.swing.Component

object TrackTools {
  sealed trait Update[S <: stm.Sys[S]]
  final case class ToolChanged          [S <: stm.Sys[S]](change: Change[TrackTool[S, _]]) extends Update[S]
  final case class VisualBoostChanged   [S <: stm.Sys[S]](change: Change[Float          ]) extends Update[S]
  final case class FadeViewModeChanged  [S <: stm.Sys[S]](change: Change[FadeViewMode   ]) extends Update[S]
  final case class RegionViewModeChanged[S <: stm.Sys[S]](change: Change[RegionViewMode ]) extends Update[S]

  def apply  [S <: Sys[S]](canvas: TimelineProcCanvas[S]): TrackTools[S] = new ToolsImpl(canvas)
  def palette[S <: Sys[S]](control: TrackTools[S], tools: Vec[TrackTool[S, _]]): Component =
    new PaletteImpl[S](control, tools)
}

object RegionViewMode {
  /** No visual indicator for region borders */
  case object None      extends RegionViewMode { final val id = 0 }
  /** Rounded box for region borders */
  case object Box       extends RegionViewMode { final val id = 1 }
  /** Rounded box with region name for region borders */
  case object TitledBox extends RegionViewMode { final val id = 2 }

  def apply(id: Int): RegionViewMode = (id: @switch) match {
    case None     .id => None
    case Box      .id => Box
    case TitledBox.id => TitledBox
  }
}
sealed trait RegionViewMode { def id: Int }

object FadeViewMode {
  /** No visual indicator for fades */
  case object None     extends FadeViewMode { final val id = 0 }
  /** Curve overlays to indicate fades */
  case object Curve    extends FadeViewMode { final val id = 1 }
  /** Gain adjustments to sonogram to indicate fades */
  case object Sonogram extends FadeViewMode { final val id = 2 }

  def apply(id: Int): FadeViewMode = (id: @switch) match {
    case None    .id  => None
    case Curve   .id  => Curve
    case Sonogram.id  => Sonogram
  }
}
sealed trait FadeViewMode {
  def id: Int
}

trait TrackTools[S <: stm.Sys[S]] extends Model[TrackTools.Update[S]] {
  var currentTool   : TrackTool[S, _]
  var visualBoost   : Float
  var fadeViewMode  : FadeViewMode
  var regionViewMode: RegionViewMode
}

object TrackTool {
  trait Rectangular {
    def trackIndex: Int
    def trackHeight: Int
    def span: Span

    def isValid: Boolean = trackIndex >= 0
  }

  sealed trait Update[+A]
  case object DragBegin  extends Update[Nothing]
  final case class DragAdjust[A](value: A) extends Update[A]

  final case class DragRubber(trackIndex: Int, trackHeight: Int, span: Span)
    extends Update[Nothing] with Rectangular

  case object DragEnd    extends Update[Nothing] // (commit: AbstractCompoundEdit)
  case object DragCancel extends Update[Nothing]

  /** Direct adjustment without drag period. */
  case class Adjust[A](value: A) extends Update[A]

  val EmptyRubber = DragRubber(-1, -1, Span(0L, 0L))

  // ----

  type Move   = ProcActions.Move
  val  Move   = ProcActions.Move
  type Resize = ProcActions.Resize
  val  Resize = ProcActions.Resize
  final case class Gain    (factor: Float)
  final case class Mute    (engaged: Boolean)
  final case class Fade    (deltaFadeIn: Long, deltaFadeOut: Long, deltaFadeInCurve: Float, deltaFadeOutCurve: Float)

  final val NoMove      = Move(deltaTime = 0L, deltaTrack = 0, copy = false)
  final val NoResize    = Resize(deltaStart = 0L, deltaStop = 0L)
  final val NoGain      = Gain(1f)
  final val NoFade      = Fade(0L, 0L, 0f, 0f)
  final val NoFunction  = Function(-1, -1, Span(0L, 0L))

  final case class Function(trackIndex: Int, trackHeight: Int, span: Span)
    extends Update[Nothing] with Rectangular

  final case class Cursor  (name: Option[String])

  object Patch {
    sealed trait Sink[+S]
    case class Linked[S <: Sys[S]](proc: ProcObjView.Timeline[S]) extends Sink[S]
    case class Unlinked(frame: Long, y: Int) extends Sink[Nothing]
  }
  final case class Patch[S <: Sys[S]](source: ProcObjView.Timeline[S], sink: Patch.Sink[S])

  final val EmptyFade = FadeSpec(numFrames = 0L)

  type Listener = Model.Listener[Update[Any]]

  def cursor  [S <: Sys[S]](canvas: TimelineProcCanvas[S]): TrackTool[S, Cursor  ] = new CursorImpl  (canvas)
  def move    [S <: Sys[S]](canvas: TimelineProcCanvas[S]): TrackTool[S, Move    ] = new MoveImpl    (canvas)
  def resize  [S <: Sys[S]](canvas: TimelineProcCanvas[S]): TrackTool[S, Resize  ] = new ResizeImpl  (canvas)
  def gain    [S <: Sys[S]](canvas: TimelineProcCanvas[S]): TrackTool[S, Gain    ] = new GainImpl    (canvas)
  def mute    [S <: Sys[S]](canvas: TimelineProcCanvas[S]): TrackTool[S, Mute    ] = new MuteImpl    (canvas)
  def fade    [S <: Sys[S]](canvas: TimelineProcCanvas[S]): TrackTool[S, Fade    ] = new FadeImpl    (canvas)
  def function[S <: Sys[S]](canvas: TimelineProcCanvas[S], view: TimelineView[S]): TrackTool[S, Function] =
    new FunctionImpl(canvas, view)

  def patch   [S <: Sys[S]](canvas: TimelineProcCanvas[S]): TrackTool[S, Patch[S]] = new PatchImpl   (canvas)

  def audition[S <: Sys[S]](canvas: TimelineProcCanvas[S], view: TimelineView[S]): TrackTool[S, Unit] =
    new AuditionImpl(canvas, view)
}

/** A tool that operates on object inside the timeline view.
  *
  * @tparam A   the type of element that represents an ongoing
  *             edit state (typically during mouse drag).
  */
trait TrackTool[S <: stm.Sys[S], A] extends Model[TrackTool.Update[A]] {
  /** The mouse cursor used when the tool is active. */
  def defaultCursor: Cursor
  /** The icon to use in a tool bar. */
  def icon: Icon
  /** The human readable name of the tool. */
  def name: String

  /** Called to activate the tool to operate on the given component. */
  def install  (component: Component): Unit
  /** Called to deactivate the tool before switching to a different tool. */
  def uninstall(component: Component): Unit

  // def handleSelect(e: MouseEvent, hitTrack: Int, pos: Long, regionOpt: Option[TimelineProcView[S]]): Unit

  /** Called after the end of a mouse drag gesture. If this constitutes a
    * valid edit, the method should return the resulting undoable edit.
    *
    * @param drag   the last editing state
    * @param cursor the cursor that might be needed to construct the undoable edit
    * @return either `Some` edit or `None` if the action does not constitute an
    *         edit or the edit parameters are invalid.
    */
  def commit(drag: A)(implicit tx: S#Tx, cursor: stm.Cursor[S]): Option[UndoableEdit]
}

//object TrackSlideTool {
//  case class Slide(deltaOuter: Long, deltaInner: Long)
//}
//
//class TrackSlideTool(trackList: TrackList, timelineModel: TimelineView)
//  extends BasicTrackRegionTool[TrackSlideTool.Slide](trackList, timelineModel) {
//
//  import TrackSlideTool._
//
//  def defaultCursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)
//
//  val name = "Slide"
//
//  protected def dialog: Option[Slide] = None // not yet supported
//
//  protected def dragToParam(d: Drag): Slide = {
//    val amt = d.currentPos - d.firstPos
//    if (d.firstEvent.isAltDown)
//      Slide(0L, -amt)
//    else
//      Slide(amt, 0L)
//  }
//}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy