src/Pure/GUI/swing_thread.scala
changeset 53783 f5e9d182f645
parent 52859 f31624cc4467
child 53853 e8430d668f44
equal deleted inserted replaced
53782:3746a78a2c01 53783:f5e9d182f645
       
     1 /*  Title:      Pure/GUI/swing_thread.scala
       
     2     Author:     Makarius
       
     3 
       
     4 Evaluation within the AWT/Swing thread.
       
     5 */
       
     6 
       
     7 package isabelle
       
     8 
       
     9 import javax.swing.{SwingUtilities, Timer}
       
    10 import java.awt.event.{ActionListener, ActionEvent}
       
    11 
       
    12 
       
    13 object Swing_Thread
       
    14 {
       
    15   /* checks */
       
    16 
       
    17   def assert[A](body: => A) =
       
    18   {
       
    19     Predef.assert(SwingUtilities.isEventDispatchThread())
       
    20     body
       
    21   }
       
    22 
       
    23   def require[A](body: => A) =
       
    24   {
       
    25     Predef.require(SwingUtilities.isEventDispatchThread())
       
    26     body
       
    27   }
       
    28 
       
    29 
       
    30   /* main dispatch queue */
       
    31 
       
    32   def now[A](body: => A): A =
       
    33   {
       
    34     if (SwingUtilities.isEventDispatchThread()) body
       
    35     else {
       
    36       lazy val result = { assert(); Exn.capture(body) }
       
    37       SwingUtilities.invokeAndWait(new Runnable { def run = result })
       
    38       Exn.release(result)
       
    39     }
       
    40   }
       
    41 
       
    42   def future[A](body: => A): Future[A] =
       
    43   {
       
    44     if (SwingUtilities.isEventDispatchThread()) Future.value(body)
       
    45     else Future.fork { now(body) }
       
    46   }
       
    47 
       
    48   def later(body: => Unit)
       
    49   {
       
    50     if (SwingUtilities.isEventDispatchThread()) body
       
    51     else SwingUtilities.invokeLater(new Runnable { def run = body })
       
    52   }
       
    53 
       
    54 
       
    55   /* delayed actions */
       
    56 
       
    57   abstract class Delay extends
       
    58   {
       
    59     def invoke(): Unit
       
    60     def revoke(): Unit
       
    61     def postpone(time: Time): Unit
       
    62   }
       
    63 
       
    64   private def delayed_action(first: Boolean)(time: => Time)(action: => Unit): Delay =
       
    65     new Delay {
       
    66       private val timer = new Timer(time.ms.toInt, null)
       
    67       timer.setRepeats(false)
       
    68       timer.addActionListener(new ActionListener {
       
    69         override def actionPerformed(e: ActionEvent) {
       
    70           assert()
       
    71           timer.setInitialDelay(time.ms.toInt)
       
    72           action
       
    73         }
       
    74       })
       
    75 
       
    76       def invoke()
       
    77       {
       
    78         require()
       
    79         if (first) timer.start() else timer.restart()
       
    80       }
       
    81 
       
    82       def revoke()
       
    83       {
       
    84         require()
       
    85         timer.stop()
       
    86         timer.setInitialDelay(time.ms.toInt)
       
    87       }
       
    88 
       
    89       def postpone(alt_time: Time)
       
    90       {
       
    91         require()
       
    92         if (timer.isRunning) {
       
    93           timer.setInitialDelay(timer.getInitialDelay max alt_time.ms.toInt)
       
    94           timer.restart()
       
    95         }
       
    96       }
       
    97     }
       
    98 
       
    99   // delayed action after first invocation
       
   100   def delay_first = delayed_action(true) _
       
   101 
       
   102   // delayed action after last invocation
       
   103   def delay_last = delayed_action(false) _
       
   104 }