87 lines
3.3 KiB
Java
87 lines
3.3 KiB
Java
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.common.Utils;
|
|
import io.gitlab.jfronny.inceptum.gtk.GtkEnvBackend;
|
|
import io.gitlab.jfronny.inceptum.gtk.GtkMain;
|
|
import io.gitlab.jfronny.inceptum.gtk.util.I18n;
|
|
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
|
|
import org.gtk.glib.GLib;
|
|
import org.gtk.gtk.*;
|
|
|
|
public class ProcessStateWatcherDialog extends MessageDialog {
|
|
private final ProcessState state;
|
|
private boolean finished = false;
|
|
private State cachedState = null;
|
|
|
|
public static ProcessStateWatcherDialog show(Window parent, String title, String errorMessage, ProcessState state, ThrowingRunnable<?> executor) {
|
|
ProcessStateWatcherDialog dialog = new ProcessStateWatcherDialog(parent, title, errorMessage, state, executor);
|
|
dialog.show();
|
|
return dialog;
|
|
}
|
|
|
|
public ProcessStateWatcherDialog(Window parent, String title, String errorMessage, ProcessState state, ThrowingRunnable<?> executor) {
|
|
//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
|
|
super(parent, DialogFlags.MODAL.or(DialogFlags.DESTROY_WITH_PARENT), MessageType.INFO, ButtonsType.NONE, null);
|
|
this.state = state;
|
|
this.title = title;
|
|
addButton(I18n.get("cancel"), ResponseType.CANCEL.value);
|
|
onResponse(responseId -> {
|
|
switch (ResponseType.of(responseId)) {
|
|
case CLOSE, CANCEL -> {
|
|
state.cancel();
|
|
close();
|
|
}
|
|
case DELETE_EVENT -> destroy();
|
|
default -> Utils.LOGGER.error("Unexpected response type: " + responseId);
|
|
}
|
|
});
|
|
onCloseRequest(() -> {
|
|
if (finished) return false;
|
|
state.cancel();
|
|
return false;
|
|
});
|
|
var progress = new ProgressBar();
|
|
((Box) messageArea).append(progress);
|
|
addTickCallback((widget, clock) -> {
|
|
if (finished) return GLib.SOURCE_REMOVE;
|
|
var nc = new State(state);
|
|
if (!nc.equals(cachedState)) {
|
|
cachedState = nc;
|
|
setMarkup(cachedState.msg);
|
|
progress.fraction = Math.min(cachedState.progress, 1);
|
|
widget.queueDraw();
|
|
}
|
|
return GLib.SOURCE_CONTINUE;
|
|
}, null);
|
|
new Thread(() -> {
|
|
try {
|
|
executor.run();
|
|
} catch (Throwable e) {
|
|
state.cancel();
|
|
Utils.LOGGER.error(errorMessage, e);
|
|
GtkEnvBackend.simpleDialog(
|
|
parent,
|
|
StringFormatter.toString(e),
|
|
errorMessage,
|
|
MessageType.ERROR,
|
|
ButtonsType.CLOSE,
|
|
null,
|
|
null
|
|
);
|
|
} finally {
|
|
finished = true;
|
|
GtkMain.schedule(this::close);
|
|
}
|
|
}).start();
|
|
}
|
|
|
|
record State(String msg, float progress) {
|
|
State(ProcessState source) {
|
|
this(source.currentStep, source.progress);
|
|
}
|
|
}
|
|
}
|