mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-17 10:11:27 +00:00
added tray icon, refactored dagger component graph:
singleton -> tray -> fxapplication -> mainwindow
This commit is contained in:
@@ -5,11 +5,10 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.launcher;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.logging.DebugMode;
|
||||
import org.cryptomator.logging.LoggerConfiguration;
|
||||
import org.cryptomator.ui.FxApplication;
|
||||
import org.cryptomator.ui.traymenu.TrayMenuComponent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -34,15 +33,17 @@ public class Cryptomator {
|
||||
private final Optional<String> applicationVersion;
|
||||
private final CountDownLatch shutdownLatch;
|
||||
private final CleanShutdownPerformer shutdownPerformer;
|
||||
private final TrayMenuComponent.Builder trayComponent;
|
||||
|
||||
@Inject
|
||||
Cryptomator(LoggerConfiguration logConfig, DebugMode debugMode, IpcFactory ipcFactory, @Named("applicationVersion") Optional<String> applicationVersion, @Named("shutdownLatch") CountDownLatch shutdownLatch, CleanShutdownPerformer shutdownPerformer) {
|
||||
Cryptomator(LoggerConfiguration logConfig, DebugMode debugMode, IpcFactory ipcFactory, @Named("applicationVersion") Optional<String> applicationVersion, @Named("shutdownLatch") CountDownLatch shutdownLatch, CleanShutdownPerformer shutdownPerformer, TrayMenuComponent.Builder trayComponent) {
|
||||
this.logConfig = logConfig;
|
||||
this.debugMode = debugMode;
|
||||
this.ipcFactory = ipcFactory;
|
||||
this.applicationVersion = applicationVersion;
|
||||
this.shutdownLatch = shutdownLatch;
|
||||
this.shutdownPerformer = shutdownPerformer;
|
||||
this.trayComponent = trayComponent;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@@ -89,7 +90,7 @@ public class Cryptomator {
|
||||
private int runGuiApplication() {
|
||||
try {
|
||||
shutdownPerformer.registerShutdownHook();
|
||||
CRYPTOMATOR_COMPONENT.fxApplicationComponent().start();
|
||||
trayComponent.build().addIconToSystemTray();
|
||||
shutdownLatch.await();
|
||||
LOG.info("UI shut down");
|
||||
return 0;
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.cryptomator.launcher;
|
||||
import dagger.Component;
|
||||
import org.cryptomator.common.CommonsModule;
|
||||
import org.cryptomator.logging.LoggerModule;
|
||||
import org.cryptomator.ui.FxApplicationComponent;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationComponent;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@@ -13,6 +13,4 @@ public interface CryptomatorComponent {
|
||||
|
||||
Cryptomator application();
|
||||
|
||||
FxApplicationComponent fxApplicationComponent();
|
||||
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.settings.SettingsProvider;
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.UiModule;
|
||||
import org.cryptomator.ui.model.AppLaunchEvent;
|
||||
import org.cryptomator.ui.model.VaultComponent;
|
||||
import org.cryptomator.ui.traymenu.TrayMenuComponent;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
@@ -15,7 +17,7 @@ import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Module
|
||||
@Module(includes = {UiModule.class}, subcomponents = {VaultComponent.class, TrayMenuComponent.class})
|
||||
class CryptomatorModule {
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.jni.JniException;
|
||||
import org.cryptomator.jni.MacApplicationUiState;
|
||||
import org.cryptomator.jni.MacFunctions;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.cryptomator.ui.l10n.Localization;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -16,10 +16,11 @@ import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.frontend.webdav.WebDavServer;
|
||||
import org.cryptomator.keychain.KeychainModule;
|
||||
import org.cryptomator.ui.model.VaultComponent;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -27,13 +28,15 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Module(includes = {KeychainModule.class}, subcomponents = {VaultComponent.class})
|
||||
// TODO move to common...
|
||||
@Deprecated(forRemoval = true, since = "1.5.0")
|
||||
@Module(includes = {KeychainModule.class})
|
||||
public class UiModule {
|
||||
|
||||
private static final int NUM_SCHEDULER_THREADS = 4;
|
||||
|
||||
@Provides
|
||||
@FxApplicationScoped
|
||||
@Singleton
|
||||
ScheduledExecutorService provideScheduledExecutorService(@Named("shutdownTaskScheduler") Consumer<Runnable> shutdownTaskScheduler) {
|
||||
final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(NUM_SCHEDULER_THREADS, r -> {
|
||||
@@ -48,7 +51,7 @@ public class UiModule {
|
||||
|
||||
// TODO @Binds abstract ExecutorService bindExecutorService(ScheduledExecutorService executor); ?
|
||||
@Provides
|
||||
@FxApplicationScoped
|
||||
@Singleton
|
||||
ExecutorService provideExecutorService(@Named("shutdownTaskScheduler") Consumer<Runnable> shutdownTaskScheduler) {
|
||||
final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||
ExecutorService executorService = Executors.newCachedThreadPool(r -> {
|
||||
@@ -62,7 +65,7 @@ public class UiModule {
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxApplicationScoped
|
||||
@Singleton
|
||||
Binding<InetSocketAddress> provideServerSocketAddressBinding(Settings settings) {
|
||||
return Bindings.createObjectBinding(() -> {
|
||||
String host = SystemUtils.IS_OS_WINDOWS ? "127.0.0.1" : "localhost";
|
||||
@@ -71,7 +74,7 @@ public class UiModule {
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxApplicationScoped
|
||||
@Singleton
|
||||
WebDavServer provideWebDavServer(Binding<InetSocketAddress> serverSocketAddressBinding) {
|
||||
WebDavServer server = WebDavServer.create();
|
||||
// no need to unsubscribe eventually, because server is a singleton
|
||||
|
||||
@@ -44,7 +44,7 @@ import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.Duration;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
import org.cryptomator.ui.ExitUtil;
|
||||
import org.cryptomator.ui.controls.DirectoryListCell;
|
||||
|
||||
@@ -8,7 +8,7 @@ package org.cryptomator.ui.controllers;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.StringConverter;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.settings.VolumeImpl;
|
||||
import org.cryptomator.ui.l10n.Localization;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
package org.cryptomator.ui.controllers;
|
||||
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.cryptomator.ui.l10n.Localization;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -23,7 +23,7 @@ import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ProgressIndicator;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.ui.l10n.Localization;
|
||||
import org.cryptomator.ui.common.Tasks;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.cryptomator.ui;
|
||||
package org.cryptomator.ui.fxapp;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
@@ -38,6 +38,7 @@ public class FxApplication extends Application {
|
||||
|
||||
public void start() {
|
||||
LOG.trace("FxApplication.start()");
|
||||
Platform.setImplicitExit(false);
|
||||
|
||||
settings.theme().addListener(this::themeChanged);
|
||||
loadSelectedStyleSheet(settings.theme().get());
|
||||
@@ -45,8 +46,6 @@ public class FxApplication extends Application {
|
||||
if (Desktop.getDesktop().isSupported(Desktop.Action.APP_PREFERENCES)) {
|
||||
Desktop.getDesktop().setPreferencesHandler(this::handlePreferences);
|
||||
}
|
||||
|
||||
mainWindow.build().showMainWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,11 +54,19 @@ public class FxApplication extends Application {
|
||||
}
|
||||
|
||||
private void handlePreferences(PreferencesEvent preferencesEvent) {
|
||||
Platform.runLater(this::showPreferencesWindow);
|
||||
showPreferencesWindow();
|
||||
}
|
||||
|
||||
public void showPreferencesWindow() {
|
||||
preferencesWindow.build().showPreferencesWindow();
|
||||
Platform.runLater(() -> {
|
||||
preferencesWindow.build().showPreferencesWindow();
|
||||
});
|
||||
}
|
||||
|
||||
public void showMainWindow() {
|
||||
Platform.runLater(() -> {
|
||||
mainWindow.build().showMainWindow();
|
||||
});
|
||||
}
|
||||
|
||||
private void themeChanged(@SuppressWarnings("unused") ObservableValue<? extends UiTheme> observable, @SuppressWarnings("unused") UiTheme oldValue, UiTheme newValue) {
|
||||
@@ -3,22 +3,20 @@
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the accompanying LICENSE file.
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.ui;
|
||||
package org.cryptomator.ui.fxapp;
|
||||
|
||||
import dagger.Subcomponent;
|
||||
import javafx.application.Platform;
|
||||
|
||||
@FxApplicationScoped
|
||||
@Subcomponent(modules = FxApplicationModule.class)
|
||||
public interface FxApplicationComponent {
|
||||
|
||||
FxApplication application();
|
||||
|
||||
default void start() {
|
||||
Platform.startup(() -> {
|
||||
assert Platform.isFxApplicationThread();
|
||||
application().start();
|
||||
});
|
||||
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
|
||||
FxApplicationComponent build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the accompanying LICENSE file.
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.ui;
|
||||
package org.cryptomator.ui.fxapp;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
@@ -12,6 +12,7 @@ import javafx.application.Application;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.cryptomator.ui.UiModule;
|
||||
import org.cryptomator.ui.mainwindow.MainWindowComponent;
|
||||
import org.cryptomator.ui.model.Vault;
|
||||
import org.cryptomator.ui.model.VaultList;
|
||||
@@ -19,7 +20,7 @@ import org.cryptomator.ui.preferences.PreferencesComponent;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@Module(includes = {UiModule.class}, subcomponents = {MainWindowComponent.class, PreferencesComponent.class})
|
||||
@Module(subcomponents = {MainWindowComponent.class, PreferencesComponent.class})
|
||||
abstract class FxApplicationModule {
|
||||
|
||||
@Binds
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.cryptomator.ui;
|
||||
package org.cryptomator.ui.fxapp;
|
||||
|
||||
import javax.inject.Scope;
|
||||
import java.lang.annotation.Documented;
|
||||
@@ -7,7 +7,7 @@ package org.cryptomator.ui.l10n;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ package org.cryptomator.ui.mainwindow;
|
||||
import dagger.Subcomponent;
|
||||
import javafx.stage.Stage;
|
||||
import org.cryptomator.ui.common.FXMLLoaderFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@MainWindowScoped
|
||||
@Subcomponent(modules = {MainWindowModule.class})
|
||||
|
||||
@@ -4,7 +4,7 @@ import javafx.fxml.FXML;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.stage.Stage;
|
||||
import org.cryptomator.ui.FxApplication;
|
||||
import org.cryptomator.ui.fxapp.FxApplication;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -18,7 +18,6 @@ public class MainWindowController implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MainWindowController.class);
|
||||
|
||||
private final CountDownLatch shutdownLatch;
|
||||
private final Stage window;
|
||||
private final FxApplication application;
|
||||
public HBox titleBar;
|
||||
@@ -27,8 +26,7 @@ public class MainWindowController implements FxController {
|
||||
private double yOffset;
|
||||
|
||||
@Inject
|
||||
public MainWindowController(@Named("shutdownLatch") CountDownLatch shutdownLatch, @MainWindow Stage window, FxApplication application) {
|
||||
this.shutdownLatch = shutdownLatch;
|
||||
public MainWindowController(@MainWindow Stage window, FxApplication application) {
|
||||
this.window = window;
|
||||
this.application = application;
|
||||
}
|
||||
@@ -54,8 +52,6 @@ public class MainWindowController implements FxController {
|
||||
@FXML
|
||||
public void close() {
|
||||
window.close();
|
||||
LOG.info("closed...");
|
||||
shutdownLatch.countDown();
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.ui.model;
|
||||
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.cryptomator.cryptolib.api.CryptoException;
|
||||
import org.cryptomator.keychain.KeychainAccess;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.ui.model;
|
||||
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@FxApplicationScoped
|
||||
@Singleton
|
||||
public class VaultFactory {
|
||||
|
||||
private final VaultComponent.Builder vaultComponentBuilder;
|
||||
|
||||
@@ -9,15 +9,15 @@ import com.google.common.collect.Lists;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.collections.transformation.TransformationList;
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@FxApplicationScoped
|
||||
@Singleton
|
||||
public class VaultList extends TransformationList<Vault, VaultSettings> {
|
||||
|
||||
private final VaultFactory vaultFactory;
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
package org.cryptomator.ui.model;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Set;
|
||||
@@ -19,7 +20,7 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
@FxApplicationScoped
|
||||
@Singleton
|
||||
public final class WindowsDriveLetters {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(WindowsDriveLetters.class);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.ui.model.upgrade;
|
||||
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.cryptomator.ui.model.Vault;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -7,7 +7,7 @@ package org.cryptomator.ui.model.upgrade;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.cryptomator.cryptolib.Cryptors;
|
||||
import org.cryptomator.cryptolib.api.Cryptor;
|
||||
import org.cryptomator.ui.l10n.Localization;
|
||||
|
||||
@@ -7,7 +7,7 @@ package org.cryptomator.ui.model.upgrade;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.cryptomator.cryptolib.Cryptors;
|
||||
import org.cryptomator.cryptolib.api.Cryptor;
|
||||
import org.cryptomator.cryptolib.common.MessageDigestSupplier;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.ui.model.upgrade;
|
||||
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.cryptomator.cryptolib.Cryptors;
|
||||
import org.cryptomator.cryptolib.api.Cryptor;
|
||||
import org.cryptomator.cryptolib.api.FileHeader;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.ui.model.upgrade;
|
||||
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.cryptomator.cryptofs.migration.Migrators;
|
||||
import org.cryptomator.cryptofs.migration.api.NoApplicableMigratorException;
|
||||
import org.cryptomator.cryptolib.Cryptors;
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import org.cryptomator.ui.fxapp.FxApplication;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationComponent;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@TrayMenuScoped
|
||||
public class FxApplicationStarter {
|
||||
|
||||
private final CompletableFuture<FxApplication> future;
|
||||
private final FxApplicationComponent.Builder fxAppComponent;
|
||||
|
||||
@Inject
|
||||
public FxApplicationStarter(FxApplicationComponent.Builder fxAppComponent) {
|
||||
this.fxAppComponent = fxAppComponent;
|
||||
this.future = new CompletableFuture<>();
|
||||
}
|
||||
|
||||
public synchronized FxApplication get() {
|
||||
if (!future.isDone()) {
|
||||
start();
|
||||
}
|
||||
try {
|
||||
return future.get();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IllegalStateException("Interrupted while waiting for FxApplication startup.", e);
|
||||
} catch (ExecutionException e) {
|
||||
throw new IllegalStateException("FxApplication startup failed.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void start() {
|
||||
Platform.startup(() -> {
|
||||
assert Platform.isFxApplicationThread();
|
||||
FxApplication app = fxAppComponent.build().application();
|
||||
app.start();
|
||||
future.complete(app);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import javafx.beans.Observable;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.awt.AWTException;
|
||||
import java.awt.SystemTray;
|
||||
import java.awt.TrayIcon;
|
||||
|
||||
@TrayMenuScoped
|
||||
public class TrayIconController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TrayIconController.class);
|
||||
|
||||
private final Settings settings;
|
||||
private final TrayImageFactory imageFactory;
|
||||
private final TrayMenuController trayMenuController;
|
||||
private final TrayIcon trayIcon;
|
||||
|
||||
@Inject
|
||||
TrayIconController(Settings settings, TrayImageFactory imageFactory, TrayMenuController trayMenuController) {
|
||||
this.settings = settings;
|
||||
this.trayMenuController = trayMenuController;
|
||||
this.imageFactory = imageFactory;
|
||||
this.trayIcon = new TrayIcon(imageFactory.loadImage(), "Cryptomator", trayMenuController.getMenu());
|
||||
}
|
||||
|
||||
public void initializeTrayIcon() {
|
||||
settings.theme().addListener(this::themeChanged);
|
||||
|
||||
trayMenuController.initTrayMenu();
|
||||
|
||||
try {
|
||||
SystemTray.getSystemTray().add(trayIcon);
|
||||
LOG.info("initialized tray icon");
|
||||
} catch (AWTException e) {
|
||||
LOG.error("Error adding tray icon", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void themeChanged(@SuppressWarnings("unused") Observable observable) {
|
||||
trayIcon.setImage(imageFactory.loadImage());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.awt.Image;
|
||||
import java.awt.Toolkit;
|
||||
|
||||
@TrayMenuScoped
|
||||
class TrayImageFactory {
|
||||
|
||||
private final Settings settings;
|
||||
|
||||
@Inject
|
||||
TrayImageFactory(Settings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public Image loadImage() {
|
||||
String resourceName = SystemUtils.IS_OS_MAC_OSX ? getMacResourceName() : getWinOrLinuxResourceName();
|
||||
return Toolkit.getDefaultToolkit().getImage(getClass().getResource(resourceName));
|
||||
}
|
||||
|
||||
private String getMacResourceName() {
|
||||
switch (settings.theme().get()) {
|
||||
case DARK:
|
||||
return "/tray_icon_mac_white.png";
|
||||
default:
|
||||
return "/tray_icon_mac_black.png";
|
||||
}
|
||||
}
|
||||
|
||||
private String getWinOrLinuxResourceName() {
|
||||
return "/tray_icon.png";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*******************************************************************************
|
||||
* 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.traymenu;
|
||||
|
||||
import dagger.Subcomponent;
|
||||
|
||||
import java.awt.SystemTray;
|
||||
|
||||
@TrayMenuScoped
|
||||
@Subcomponent(modules = {TrayMenuModule.class})
|
||||
public interface TrayMenuComponent {
|
||||
|
||||
TrayIconController trayIconController();
|
||||
|
||||
default void addIconToSystemTray() {
|
||||
if (SystemTray.isSupported()) {
|
||||
trayIconController().initializeTrayIcon();
|
||||
} else {
|
||||
// TODO what?
|
||||
}
|
||||
}
|
||||
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
|
||||
TrayMenuComponent build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.PopupMenu;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
@TrayMenuScoped
|
||||
public class TrayMenuController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TrayMenuController.class);
|
||||
|
||||
private final FxApplicationStarter fxApplicationStarter;
|
||||
private final CountDownLatch shutdownLatch;
|
||||
private final PopupMenu menu;
|
||||
|
||||
@Inject
|
||||
TrayMenuController(FxApplicationStarter fxApplicationStarter, @Named("shutdownLatch") CountDownLatch shutdownLatch) {
|
||||
this.fxApplicationStarter = fxApplicationStarter;
|
||||
this.shutdownLatch = shutdownLatch;
|
||||
this.menu = new PopupMenu();
|
||||
}
|
||||
|
||||
public PopupMenu getMenu() {
|
||||
return menu;
|
||||
}
|
||||
|
||||
public void initTrayMenu() {
|
||||
// TODO add listeners
|
||||
rebuildMenu();
|
||||
}
|
||||
|
||||
private void rebuildMenu() {
|
||||
MenuItem showMainWindowItem = new MenuItem("TODO show");
|
||||
showMainWindowItem.addActionListener(this::showMainWindow);
|
||||
menu.add(showMainWindowItem);
|
||||
|
||||
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 quitApplication(ActionEvent actionEvent) {
|
||||
shutdownLatch.countDown();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import dagger.Module;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationComponent;
|
||||
|
||||
@Module(subcomponents = {FxApplicationComponent.class})
|
||||
abstract class TrayMenuModule {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import javax.inject.Scope;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Scope
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface TrayMenuScoped {
|
||||
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import javafx.scene.layout.Background;
|
||||
import javafx.scene.layout.BackgroundFill;
|
||||
import javafx.scene.layout.CornerRadii;
|
||||
import javafx.scene.paint.Color;
|
||||
import org.cryptomator.ui.FxApplicationScoped;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.cryptomator.ui.l10n.Localization;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
27
main/ui/src/test/java/org/cryptomator/ui/controls/Foo.java
Normal file
27
main/ui/src/test/java/org/cryptomator/ui/controls/Foo.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package org.cryptomator.ui.controls;
|
||||
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class Foo {
|
||||
|
||||
@Test
|
||||
public void foo() {
|
||||
StringProperty str = new SimpleStringProperty("foo");
|
||||
CountDownLatch done = new CountDownLatch(1);
|
||||
str.addListener(observable -> {
|
||||
Assertions.assertEquals("bar", str.get());
|
||||
done.countDown();
|
||||
});
|
||||
str.set("bar");
|
||||
Assertions.assertTimeoutPreemptively(Duration.ofMillis(100), () -> {
|
||||
done.await();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user