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 extends FxController> 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