1 /* 2 * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 5 package kotlinx.coroutines.swing 6 7 import kotlinx.coroutines.* 8 import kotlinx.coroutines.internal.* 9 import java.awt.event.* 10 import java.util.concurrent.* 11 import javax.swing.* 12 import kotlin.coroutines.* 13 14 /** 15 * Dispatches execution onto Swing event dispatching thread and provides native [delay] support. 16 */ 17 @Suppress("unused") 18 public val Dispatchers.Swing : SwingDispatcher 19 get() = kotlinx.coroutines.swing.Swing 20 21 /** 22 * Dispatcher for Swing event dispatching thread. 23 * 24 * This class provides type-safety and a point for future extensions. 25 */ 26 public sealed class SwingDispatcher : MainCoroutineDispatcher(), Delay { 27 /** @suppress */ dispatchnull28 override fun dispatch(context: CoroutineContext, block: Runnable): Unit = SwingUtilities.invokeLater(block) 29 30 /** @suppress */ 31 override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) { 32 val timer = schedule(timeMillis, TimeUnit.MILLISECONDS, ActionListener { 33 with(continuation) { resumeUndispatched(Unit) } 34 }) 35 continuation.invokeOnCancellation { timer.stop() } 36 } 37 38 /** @suppress */ invokeOnTimeoutnull39 override fun invokeOnTimeout(timeMillis: Long, block: Runnable, context: CoroutineContext): DisposableHandle { 40 val timer = schedule(timeMillis, TimeUnit.MILLISECONDS, ActionListener { 41 block.run() 42 }) 43 return object : DisposableHandle { 44 override fun dispose() { 45 timer.stop() 46 } 47 } 48 } 49 schedulenull50 private fun schedule(time: Long, unit: TimeUnit, action: ActionListener): Timer = 51 Timer(unit.toMillis(time).coerceAtMost(Int.MAX_VALUE.toLong()).toInt(), action).apply { 52 isRepeats = false 53 start() 54 } 55 } 56 57 internal class SwingDispatcherFactory : MainDispatcherFactory { 58 override val loadPriority: Int 59 get() = 0 60 createDispatchernull61 override fun createDispatcher(allFactories: List<MainDispatcherFactory>): MainCoroutineDispatcher = Swing 62 } 63 64 private object ImmediateSwingDispatcher : SwingDispatcher() { 65 override val immediate: MainCoroutineDispatcher 66 get() = this 67 68 override fun isDispatchNeeded(context: CoroutineContext): Boolean = !SwingUtilities.isEventDispatchThread() 69 70 override fun toString() = toStringInternalImpl() ?: "Swing.immediate" 71 } 72 73 /** 74 * Dispatches execution onto Swing event dispatching thread and provides native [delay] support. 75 */ 76 internal object Swing : SwingDispatcher() { 77 override val immediate: MainCoroutineDispatcher 78 get() = ImmediateSwingDispatcher 79 toStringnull80 override fun toString() = toStringInternalImpl() ?: "Swing" 81 } 82