101 lines
3.2 KiB
Kotlin
101 lines
3.2 KiB
Kotlin
package io.gitlab.jfronny.inceptum.gtk.window.dialog
|
|
|
|
import io.gitlab.jfronny.commons.StringFormatter
|
|
import io.gitlab.jfronny.commons.throwable.ThrowingRunnable
|
|
import io.gitlab.jfronny.inceptum.gtk.GtkEnvBackend
|
|
import io.gitlab.jfronny.inceptum.gtk.schedule
|
|
import io.gitlab.jfronny.inceptum.gtk.util.I18n
|
|
import io.gitlab.jfronny.inceptum.gtk.util.Log
|
|
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState
|
|
import org.gnome.glib.GLib
|
|
import org.gnome.gtk.*
|
|
|
|
class ProcessStateWatcherDialog(
|
|
parent: Window?,
|
|
title: String,
|
|
errorMessage: String,
|
|
private val state: ProcessState,
|
|
executor: ThrowingRunnable<*>
|
|
) : MessageDialog(
|
|
parent,
|
|
DialogFlags.MODAL.or(DialogFlags.DESTROY_WITH_PARENT),
|
|
MessageType.INFO,
|
|
ButtonsType.NONE,
|
|
null
|
|
) {
|
|
private var finished = false
|
|
private var cachedState: State? = null
|
|
|
|
init {
|
|
//TODO alternate UI: Only show progress bar by default, but have a dropdown to a "console" with the actual steps
|
|
// this should make visualizing parallelized steps easier
|
|
this.title = title
|
|
addButton(I18n["cancel"], ResponseType.CANCEL.value)
|
|
onResponse { responseId: Int ->
|
|
when (ResponseType.of(responseId)) {
|
|
ResponseType.CLOSE, ResponseType.CANCEL -> {
|
|
state.cancel()
|
|
close()
|
|
}
|
|
|
|
ResponseType.DELETE_EVENT -> destroy()
|
|
else -> Log.error("Unexpected response type: $responseId")
|
|
}
|
|
}
|
|
onCloseRequest {
|
|
if (finished) return@onCloseRequest false
|
|
state.cancel()
|
|
false
|
|
}
|
|
val progress = ProgressBar()
|
|
(messageArea as Box).append(progress)
|
|
addTickCallback { widget, _ ->
|
|
if (finished) return@addTickCallback GLib.SOURCE_REMOVE
|
|
val nc = State(state)
|
|
if (nc != cachedState) {
|
|
cachedState = nc
|
|
setMarkup(cachedState!!.msg)
|
|
progress.fraction = cachedState!!.progress.coerceAtMost(1f).toDouble()
|
|
widget.queueDraw()
|
|
}
|
|
GLib.SOURCE_CONTINUE
|
|
}
|
|
Thread {
|
|
try {
|
|
executor.run()
|
|
} catch (e: Throwable) {
|
|
state.cancel()
|
|
Log.error(errorMessage, e)
|
|
GtkEnvBackend.simpleDialog(
|
|
parent,
|
|
StringFormatter.toString(e),
|
|
errorMessage,
|
|
null,
|
|
null
|
|
)
|
|
} finally {
|
|
finished = true
|
|
schedule { close() }
|
|
}
|
|
}.start()
|
|
}
|
|
|
|
data class State(val msg: String, val progress: Float) {
|
|
constructor(source: ProcessState) : this(source.currentStep, source.progress)
|
|
}
|
|
|
|
companion object {
|
|
fun show(
|
|
parent: Window?,
|
|
title: String,
|
|
errorMessage: String,
|
|
state: ProcessState,
|
|
executor: ThrowingRunnable<*>
|
|
): ProcessStateWatcherDialog {
|
|
val dialog = ProcessStateWatcherDialog(parent, title, errorMessage, state, executor)
|
|
dialog.visible = true
|
|
return dialog
|
|
}
|
|
}
|
|
}
|