src/Pure/System/swing_thread.scala
author wenzelm
Tue, 29 May 2012 20:20:32 +0200
changeset 48017 9f7b27635b57
parent 48000 880f1693299a
child 49195 9d10bd85c1be
permissions -rw-r--r--
tuned message;

/*  Title:      Pure/System/swing_thread.scala
    Module:     PIDE
    Author:     Makarius
    Author:     Fabian Immler, TU Munich

Evaluation within the AWT/Swing thread.
*/

package isabelle

import javax.swing.{SwingUtilities, Timer}
import java.awt.event.{ActionListener, ActionEvent}


object Swing_Thread
{
  /* checks */

  def assert() = Predef.assert(SwingUtilities.isEventDispatchThread())
  def require() = Predef.require(SwingUtilities.isEventDispatchThread())


  /* main dispatch queue */

  def now[A](body: => A): A =
  {
    if (SwingUtilities.isEventDispatchThread()) body
    else {
      lazy val result = { assert(); Exn.capture(body) }
      SwingUtilities.invokeAndWait(new Runnable { def run = result })
      Exn.release(result)
    }
  }

  def future[A](body: => A): Future[A] =
  {
    if (SwingUtilities.isEventDispatchThread()) Future.value(body)
    else Future.fork { now(body) }
  }

  def later(body: => Unit)
  {
    if (SwingUtilities.isEventDispatchThread()) body
    else SwingUtilities.invokeLater(new Runnable { def run = body })
  }


  /* delayed actions */

  private def delayed_action(first: Boolean)(time: Time)(action: => Unit): Boolean => Unit =
  {
    val listener = new ActionListener {
      override def actionPerformed(e: ActionEvent) { Swing_Thread.assert(); action }
    }
    val timer = new Timer(time.ms.toInt, listener)
    timer.setRepeats(false)

    def invoke() { later { if (first) timer.start() else timer.restart() } }
    def revoke() { timer.stop() }

    (active: Boolean) => if (active) invoke() else revoke()
  }

  // delayed action after first invocation
  def delay_first = delayed_action(true) _

  // delayed action after last invocation
  def delay_last = delayed_action(false) _
}