diff --git a/app/src/main/java/io/xpipe/app/comp/base/AppMainWindowContentComp.java b/app/src/main/java/io/xpipe/app/comp/base/AppMainWindowContentComp.java index 444caf6d2..9b6a4abfb 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/AppMainWindowContentComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/AppMainWindowContentComp.java @@ -13,11 +13,14 @@ import io.xpipe.app.util.PlatformThread; import io.xpipe.core.process.OsType; import javafx.animation.Animation; +import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.ListChangeListener; import javafx.geometry.Pos; import javafx.scene.image.ImageView; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; +import javafx.stage.Stage; import javafx.util.Duration; import atlantafx.base.util.Animations; @@ -26,6 +29,10 @@ import java.time.Instant; public class AppMainWindowContentComp extends SimpleComp { + private final Stage stage; + + public AppMainWindowContentComp(Stage stage) {this.stage = stage;} + @Override protected Region createSimple() { var overlay = AppDialog.getModalOverlay(); @@ -81,9 +88,21 @@ public class AppMainWindowContentComp extends SimpleComp { } }); + overlay.addListener((ListChangeListener) c -> { + if (c.next() && c.wasAdded()) { + stage.requestFocus(); + } + }); + + loaded.addListener((observable, oldValue, newValue) -> { + if (newValue != null) { + stage.requestFocus(); + } + }); + return pane; }); - var modal = new ModalOverlayComp(bg, overlay); + var modal = new ModalOverlayStackComp(bg, overlay); return modal.createRegion(); } } diff --git a/app/src/main/java/io/xpipe/app/comp/base/ModalOverlay.java b/app/src/main/java/io/xpipe/app/comp/base/ModalOverlay.java index cb15a04fb..9b1fdb6e5 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/ModalOverlay.java +++ b/app/src/main/java/io/xpipe/app/comp/base/ModalOverlay.java @@ -61,7 +61,7 @@ public class ModalOverlay { } public void show() { - AppDialog.show(this, false, true); + AppDialog.show(this, false); } public void showAndWait() { diff --git a/app/src/main/java/io/xpipe/app/comp/base/ModalOverlayStackComp.java b/app/src/main/java/io/xpipe/app/comp/base/ModalOverlayStackComp.java new file mode 100644 index 000000000..62a854390 --- /dev/null +++ b/app/src/main/java/io/xpipe/app/comp/base/ModalOverlayStackComp.java @@ -0,0 +1,41 @@ +package io.xpipe.app.comp.base; + +import io.xpipe.app.comp.Comp; +import io.xpipe.app.comp.SimpleComp; +import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.ObservableList; +import javafx.scene.layout.Region; + +public class ModalOverlayStackComp extends SimpleComp { + + private final Comp background; + private final ObservableList modalOverlay; + + public ModalOverlayStackComp(Comp background, ObservableList modalOverlay) { + this.background = background; + this.modalOverlay = modalOverlay; + } + + @Override + protected Region createSimple() { + var current = background; + for (var i = 0; i < 5; i++) { + current = buildModalOverlay(current, i); + } + return current.createRegion(); + } + + private Comp buildModalOverlay(Comp current, int index) { + var prop = new SimpleObjectProperty(); + modalOverlay.subscribe(() -> { + prop.set(modalOverlay.size() > index ? modalOverlay.get(index) : null); + }); + prop.addListener((observable, oldValue, newValue) -> { + if (newValue == null) { + modalOverlay.remove(oldValue); + } + }); + var comp = new ModalOverlayComp(current, prop); + return comp; + } +} diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryWrapper.java b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryWrapper.java index 2992b1249..d55088cf6 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryWrapper.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryWrapper.java @@ -173,17 +173,15 @@ public class StoreEntryWrapper { notes.setValue(new StoreNotes(entry.getNotes(), entry.getNotes())); customIcon.setValue(entry.getIcon()); iconFile.setValue(entry.getEffectiveIconFile()); - busy.setValue(entry.getBusyCounter().get() != 0); deletable.setValue(entry.getConfiguration().isDeletable()); sessionActive.setValue(entry.getStore() instanceof SingletonSessionStore ss && entry.getStore() instanceof ShellStore && ss.isSessionRunning()); - - category.setValue(StoreViewState.get() - .getCategoryWrapper(DataStorage.get() - .getStoreCategoryIfPresent(entry.getCategoryUuid()) - .orElseThrow())); + category.setValue(StoreViewState.get().getCategories().getList().stream() + .filter(storeCategoryWrapper -> storeCategoryWrapper.getCategory().getUuid() + .equals(entry.getCategoryUuid())).findFirst().orElse(StoreViewState.get() + .getAllConnectionsCategory())); perUser.setValue(!category.getValue().getRoot().equals(StoreViewState.get().getAllIdentitiesCategory()) && entry.isPerUserStore()); if (!entry.getValidity().isUsable()) { diff --git a/app/src/main/java/io/xpipe/app/core/window/AppDialog.java b/app/src/main/java/io/xpipe/app/core/window/AppDialog.java index c83d5360e..f5c2f819f 100644 --- a/app/src/main/java/io/xpipe/app/core/window/AppDialog.java +++ b/app/src/main/java/io/xpipe/app/core/window/AppDialog.java @@ -13,6 +13,9 @@ import javafx.animation.PauseTransition; import javafx.application.Platform; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; import javafx.scene.layout.StackPane; import javafx.scene.text.Text; import javafx.util.Duration; @@ -24,7 +27,7 @@ import java.util.concurrent.atomic.AtomicBoolean; public class AppDialog { @Getter - private static final ObjectProperty modalOverlay = new SimpleObjectProperty<>(); + private static final ObservableList modalOverlay = FXCollections.observableArrayList(); private static void showMainWindow() { PlatformInit.init(true); @@ -32,69 +35,44 @@ public class AppDialog { } public static void closeDialog(ModalOverlay overlay) { - if (modalOverlay.get() == overlay) { - modalOverlay.setValue(null); - } + modalOverlay.remove(overlay); } public static void waitForClose() { - while (modalOverlay.getValue() != null) { + while (!modalOverlay.isEmpty()) { ThreadHelper.sleep(10); } } public static void showAndWait(ModalOverlay o) { - showMainWindow(); - waitForClose(); - if (!Platform.isFxApplicationThread()) { - PlatformThread.runLaterIfNeededBlocking(() -> { - modalOverlay.setValue(o); - }); - waitForClose(); - ThreadHelper.sleep(200); - } else { - var key = new Object(); - PlatformThread.runLaterIfNeededBlocking(() -> { - modalOverlay.setValue(o); - modalOverlay.addListener((observable, oldValue, newValue) -> { - if (oldValue == o && newValue == null) { - var transition = new PauseTransition(Duration.millis(200)); - transition.setOnFinished(e -> { - Platform.exitNestedEventLoop(key, null); - }); - transition.play(); - } - }); - }); - Platform.enterNestedEventLoop(key); - waitForClose(); - } + show(o, true); } - public static void show(ModalOverlay o, boolean wait, boolean replaceExisting) { + public static void show(ModalOverlay o, boolean wait) { showMainWindow(); - if (!replaceExisting) { - waitForClose(); - } if (!Platform.isFxApplicationThread()) { PlatformThread.runLaterIfNeededBlocking(() -> { - modalOverlay.setValue(o); + modalOverlay.add(o); }); waitForClose(); ThreadHelper.sleep(200); } else { var key = new Object(); PlatformThread.runLaterIfNeededBlocking(() -> { - modalOverlay.setValue(o); - modalOverlay.addListener((observable, oldValue, newValue) -> { - if (oldValue == o && newValue == null) { - var transition = new PauseTransition(Duration.millis(200)); - transition.setOnFinished(e -> { - if (wait) { - Platform.exitNestedEventLoop(key, null); - } - }); - transition.play(); + modalOverlay.add(o); + modalOverlay.addListener(new ListChangeListener<>() { + @Override + public void onChanged(Change c) { + if (!c.getList().contains(o)) { + var transition = new PauseTransition(Duration.millis(200)); + transition.setOnFinished(e -> { + if (wait) { + Platform.exitNestedEventLoop(key, null); + } + }); + transition.play(); + modalOverlay.removeListener(this); + } } }); }); diff --git a/app/src/main/java/io/xpipe/app/core/window/AppMainWindow.java b/app/src/main/java/io/xpipe/app/core/window/AppMainWindow.java index e35ecd981..9ef8050ad 100644 --- a/app/src/main/java/io/xpipe/app/core/window/AppMainWindow.java +++ b/app/src/main/java/io/xpipe/app/core/window/AppMainWindow.java @@ -86,7 +86,7 @@ public class AppMainWindow { var stage = App.getApp().getStage(); INSTANCE = new AppMainWindow(stage); - var content = new AppMainWindowContentComp().createRegion(); + var content = new AppMainWindowContentComp(stage).createRegion(); content.opacityProperty() .bind(Bindings.createDoubleBinding( () -> { diff --git a/app/src/main/java/io/xpipe/app/issue/ErrorHandlerComp.java b/app/src/main/java/io/xpipe/app/issue/ErrorHandlerComp.java index 888e3ed63..c9cb61504 100644 --- a/app/src/main/java/io/xpipe/app/issue/ErrorHandlerComp.java +++ b/app/src/main/java/io/xpipe/app/issue/ErrorHandlerComp.java @@ -161,7 +161,6 @@ public class ErrorHandlerComp extends SimpleComp { var layout = new VBox(); layout.getChildren().add(content); layout.getStyleClass().add("error-handler-comp"); - layout.getStyleClass().add("background"); if (event.getThrowable() != null) { content.getChildren().add(new Separator(Orientation.HORIZONTAL)); diff --git a/app/src/main/java/io/xpipe/app/issue/ErrorHandlerDialog.java b/app/src/main/java/io/xpipe/app/issue/ErrorHandlerDialog.java index dd8a62bf0..a354efe5e 100644 --- a/app/src/main/java/io/xpipe/app/issue/ErrorHandlerDialog.java +++ b/app/src/main/java/io/xpipe/app/issue/ErrorHandlerDialog.java @@ -57,6 +57,6 @@ public class ErrorHandlerDialog { } }); - AppDialog.show(modal.get(), true, false); + AppDialog.show(modal.get(), true); } }