Reuse existing Stages and Scenes

This commit is contained in:
Sebastian Stenzel
2019-07-29 16:07:34 +02:00
parent 10e842e457
commit fead9a48eb
17 changed files with 182 additions and 56 deletions

View File

@@ -6,12 +6,15 @@ import dagger.Provides;
import dagger.multibindings.IntoMap;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.mainwindow.MainWindow;
import javax.inject.Provider;
@@ -48,6 +51,20 @@ public abstract class AddVaultModule {
return new SimpleObjectProperty<>();
}
@Provides
@FxmlScene(FxmlFile.ADDVAULT_WELCOME)
@AddVaultWizardScoped
static Scene provideWelcomeScene(@AddVaultWizard FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/addvault_welcome.fxml");
}
@Provides
@FxmlScene(FxmlFile.ADDVAULT_EXISTING)
@AddVaultWizardScoped
static Scene provideChooseExistingVaultScene(@AddVaultWizard FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/addvault_existing.fxml");
}
// ------------------
@Binds

View File

@@ -1,24 +1,28 @@
package org.cryptomator.ui.addvaultwizard;
import dagger.Lazy;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
@AddVaultWizardScoped
public class AddVaultWelcomeController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(AddVaultWelcomeController.class);
private final Stage window;
private final FXMLLoaderFactory fxmlLoaders;
private final Lazy<Scene> chooseExistingVaultScene;
@Inject
AddVaultWelcomeController(@AddVaultWizard Stage window, @AddVaultWizard FXMLLoaderFactory fxmlLoaders) {
AddVaultWelcomeController(@AddVaultWizard Stage window, @FxmlScene(FxmlFile.ADDVAULT_EXISTING) Lazy<Scene> chooseExistingVaultScene) {
this.window = window;
this.fxmlLoaders = fxmlLoaders;
this.chooseExistingVaultScene = chooseExistingVaultScene;
}
public void createNewVault() {
@@ -28,6 +32,6 @@ public class AddVaultWelcomeController implements FxController {
public void chooseExistingVault() {
LOG.debug("AddVaultWelcomeController.chooseExistingVault()");
fxmlLoaders.setScene("/fxml/addvault_existing.fxml", window);
window.setScene(chooseExistingVaultScene.get());
}
}

View File

@@ -5,9 +5,15 @@
*******************************************************************************/
package org.cryptomator.ui.addvaultwizard;
import dagger.Lazy;
import dagger.Subcomponent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import javax.inject.Named;
@AddVaultWizardScoped
@Subcomponent(modules = {AddVaultModule.class})
@@ -16,12 +22,12 @@ public interface AddVaultWizardComponent {
@AddVaultWizard
Stage window();
@AddVaultWizard
FXMLLoaderFactory fxmlLoaders();
@FxmlScene(FxmlFile.ADDVAULT_WELCOME)
Lazy<Scene> scene();
default void showAddVaultWizard() {
Stage stage = window();
fxmlLoaders().setScene("/fxml/addvault_welcome.fxml", stage);
stage.setScene(scene().get());
stage.sizeToScene();
stage.show();
}

View File

@@ -1,17 +1,22 @@
package org.cryptomator.ui.addvaultwizard;
import dagger.Lazy;
import javafx.beans.property.ObjectProperty;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.model.Vault;
import org.cryptomator.ui.model.VaultFactory;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.File;
import java.nio.file.Path;
import java.util.ResourceBundle;
@@ -20,16 +25,16 @@ import java.util.ResourceBundle;
public class ChooseExistingVaultController implements FxController {
private final Stage window;
private final FXMLLoaderFactory fxmlLoaders;
private final Lazy<Scene> welcomeScene;
private final ObjectProperty<Path> vaultPath;
private final ObservableList<Vault> vaults;
private final VaultFactory vaultFactory;
private final ResourceBundle resourceBundle;
@Inject
ChooseExistingVaultController(@AddVaultWizard Stage window, @AddVaultWizard FXMLLoaderFactory fxmlLoaders, ObjectProperty<Path> vaultPath, ObservableList<Vault> vaults, VaultFactory vaultFactory, ResourceBundle resourceBundle) {
ChooseExistingVaultController(@AddVaultWizard Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy<Scene> welcomeScene, ObjectProperty<Path> vaultPath, ObservableList<Vault> vaults, VaultFactory vaultFactory, ResourceBundle resourceBundle) {
this.window = window;
this.fxmlLoaders = fxmlLoaders;
this.welcomeScene = welcomeScene;
this.vaultPath = vaultPath;
this.vaults = vaults;
this.vaultFactory = vaultFactory;
@@ -49,7 +54,7 @@ public class ChooseExistingVaultController implements FxController {
@FXML
public void back() {
fxmlLoaders.setScene("/fxml/addvault_welcome.fxml", window);
window.setScene(welcomeScene.get());
}
@FXML

View File

@@ -47,20 +47,19 @@ public class FXMLLoaderFactory {
}
/**
* {@link #load(String) Loads} the FXML file and sets the given stage's scene to a new Scene containing the loaded ui.
* {@link #load(String) Loads} the FXML file and creates a new Scene containing the loaded ui.
* @param fxmlResourceName Name of the resource (as in {@link Class#getResource(String)}).
* @param stage The stage which should get a new scene
* @throws UncheckedIOException wrapping any IOException thrown by {@link #load(String)).
*/
public void setScene(String fxmlResourceName, Stage stage) throws UncheckedIOException {
public Scene createScene(String fxmlResourceName) {
final FXMLLoader loader;
try {
loader = load(fxmlResourceName);
} catch (IOException e) {
throw new UncheckedIOException("Failed to load " + fxmlResourceName, e);
} Parent root = loader.getRoot();
Scene scene = new Scene(root);
stage.setScene(scene);
}
Parent root = loader.getRoot();
return new Scene(root);
}
private FxController constructController(Class<?> aClass) {

View File

@@ -0,0 +1,16 @@
package org.cryptomator.ui.common;
public enum FxmlFile {
MAIN_WINDOW("/fxml/main_window.fxml"), //
ADDVAULT_WELCOME("/fxml/addvault_welcome.fxml"), //
ADDVAULT_EXISTING("/fxml/addvault_existing.fxml"), //
PREFERENCES("/fxml/preferences.fxml"), //
UNLOCK("/fxml/unlock2.fxml"), // TODO rename
;
private final String filename;
FxmlFile(String filename) {
this.filename = filename;
}
}

View File

@@ -0,0 +1,16 @@
package org.cryptomator.ui.common;
import javax.inject.Qualifier;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface FxmlScene {
FxmlFile value();
}

View File

@@ -1,5 +1,6 @@
package org.cryptomator.ui.fxapp;
import dagger.Lazy;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
@@ -24,12 +25,12 @@ public class FxApplication extends Application {
private static final Logger LOG = LoggerFactory.getLogger(FxApplication.class);
private final Settings settings;
private final MainWindowComponent.Builder mainWindow;
private final PreferencesComponent.Builder preferencesWindow;
private final Lazy<MainWindowComponent> mainWindow;
private final Lazy<PreferencesComponent> preferencesWindow;
private final Optional<MacFunctions> macFunctions;
@Inject
FxApplication(Settings settings, MainWindowComponent.Builder mainWindow, PreferencesComponent.Builder preferencesWindow, Optional<MacFunctions> macFunctions) {
FxApplication(Settings settings, Lazy<MainWindowComponent> mainWindow, Lazy<PreferencesComponent> preferencesWindow, Optional<MacFunctions> macFunctions) {
this.settings = settings;
this.mainWindow = mainWindow;
this.preferencesWindow = preferencesWindow;
@@ -42,10 +43,6 @@ public class FxApplication extends Application {
settings.theme().addListener(this::themeChanged);
loadSelectedStyleSheet(settings.theme().get());
if (Desktop.getDesktop().isSupported(Desktop.Action.APP_PREFERENCES)) {
Desktop.getDesktop().setPreferencesHandler(this::handlePreferences);
}
}
@Override
@@ -53,19 +50,17 @@ public class FxApplication extends Application {
throw new UnsupportedOperationException("Use start() instead.");
}
private void handlePreferences(PreferencesEvent preferencesEvent) {
showPreferencesWindow();
}
public void showPreferencesWindow() {
Platform.runLater(() -> {
preferencesWindow.build().showPreferencesWindow();
preferencesWindow.get().showPreferencesWindow();
LOG.debug("Showing Preferences");
});
}
public void showMainWindow() {
Platform.runLater(() -> {
mainWindow.build().showMainWindow();
mainWindow.get().showMainWindow();
LOG.debug("Showing MainWindow");
});
}

View File

@@ -6,6 +6,7 @@
package org.cryptomator.ui.fxapp;
import dagger.Binds;
import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
import javafx.application.Application;
@@ -27,6 +28,7 @@ abstract class FxApplicationModule {
@FxApplicationScoped
abstract Application provideApplication(FxApplication application);
// TODO move to commons...
@Binds
abstract ObservableList<Vault> bindVaultList(VaultList vaultList);
@@ -41,5 +43,15 @@ abstract class FxApplicationModule {
static ResourceBundle provideLocalization() {
return ResourceBundle.getBundle("i18n.strings");
}
@Provides
static MainWindowComponent provideMainWindowComponent(MainWindowComponent.Builder builder) {
return builder.build();
}
@Provides
static PreferencesComponent providePreferencesComponent(PreferencesComponent.Builder builder) {
return builder.build();
}
}

View File

@@ -5,30 +5,32 @@
*******************************************************************************/
package org.cryptomator.ui.mainwindow;
import dagger.Lazy;
import dagger.Subcomponent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
@MainWindowScoped
@Subcomponent(modules = {MainWindowModule.class})
public interface MainWindowComponent {
@MainWindow
Stage window();
@MainWindow
FXMLLoaderFactory fxmlLoaders();
@FxmlScene(FxmlFile.MAIN_WINDOW)
Lazy<Scene> scene();
default void showMainWindow() {
Stage stage = window();
fxmlLoaders().setScene("/fxml/main_window.fxml", stage);
stage.setScene(scene().get());
stage.show();
}
@Subcomponent.Builder
interface Builder {
MainWindowComponent build();
}

View File

@@ -4,12 +4,15 @@ import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.unlock.UnlockComponent;
import javax.inject.Provider;
@@ -40,6 +43,13 @@ abstract class MainWindowModule {
return stage;
}
@Provides
@FxmlScene(FxmlFile.MAIN_WINDOW)
@MainWindowScoped
static Scene provideMainScene(@MainWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/main_window.fxml");
}
// ------------------
@Binds

View File

@@ -5,9 +5,13 @@
*******************************************************************************/
package org.cryptomator.ui.preferences;
import dagger.Lazy;
import dagger.Subcomponent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
@PreferencesScoped
@Subcomponent(modules = {PreferencesModule.class})
@@ -16,12 +20,12 @@ public interface PreferencesComponent {
@PreferencesWindow
Stage window();
@PreferencesWindow
FXMLLoaderFactory fxmlLoaders();
@FxmlScene(FxmlFile.PREFERENCES)
Lazy<Scene> scene();
default void showPreferencesWindow() {
Stage stage = window();
fxmlLoaders().setScene("/fxml/preferences.fxml", stage);
stage.setScene(scene().get());
stage.show();
}

View File

@@ -4,11 +4,14 @@ import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import javax.inject.Provider;
import java.util.Map;
@@ -36,6 +39,13 @@ abstract class PreferencesModule {
return stage;
}
@Provides
@FxmlScene(FxmlFile.PREFERENCES)
@PreferencesScoped
static Scene providePreferencesScene(@PreferencesWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/preferences.fxml");
}
// ------------------
@Binds

View File

@@ -3,6 +3,8 @@ package org.cryptomator.ui.traymenu;
import javafx.application.Platform;
import org.cryptomator.ui.fxapp.FxApplication;
import org.cryptomator.ui.fxapp.FxApplicationComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.util.concurrent.CompletableFuture;
@@ -10,6 +12,8 @@ import java.util.concurrent.ExecutionException;
@TrayMenuScoped
public class FxApplicationStarter {
private static final Logger LOG = LoggerFactory.getLogger(FxApplicationStarter.class);
private final CompletableFuture<FxApplication> future;
private final FxApplicationComponent.Builder fxAppComponent;
@@ -35,8 +39,10 @@ public class FxApplicationStarter {
}
private void start() {
LOG.debug("Starting JavaFX runtime...");
Platform.startup(() -> {
assert Platform.isFxApplicationThread();
LOG.debug("JavaFX Runtime started.");
FxApplication app = fxAppComponent.build().application();
app.start();
future.complete(app);

View File

@@ -1,19 +1,16 @@
package org.cryptomator.ui.traymenu;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import java.awt.Desktop;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.event.ActionEvent;
import java.util.EventObject;
import java.util.concurrent.CountDownLatch;
@TrayMenuScoped
public class TrayMenuController {
private static final Logger LOG = LoggerFactory.getLogger(TrayMenuController.class);
class TrayMenuController {
private final FxApplicationStarter fxApplicationStarter;
private final CountDownLatch shutdownLatch;
@@ -25,7 +22,7 @@ public class TrayMenuController {
this.shutdownLatch = shutdownLatch;
this.menu = new PopupMenu();
}
public PopupMenu getMenu() {
return menu;
}
@@ -33,27 +30,40 @@ public class TrayMenuController {
public void initTrayMenu() {
// TODO add listeners
rebuildMenu();
// register preferences shortcut
if (Desktop.getDesktop().isSupported(Desktop.Action.APP_PREFERENCES)) {
Desktop.getDesktop().setPreferencesHandler(this::showPreferencesWindow);
}
}
private void rebuildMenu() {
MenuItem showMainWindowItem = new MenuItem("TODO show");
showMainWindowItem.addActionListener(this::showMainWindow);
menu.add(showMainWindowItem);
MenuItem showPreferencesItem = new MenuItem("TODO preferences");
showPreferencesItem.addActionListener(this::showPreferencesWindow);
menu.add(showPreferencesItem);
menu.addSeparator();
// foreach vault: add submenu
menu.addSeparator();
MenuItem quitApplicationItem = new MenuItem("TODO quit");
quitApplicationItem.addActionListener(this::quitApplication);
menu.add(quitApplicationItem);
}
private void showMainWindow(ActionEvent actionEvent) {
fxApplicationStarter.get().showMainWindow();
}
private void showPreferencesWindow(EventObject actionEvent) {
fxApplicationStarter.get().showPreferencesWindow();
}
private void quitApplication(ActionEvent actionEvent) {
shutdownLatch.countDown();
}

View File

@@ -6,9 +6,13 @@
package org.cryptomator.ui.unlock;
import dagger.BindsInstance;
import dagger.Lazy;
import dagger.Subcomponent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.model.Vault;
@UnlockScoped
@@ -18,12 +22,12 @@ public interface UnlockComponent {
@UnlockWindow
Stage window();
@UnlockWindow
FXMLLoaderFactory fxmlLoaders();
@FxmlScene(FxmlFile.UNLOCK)
Lazy<Scene> scene();
default void showUnlockWindow() {
Stage stage = window();
fxmlLoaders().setScene("/fxml/unlock2.fxml", stage); // TODO rename fxml file
stage.setScene(scene().get());
stage.show();
}

View File

@@ -4,11 +4,14 @@ import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import javax.inject.Provider;
import java.util.Map;
@@ -34,6 +37,13 @@ abstract class UnlockModule {
stage.initModality(Modality.APPLICATION_MODAL);
return stage;
}
@Provides
@FxmlScene(FxmlFile.UNLOCK)
@UnlockScoped
static Scene provideUnlockScene(@UnlockWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/unlock2.fxml"); // TODO rename fxml file
}
// ------------------