diff --git a/main/pom.xml b/main/pom.xml index ad93007b5..0bd97ed7b 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -32,6 +32,7 @@ 1.0.10 12 + 4.7.0-9.1.2 2.6 3.8.1 @@ -139,6 +140,11 @@ javafx-fxml ${javafx.version} + + de.jensd + fontawesomefx-fontawesome + ${fontawesomefx.version} + diff --git a/main/ui/pom.xml b/main/ui/pom.xml index 1465683f0..bf8e89ce1 100644 --- a/main/ui/pom.xml +++ b/main/ui/pom.xml @@ -55,6 +55,10 @@ org.openjfx javafx-fxml + + de.jensd + fontawesomefx-fontawesome + diff --git a/main/ui/src/main/java/org/cryptomator/ui/FXMLLoaderFactory.java b/main/ui/src/main/java/org/cryptomator/ui/FXMLLoaderFactory.java new file mode 100644 index 000000000..146d16ae4 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/FXMLLoaderFactory.java @@ -0,0 +1,46 @@ +package org.cryptomator.ui; + +import javafx.fxml.FXMLLoader; + +import javax.inject.Inject; +import javax.inject.Provider; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.ResourceBundle; + +@FxApplicationScoped +public class FXMLLoaderFactory { + + private final Map, Provider> factories; + private final ResourceBundle resourceBundle; + + @Inject + FXMLLoaderFactory(Map, Provider> factories) { + this.factories = factories; + this.resourceBundle = ResourceBundle.getBundle("i18n.strings"); + } + + public FXMLLoader construct() { + FXMLLoader loader = new FXMLLoader(); + loader.setControllerFactory(this::constructController); + loader.setResources(resourceBundle); + return loader; + } + + public FXMLLoader load(String fxmlResourceName) throws IOException { + FXMLLoader loader = construct(); + try (InputStream in = getClass().getResourceAsStream(fxmlResourceName)) { + loader.load(in); + } + return loader; + } + + private FxController constructController(Class aClass) { + if (!factories.containsKey(aClass)) { + throw new IllegalArgumentException("ViewController not registered: " + aClass); + } else { + return factories.get(aClass).get(); + } + } +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java index f8136479f..8ffff75cd 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java @@ -1,14 +1,16 @@ package org.cryptomator.ui; import javafx.application.Application; +import javafx.scene.Parent; +import javafx.scene.Scene; import javafx.stage.Stage; -import org.cryptomator.ui.controllers.MainController; -import org.cryptomator.ui.controllers.ViewControllerLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.inject.Named; +import java.io.IOException; +import java.io.UncheckedIOException; @FxApplicationScoped public class FxApplication extends Application { @@ -16,24 +18,28 @@ public class FxApplication extends Application { private static final Logger LOG = LoggerFactory.getLogger(FxApplication.class); private final Stage primaryStage; - private final ViewControllerLoader fxmlLoader; + private final FXMLLoaderFactory fxmlLoaders; @Inject - FxApplication(@Named("mainWindow") Stage primaryStage, ViewControllerLoader fxmlLoader) { + FxApplication(@Named("mainWindow") Stage primaryStage, FXMLLoaderFactory fxmlLoaders) { this.primaryStage = primaryStage; - this.fxmlLoader = fxmlLoader; + this.fxmlLoaders = fxmlLoaders; } public void start() { - LOG.info("Starting GUI..."); - start(primaryStage); + try { + LOG.info("Starting GUI..."); + start(primaryStage); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } @Override - public void start(Stage primaryStage) { - MainController mainCtrl = fxmlLoader.load("/fxml/main.fxml"); - mainCtrl.initStage(primaryStage); - primaryStage.show(); + public void start(Stage stage) throws IOException { + Parent root = fxmlLoaders.load("/fxml/main_window.fxml").getRoot(); + stage.setScene(new Scene(root)); + stage.show(); } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java index 5482dd189..658204c9b 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java @@ -10,6 +10,7 @@ import dagger.Module; import dagger.Provides; import javafx.application.Application; import javafx.stage.Stage; +import javafx.stage.StageStyle; import javax.inject.Named; @@ -23,6 +24,7 @@ abstract class FxApplicationModule { Stage stage = new Stage(); stage.setMinWidth(652.0); stage.setMinHeight(440.0); + stage.initStyle(StageStyle.UNDECORATED); return stage; } diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxController.java b/main/ui/src/main/java/org/cryptomator/ui/FxController.java new file mode 100644 index 000000000..df717a5b2 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/FxController.java @@ -0,0 +1,9 @@ +/******************************************************************************* + * Copyright (c) 2017 Skymatic UG (haftungsbeschränkt). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the accompanying LICENSE file. + *******************************************************************************/ +package org.cryptomator.ui; + +public interface FxController { +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxControllerKey.java b/main/ui/src/main/java/org/cryptomator/ui/FxControllerKey.java new file mode 100644 index 000000000..a9cfbf739 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/FxControllerKey.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2017 Skymatic UG (haftungsbeschränkt). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the accompanying LICENSE file. + *******************************************************************************/ +package org.cryptomator.ui; + +import dagger.MapKey; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +// TODO rename after refactoring +@Documented +@Target(METHOD) +@Retention(RUNTIME) +@MapKey +public @interface FxControllerKey { + Class value(); +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/UiModule.java b/main/ui/src/main/java/org/cryptomator/ui/UiModule.java index 6c09147e1..59d652cc1 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/UiModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/UiModule.java @@ -16,7 +16,9 @@ import org.cryptomator.common.settings.Settings; import org.cryptomator.frontend.webdav.WebDavServer; import org.cryptomator.keychain.KeychainModule; import org.cryptomator.ui.controllers.ViewControllerModule; +import org.cryptomator.ui.mainwindow.MainWindowModule; import org.cryptomator.ui.model.VaultComponent; +import org.cryptomator.ui.vaultlist.VaultListModule; import org.fxmisc.easybind.EasyBind; import javax.inject.Named; @@ -27,7 +29,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -@Module(includes = {ViewControllerModule.class, KeychainModule.class}, subcomponents = {VaultComponent.class}) +@Module(includes = {ViewControllerModule.class, KeychainModule.class, VaultListModule.class, MainWindowModule.class}, subcomponents = {VaultComponent.class}) public class UiModule { private static final int NUM_SCHEDULER_THREADS = 4; diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java new file mode 100644 index 000000000..3a9cbc828 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java @@ -0,0 +1,55 @@ +package org.cryptomator.ui.mainwindow; + +import javafx.application.Application; +import javafx.fxml.FXML; +import javafx.scene.layout.HBox; +import javafx.stage.Stage; +import org.cryptomator.ui.FxApplicationScoped; +import org.cryptomator.ui.FxController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javax.inject.Named; +import java.util.concurrent.CountDownLatch; + +@FxApplicationScoped +public class MainWindowController implements FxController { + + private static final Logger LOG = LoggerFactory.getLogger(MainWindowController.class); + + private final CountDownLatch shutdownLatch; + private final Stage mainWindow; + + @FXML + public HBox titleBar; + + private double xOffset; + private double yOffset; + + @Inject + public MainWindowController(@Named("shutdownLatch") CountDownLatch shutdownLatch, @Named("mainWindow") Stage mainWindow) { + this.shutdownLatch = shutdownLatch; + this.mainWindow = mainWindow; + } + + @FXML + public void initialize() { + LOG.debug("init MainWindowController"); + titleBar.setOnMousePressed(event -> { + xOffset = event.getSceneX(); + yOffset = event.getSceneY(); + }); + titleBar.setOnMouseDragged(event -> { + titleBar.getScene().getWindow().setX(event.getScreenX() - xOffset); + titleBar.getScene().getWindow().setY(event.getScreenY() - yOffset); + }); + } + + @FXML + public void close() { + mainWindow.close(); + LOG.info("closed..."); + shutdownLatch.countDown(); + } +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java new file mode 100644 index 000000000..6a0344ee1 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java @@ -0,0 +1,18 @@ +package org.cryptomator.ui.mainwindow; + +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoMap; +import org.cryptomator.ui.FxController; +import org.cryptomator.ui.FxControllerKey; +import org.cryptomator.ui.vaultlist.VaultListController; + +@Module +public abstract class MainWindowModule { + + @Binds + @IntoMap + @FxControllerKey(MainWindowController.class) + abstract FxController bindController(MainWindowController controller); + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListController.java new file mode 100644 index 000000000..9e28ba9c5 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListController.java @@ -0,0 +1,25 @@ +package org.cryptomator.ui.vaultlist; + +import javafx.fxml.FXML; +import org.cryptomator.ui.FxApplicationScoped; +import org.cryptomator.ui.FxController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; + +@FxApplicationScoped +public class VaultListController implements FxController { + + private static final Logger LOG = LoggerFactory.getLogger(VaultListController.class); + + @Inject + public VaultListController() { + } + + @FXML + public void initialize() { + LOG.debug("init VaultListController"); + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListModule.java b/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListModule.java new file mode 100644 index 000000000..86ce99080 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListModule.java @@ -0,0 +1,17 @@ +package org.cryptomator.ui.vaultlist; + +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoMap; +import org.cryptomator.ui.FxController; +import org.cryptomator.ui.FxControllerKey; + +@Module +public abstract class VaultListModule { + + @Binds + @IntoMap + @FxControllerKey(VaultListController.class) + abstract FxController bindController(VaultListController controller); + +} diff --git a/main/ui/src/main/resources/fxml/main_window.fxml b/main/ui/src/main/resources/fxml/main_window.fxml new file mode 100644 index 000000000..d0730d023 --- /dev/null +++ b/main/ui/src/main/resources/fxml/main_window.fxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/main/ui/src/main/resources/fxml/vaultlist.fxml b/main/ui/src/main/resources/fxml/vaultlist.fxml new file mode 100644 index 000000000..344ceade7 --- /dev/null +++ b/main/ui/src/main/resources/fxml/vaultlist.fxml @@ -0,0 +1,9 @@ + + + + + + diff --git a/main/ui/src/main/resources/i18n/strings.properties b/main/ui/src/main/resources/i18n/strings.properties new file mode 100644 index 000000000..99c76666b --- /dev/null +++ b/main/ui/src/main/resources/i18n/strings.properties @@ -0,0 +1,3 @@ +main.closeBtn.tooltip=Close +main.settingsBtn.tooltip=Settings +title=Cryptomator \ No newline at end of file diff --git a/main/ui/src/main/resources/i18n/strings_de.properties b/main/ui/src/main/resources/i18n/strings_de.properties new file mode 100644 index 000000000..3f4eb3198 --- /dev/null +++ b/main/ui/src/main/resources/i18n/strings_de.properties @@ -0,0 +1,3 @@ +main.closeBtn.tooltip=Close +main.settingsBtn.tooltip=Settings +title=CryptomatorDE \ No newline at end of file diff --git a/main/ui/src/main/resources/i18n/strings_en.properties b/main/ui/src/main/resources/i18n/strings_en.properties new file mode 100644 index 000000000..8c23b81fa --- /dev/null +++ b/main/ui/src/main/resources/i18n/strings_en.properties @@ -0,0 +1,3 @@ +main.closeBtn.tooltip=Close +main.settingsBtn.tooltip=Settings +title=CryptomatorEN \ No newline at end of file