• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package kotlinx.coroutines.swing
2 
3 import kotlinx.coroutines.*
4 import kotlinx.coroutines.internal.*
5 import java.awt.event.*
6 import javax.swing.*
7 import kotlin.coroutines.*
8 
9 /**
10  * Dispatches execution onto Swing event dispatching thread and provides native [delay] support.
11  */
12 @Suppress("unused")
13 public val Dispatchers.Swing : SwingDispatcher
14     get() = kotlinx.coroutines.swing.Swing
15 
16 /**
17  * Dispatcher for Swing event dispatching thread.
18  *
19  * This class provides type-safety and a point for future extensions.
20  */
21 public sealed class SwingDispatcher : MainCoroutineDispatcher(), Delay {
22     /** @suppress */
dispatchnull23     override fun dispatch(context: CoroutineContext, block: Runnable): Unit = SwingUtilities.invokeLater(block)
24 
25     /** @suppress */
26     override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
27         val timer = schedule(timeMillis) {
28             with(continuation) { resumeUndispatched(Unit) }
29         }
30         continuation.invokeOnCancellation { timer.stop() }
31     }
32 
33     /** @suppress */
invokeOnTimeoutnull34     override fun invokeOnTimeout(timeMillis: Long, block: Runnable, context: CoroutineContext): DisposableHandle {
35         val timer = schedule(timeMillis) {
36             block.run()
37         }
38         return DisposableHandle { timer.stop() }
39     }
40 
schedulenull41     private fun schedule(timeMillis: Long, action: ActionListener): Timer =
42         Timer(timeMillis.coerceAtMost(Int.MAX_VALUE.toLong()).toInt(), action).apply {
43             isRepeats = false
44             start()
45         }
46 }
47 
48 internal class SwingDispatcherFactory : MainDispatcherFactory {
49     override val loadPriority: Int
50         get() = 0
51 
createDispatchernull52     override fun createDispatcher(allFactories: List<MainDispatcherFactory>): MainCoroutineDispatcher = Swing
53 }
54 
55 private object ImmediateSwingDispatcher : SwingDispatcher() {
56     override val immediate: MainCoroutineDispatcher
57         get() = this
58 
59     override fun isDispatchNeeded(context: CoroutineContext): Boolean = !SwingUtilities.isEventDispatchThread()
60 
61     override fun toString() = toStringInternalImpl() ?: "Swing.immediate"
62 }
63 
64 /**
65  * Dispatches execution onto Swing event dispatching thread and provides native [delay] support.
66  */
67 internal object Swing : SwingDispatcher() {
68 
69     /* A workaround so that the dispatcher's initialization crashes with an exception if running in a headless
70     environment. This is needed so that this broken dispatcher is not used as the source of delays. */
71     init {
<lambda>null72         Timer(1) { }.apply {
73             isRepeats = false
74             start()
75         }
76     }
77 
78     override val immediate: MainCoroutineDispatcher
79         get() = ImmediateSwingDispatcher
80 
toStringnull81     override fun toString() = toStringInternalImpl() ?: "Swing"
82 }
83