diff --git a/src/main/java/io/bitsquare/BitsquareModule.java b/src/main/java/io/bitsquare/BitsquareModule.java index 1e244cc936..1b57041f53 100644 --- a/src/main/java/io/bitsquare/BitsquareModule.java +++ b/src/main/java/io/bitsquare/BitsquareModule.java @@ -26,6 +26,8 @@ import java.util.Set; import org.springframework.core.env.Environment; +import static com.google.common.base.Preconditions.checkNotNull; + public abstract class BitsquareModule extends AbstractModule { protected final Environment env; @@ -33,6 +35,7 @@ public abstract class BitsquareModule extends AbstractModule { private final Set modules = Sets.newHashSet(); protected BitsquareModule(Environment env) { + checkNotNull(env, "Environment must not be null"); this.env = env; } diff --git a/src/main/java/io/bitsquare/app/gui/BitsquareApp.java b/src/main/java/io/bitsquare/app/gui/BitsquareApp.java index 0d7a1e0764..041ebb75bf 100644 --- a/src/main/java/io/bitsquare/app/gui/BitsquareApp.java +++ b/src/main/java/io/bitsquare/app/gui/BitsquareApp.java @@ -19,6 +19,7 @@ package io.bitsquare.app.gui; import io.bitsquare.BitsquareException; import io.bitsquare.account.AccountSettings; +import io.bitsquare.gui.GuiceControllerFactory; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.SystemTray; import io.bitsquare.gui.ViewLoader; @@ -47,7 +48,6 @@ import javafx.stage.Stage; import org.springframework.core.env.Environment; -import static com.google.common.base.Preconditions.checkNotNull; import static io.bitsquare.app.BitsquareEnvironment.*; public class BitsquareApp extends Application { @@ -62,9 +62,9 @@ public class BitsquareApp extends Application { @Override public void start(Stage primaryStage) throws IOException { - checkNotNull(env, "Environment must not be null"); bitsquareAppModule = new BitsquareAppModule(env, primaryStage); injector = Guice.createInjector(bitsquareAppModule); + injector.getInstance(GuiceControllerFactory.class).setInjector(injector); // route uncaught exceptions to a user-facing dialog @@ -93,11 +93,10 @@ public class BitsquareApp extends Application { // load the main view and create the main scene - ViewLoader.setInjector(injector); - ViewLoader loader = new ViewLoader(Navigation.Item.MAIN, false); - Parent view = loader.load(); + ViewLoader viewLoader = injector.getInstance(ViewLoader.class); + ViewLoader.Item loaded = viewLoader.load(Navigation.Item.MAIN.getFxmlUrl(), false); - Scene scene = new Scene(view, 1000, 600); + Scene scene = new Scene((Parent) loaded.view, 1000, 600); scene.getStylesheets().setAll( "/io/bitsquare/gui/bitsquare.css", "/io/bitsquare/gui/images.css"); diff --git a/src/main/java/io/bitsquare/gui/GuiModule.java b/src/main/java/io/bitsquare/gui/GuiModule.java index 8a4c3aaf97..58ac357bbb 100644 --- a/src/main/java/io/bitsquare/gui/GuiModule.java +++ b/src/main/java/io/bitsquare/gui/GuiModule.java @@ -45,6 +45,9 @@ public class GuiModule extends BitsquareModule { @Override protected void configure() { + bind(GuiceControllerFactory.class).asEagerSingleton(); + bind(ViewLoader.class).asEagerSingleton(); + bind(OfferBook.class).asEagerSingleton(); bind(Navigation.class).asEagerSingleton(); bind(OverlayManager.class).asEagerSingleton(); diff --git a/src/main/java/io/bitsquare/gui/GuiceControllerFactory.java b/src/main/java/io/bitsquare/gui/GuiceControllerFactory.java new file mode 100644 index 0000000000..602a8cc64b --- /dev/null +++ b/src/main/java/io/bitsquare/gui/GuiceControllerFactory.java @@ -0,0 +1,47 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bitsquare is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bitsquare. If not, see . + */ + +package io.bitsquare.gui; + +import com.google.common.base.Preconditions; + +import com.google.inject.Injector; + +import javafx.util.Callback; + +/** + * A JavaFX controller factory for constructing controllers via Guice DI. To + * install this in the {@link javafx.fxml.FXMLLoader}, pass it as a parameter to + * {@link javafx.fxml.FXMLLoader#setControllerFactory(javafx.util.Callback)}. + *

+ * Once set, make sure you do not use the static methods on + * {@link javafx.fxml.FXMLLoader} when creating your JavaFX node. + */ +public class GuiceControllerFactory implements Callback, Object> { + + private Injector injector; + + public void setInjector(Injector injector) { + this.injector = injector; + } + + @Override + public Object call(Class aClass) { + Preconditions.checkNotNull(injector, "Injector has not yet been provided"); + return injector.getInstance(aClass); + } +} diff --git a/src/main/java/io/bitsquare/gui/Navigation.java b/src/main/java/io/bitsquare/gui/Navigation.java index a9501fa260..41a9f3adb0 100644 --- a/src/main/java/io/bitsquare/gui/Navigation.java +++ b/src/main/java/io/bitsquare/gui/Navigation.java @@ -17,10 +17,13 @@ package io.bitsquare.gui; +import io.bitsquare.BitsquareException; import io.bitsquare.persistence.Persistence; import com.google.inject.Inject; +import java.net.URL; + import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -137,16 +140,12 @@ public class Navigation { void onNavigationRequested(Item... items); } - public interface FxmlResource { - String getFxmlUrl(); - } - /////////////////////////////////////////////////////////////////////////////////////////// // Enum /////////////////////////////////////////////////////////////////////////////////////////// - public static enum Item implements FxmlResource { + public static enum Item { /////////////////////////////////////////////////////////////////////////////////////////// // Application @@ -219,7 +218,10 @@ public class Navigation { ARBITRATOR_PROFILE("/io/bitsquare/gui/main/account/arbitrator/profile/ArbitratorProfileView.fxml"), ARBITRATOR_BROWSER("/io/bitsquare/gui/main/account/arbitrator/browser/ArbitratorBrowserView.fxml"), ARBITRATOR_REGISTRATION( - "/io/bitsquare/gui/main/account/arbitrator/registration/ArbitratorRegistrationView.fxml"); + "/io/bitsquare/gui/main/account/arbitrator/registration/ArbitratorRegistrationView.fxml"), + + // for testing, does not actually exist + BOGUS("/io/bitsquare/BogusView.fxml"); private final String displayName; @@ -234,9 +236,11 @@ public class Navigation { this.fxmlUrl = fxmlUrl; } - @Override - public String getFxmlUrl() { - return fxmlUrl; + public URL getFxmlUrl() { + URL url = Navigation.class.getResource(fxmlUrl); + if (url == null) + throw new BitsquareException("'%s' could not be loaded as a resource", fxmlUrl); + return url; } public String getDisplayName() { diff --git a/src/main/java/io/bitsquare/gui/ViewCB.java b/src/main/java/io/bitsquare/gui/ViewCB.java index fe72339927..ce39237b44 100644 --- a/src/main/java/io/bitsquare/gui/ViewCB.java +++ b/src/main/java/io/bitsquare/gui/ViewCB.java @@ -39,7 +39,7 @@ public class ViewCB implements Initializable { public static final String TITLE_KEY = "view.title"; protected T presentationModel; - protected ViewCB childController; + protected Initializable childController; protected ViewCB parent; @FXML protected Parent root; diff --git a/src/main/java/io/bitsquare/gui/ViewLoader.java b/src/main/java/io/bitsquare/gui/ViewLoader.java index fc3d7b3b9c..6fd940b975 100644 --- a/src/main/java/io/bitsquare/gui/ViewLoader.java +++ b/src/main/java/io/bitsquare/gui/ViewLoader.java @@ -20,8 +20,6 @@ package io.bitsquare.gui; import io.bitsquare.BitsquareException; import io.bitsquare.locale.BSResources; -import com.google.inject.Injector; - import java.io.IOException; import java.net.URL; @@ -29,105 +27,58 @@ import java.net.URL; import java.util.HashMap; import java.util.Map; -import javafx.fxml.FXMLLoader; -import javafx.util.Callback; +import javax.inject.Inject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.fxml.JavaFXBuilderFactory; +import javafx.scene.*; +import javafx.util.BuilderFactory; /** * Guice support for fxml controllers * Support caching to speed up switches between UI screens. */ public class ViewLoader { - private static final Logger log = LoggerFactory.getLogger(ViewLoader.class); - private static Injector injector = null; - private FXMLLoader loader; - private final boolean isCached; - private final URL url; - private Item item; - public static void setInjector(Injector injector) { - ViewLoader.injector = injector; + private final Map cache = new HashMap<>(); + private final BuilderFactory builderFactory = new JavaFXBuilderFactory(); + private final GuiceControllerFactory controllerFactory; + + @Inject + public ViewLoader(GuiceControllerFactory controllerFactory) { + this.controllerFactory = controllerFactory; } - // TODO maybe add more sophisticated caching strategy with removal of rarely accessed items - private static final Map cachedGUIItems = new HashMap<>(); - - public ViewLoader(Navigation.FxmlResource navItem, boolean useCaching) { - this.url = ViewLoader.class.getResource(navItem.getFxmlUrl()); - if (this.url == null) { - throw new BitsquareException("'%s' could not be loaded as a resource", navItem.getFxmlUrl()); - } - - isCached = useCaching && cachedGUIItems.containsKey(url); - if (!isCached) { - loader = new FXMLLoader(url, BSResources.getResourceBundle()); - - if (ViewLoader.injector != null) - loader.setControllerFactory(new GuiceControllerFactory(ViewLoader.injector)); - } + public Item load(URL url) { + return load(url, true); } - public ViewLoader(Navigation.FxmlResource navItem) { - this(navItem, true); - } + public Item load(URL url, boolean useCaching) { + Item item; - @SuppressWarnings("unchecked") - public T load() { - if (isCached) { - item = cachedGUIItems.get(url); - log.debug("loaded from cache " + url); - return (T) cachedGUIItems.get(url).view; + if (useCaching && cache.containsKey(url)) { + return cache.get(url); } - log.debug("load from disc " + url); + FXMLLoader loader = new FXMLLoader(url, BSResources.getResourceBundle(), builderFactory, controllerFactory); try { - T result = loader.load(); - item = new Item(result, loader.getController()); - cachedGUIItems.put(url, item); - return result; + item = new Item(loader.load(), loader.getController()); + cache.put(url, item); + return item; } catch (IOException e) { throw new BitsquareException(e, "Failed to load view at %s", url); } } - @SuppressWarnings("unchecked") - public T getController() { - return (T) item.controller; - } + public static class Item { + public final Node view; + public final Initializable controller; - - class Item { - final T view; - final T controller; - - Item(T view, T controller) { + Item(Node view, Initializable controller) { this.view = view; this.controller = controller; } } } -/** - * A JavaFX controller factory for constructing controllers via Guice DI. To - * install this in the {@link javafx.fxml.FXMLLoader}, pass it as a parameter to - * {@link javafx.fxml.FXMLLoader#setControllerFactory(javafx.util.Callback)}. - *

- * Once set, make sure you do not use the static methods on - * {@link javafx.fxml.FXMLLoader} when creating your JavaFX node. - */ -class GuiceControllerFactory implements Callback, Object> { - - private final Injector injector; - - public GuiceControllerFactory(Injector injector) { - this.injector = injector; - } - - @Override - public Object call(Class aClass) { - return injector.getInstance(aClass); - } -} - diff --git a/src/main/java/io/bitsquare/gui/main/MainViewCB.java b/src/main/java/io/bitsquare/gui/main/MainViewCB.java index 7e37ded02e..67fd3c00f9 100644 --- a/src/main/java/io/bitsquare/gui/main/MainViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/MainViewCB.java @@ -62,6 +62,7 @@ public class MainViewCB extends ViewCB { setBottomAnchor(this, 25d); }}; + private final ViewLoader viewLoader; private final Navigation navigation; private final OverlayManager overlayManager; private final Transitions transitions; @@ -69,11 +70,11 @@ public class MainViewCB extends ViewCB { private final String title; @Inject - public MainViewCB(MainPM presentationModel, Navigation navigation, OverlayManager overlayManager, - TradeManager tradeManager, Transitions transitions, BitcoinNetwork bitcoinNetwork, - @Named(TITLE_KEY) String title) { + public MainViewCB(MainPM presentationModel, ViewLoader viewLoader, Navigation navigation, + OverlayManager overlayManager, TradeManager tradeManager, Transitions transitions, + BitcoinNetwork bitcoinNetwork, @Named(TITLE_KEY) String title) { super(presentationModel); - + this.viewLoader = viewLoader; this.navigation = navigation; this.overlayManager = overlayManager; this.transitions = transitions; @@ -152,11 +153,12 @@ public class MainViewCB extends ViewCB { } private void loadSelectedNavigation(Navigation.Item selected) { - ViewLoader loader = new ViewLoader(selected); - contentContainer.getChildren().setAll(loader.load()); - childController = loader.getController(); - if (childController != null) - childController.setParent(this); + + ViewLoader.Item loaded = viewLoader.load(selected.getFxmlUrl()); + contentContainer.getChildren().setAll(loaded.view); + childController = loaded.controller; + if (childController instanceof ViewCB) + ((ViewCB) childController).setParent(this); navButtons.getToggles().stream() .filter(toggle -> toggle instanceof ToggleButton) diff --git a/src/main/java/io/bitsquare/gui/main/account/AccountViewCB.java b/src/main/java/io/bitsquare/gui/main/account/AccountViewCB.java index 9f05d3d08d..e04b61c42d 100644 --- a/src/main/java/io/bitsquare/gui/main/account/AccountViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/account/AccountViewCB.java @@ -31,7 +31,6 @@ import javax.inject.Inject; import javafx.beans.value.ChangeListener; import javafx.fxml.FXML; import javafx.fxml.Initializable; -import javafx.scene.*; import javafx.scene.control.*; import org.slf4j.Logger; @@ -41,22 +40,23 @@ public class AccountViewCB extends CachedViewCB { private static final Logger log = LoggerFactory.getLogger(AccountViewCB.class); - private final Navigation navigation; private Navigation.Listener navigationListener; - private ChangeListener tabChangeListener; @FXML Tab accountSettingsTab, arbitratorSettingsTab; + private final ViewLoader viewLoader; + private final Navigation navigation; + /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// @Inject - private AccountViewCB(AccountPM presentationModel, Navigation navigation) { + private AccountViewCB(AccountPM presentationModel, ViewLoader viewLoader, Navigation navigation) { super(presentationModel); - + this.viewLoader = viewLoader; this.navigation = navigation; } @@ -134,9 +134,8 @@ public class AccountViewCB extends CachedViewCB { protected Initializable loadView(Navigation.Item navigationItem) { super.loadView(navigationItem); - final ViewLoader loader = new ViewLoader(navigationItem); - Node view = loader.load(); - Tab tab = null; + ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl()); + final Tab tab; switch (navigationItem) { case ACCOUNT_SETTINGS: tab = accountSettingsTab; @@ -151,14 +150,16 @@ public class AccountViewCB extends CachedViewCB { case ARBITRATOR_SETTINGS: tab = arbitratorSettingsTab; break; + default: + throw new IllegalArgumentException("navigation item of type " + navigationItem + " is not allowed"); } // for IRC demo we deactivate the arbitratorSettingsTab arbitratorSettingsTab.setDisable(true); - tab.setContent(view); + tab.setContent(loaded.view); ((TabPane) root).getSelectionModel().select(tab); - Initializable childController = loader.getController(); + Initializable childController = loaded.controller; ((ViewCB) childController).setParent(this); return childController; diff --git a/src/main/java/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsViewCB.java b/src/main/java/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsViewCB.java index d93b9588aa..33c80f9513 100644 --- a/src/main/java/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsViewCB.java @@ -34,14 +34,10 @@ import javafx.scene.*; import javafx.stage.Modality; import javafx.stage.Stage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - // TODO Arbitration is very basic yet public class ArbitratorSettingsViewCB extends CachedViewCB { - private static final Logger log = LoggerFactory.getLogger(ArbitratorSettingsViewCB.class); - + private final ViewLoader viewLoader; private final Navigation navigation; private final Stage primaryStage; @@ -53,8 +49,9 @@ public class ArbitratorSettingsViewCB extends CachedViewCB { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - private ArbitratorSettingsViewCB(Navigation navigation, Stage primaryStage) { + private ArbitratorSettingsViewCB(ViewLoader viewLoader, Navigation navigation, Stage primaryStage) { super(); + this.viewLoader = viewLoader; this.navigation = navigation; this.primaryStage = primaryStage; } @@ -95,11 +92,8 @@ public class ArbitratorSettingsViewCB extends CachedViewCB { @Override protected Initializable loadView(Navigation.Item navigationItem) { - // don't use caching here, cause exc. -> need to investigate and is rarely called so no caching is better - final ViewLoader loader = new ViewLoader(navigationItem, false); - - final Parent view = loader.load(); - arbitratorRegistrationViewCB = loader.getController(); + ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl(), false); + arbitratorRegistrationViewCB = (ArbitratorRegistrationViewCB) loaded.controller; final Stage stage = new Stage(); stage.setTitle("Arbitrator"); @@ -111,7 +105,7 @@ public class ArbitratorSettingsViewCB extends CachedViewCB { stage.setY(primaryStage.getY() + 50); stage.initModality(Modality.WINDOW_MODAL); stage.initOwner(primaryStage); - Scene scene = new Scene(view, 800, 600); + Scene scene = new Scene((Parent) loaded.view, 800, 600); stage.setScene(scene); stage.show(); diff --git a/src/main/java/io/bitsquare/gui/main/account/arbitrator/browser/ArbitratorBrowserViewCB.java b/src/main/java/io/bitsquare/gui/main/account/arbitrator/browser/ArbitratorBrowserViewCB.java index 39999f49fa..c05538a6d2 100644 --- a/src/main/java/io/bitsquare/gui/main/account/arbitrator/browser/ArbitratorBrowserViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/account/arbitrator/browser/ArbitratorBrowserViewCB.java @@ -44,18 +44,16 @@ import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.stage.Stage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - // TODO Arbitration is very basic yet public class ArbitratorBrowserViewCB extends CachedViewCB implements ArbitratorListener { - private static final Logger log = LoggerFactory.getLogger(ArbitratorBrowserViewCB.class); + private final ViewLoader viewLoader; private final AccountSettings accountSettings; private final Persistence persistence; private final MessageService messageService; private final List allArbitrators = new ArrayList<>(); + private Arbitrator currentArbitrator; private ArbitratorProfileViewCB arbitratorProfileViewCB; private int index = -1; @@ -63,13 +61,15 @@ public class ArbitratorBrowserViewCB extends CachedViewCB implements ArbitratorL @FXML Button prevButton, nextButton, selectButton, closeButton; @FXML Pane arbitratorProfile; + /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public ArbitratorBrowserViewCB(AccountSettings accountSettings, Persistence persistence, + public ArbitratorBrowserViewCB(ViewLoader viewLoader, AccountSettings accountSettings, Persistence persistence, MessageService messageService) { + this.viewLoader = viewLoader; this.accountSettings = accountSettings; this.persistence = persistence; this.messageService = messageService; @@ -139,10 +139,9 @@ public class ArbitratorBrowserViewCB extends CachedViewCB implements ArbitratorL protected Initializable loadView(Navigation.Item navigationItem) { super.loadView(navigationItem); - final ViewLoader loader = new ViewLoader(navigationItem); - Node view = loader.load(); - ((Pane) root).getChildren().set(0, view); - Initializable childController = arbitratorProfileViewCB = loader.getController(); + ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl()); + ((Pane) root).getChildren().set(0, loaded.view); + Initializable childController = arbitratorProfileViewCB = (ArbitratorProfileViewCB) loaded.controller; ((ViewCB) childController).setParent(this); return childController; diff --git a/src/main/java/io/bitsquare/gui/main/account/content/restrictions/RestrictionsViewCB.java b/src/main/java/io/bitsquare/gui/main/account/content/restrictions/RestrictionsViewCB.java index 749e921585..7df548f030 100644 --- a/src/main/java/io/bitsquare/gui/main/account/content/restrictions/RestrictionsViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/account/content/restrictions/RestrictionsViewCB.java @@ -53,7 +53,6 @@ import org.slf4j.LoggerFactory; public class RestrictionsViewCB extends CachedViewCB implements ContextAware { private static final Logger log = LoggerFactory.getLogger(RestrictionsViewCB.class); - private final Stage primaryStage; @FXML ListView languagesListView; @FXML ListView countriesListView; @@ -63,14 +62,18 @@ public class RestrictionsViewCB extends CachedViewCB implements @FXML ComboBox countryComboBox; @FXML Button completedButton, addAllEuroCountriesButton; + private final ViewLoader viewLoader; + private final Stage primaryStage; + /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// @Inject - private RestrictionsViewCB(RestrictionsPM presentationModel, Stage primaryStage) { + private RestrictionsViewCB(RestrictionsPM presentationModel, ViewLoader viewLoader, Stage primaryStage) { super(presentationModel); + this.viewLoader = viewLoader; this.primaryStage = primaryStage; } @@ -187,12 +190,7 @@ public class RestrictionsViewCB extends CachedViewCB implements @Override protected Initializable loadView(Navigation.Item navigationItem) { - // TODO caching causes exception - final ViewLoader loader = new ViewLoader(navigationItem, false); - final Node view = loader.load(); - //TODO Resolve type problem... - Initializable childController = loader.getController(); - //childController.setParentController(this); + ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl(), false); final Stage stage = new Stage(); stage.setTitle("Arbitrator selection"); @@ -204,7 +202,7 @@ public class RestrictionsViewCB extends CachedViewCB implements stage.setY(primaryStage.getY() + 50); stage.initModality(Modality.WINDOW_MODAL); stage.initOwner(primaryStage); - Scene scene = new Scene((Parent) view, 800, 600); + Scene scene = new Scene((Parent) loaded.view, 800, 600); stage.setScene(scene); stage.setOnHidden(windowEvent -> { if (navigationItem == Navigation.Item.ARBITRATOR_BROWSER) @@ -212,7 +210,7 @@ public class RestrictionsViewCB extends CachedViewCB implements }); stage.show(); - return childController; + return loaded.controller; } diff --git a/src/main/java/io/bitsquare/gui/main/account/settings/AccountSettingsViewCB.java b/src/main/java/io/bitsquare/gui/main/account/settings/AccountSettingsViewCB.java index 71e3c4db39..9272a8a44d 100644 --- a/src/main/java/io/bitsquare/gui/main/account/settings/AccountSettingsViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/account/settings/AccountSettingsViewCB.java @@ -48,8 +48,10 @@ public class AccountSettingsViewCB extends CachedViewCB { private static final Logger log = LoggerFactory.getLogger(AccountSettingsViewCB.class); - private MenuItem seedWords, password, restrictions, fiatAccount, registration; + private final ViewLoader viewLoader; private final Navigation navigation; + + private MenuItem seedWords, password, restrictions, fiatAccount, registration; private Navigation.Listener listener; @FXML private VBox leftVBox; @@ -61,9 +63,9 @@ public class AccountSettingsViewCB extends CachedViewCB { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - private AccountSettingsViewCB(Navigation navigation) { + private AccountSettingsViewCB(ViewLoader viewLoader, Navigation navigation) { super(); - + this.viewLoader = viewLoader; this.navigation = navigation; } @@ -146,10 +148,9 @@ public class AccountSettingsViewCB extends CachedViewCB { @Override protected Initializable loadView(Navigation.Item navigationItem) { - final ViewLoader loader = new ViewLoader(navigationItem); - final Pane view = loader.load(); - content.getChildren().setAll(view); - childController = loader.getController(); + ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl()); + content.getChildren().setAll(loaded.view); + childController = loaded.controller; ((ViewCB) childController).setParent(this); ((ContextAware) childController).useSettingsContext(true); return childController; diff --git a/src/main/java/io/bitsquare/gui/main/account/setup/AccountSetupViewCB.java b/src/main/java/io/bitsquare/gui/main/account/setup/AccountSetupViewCB.java index 246f109fe4..5c49980bd0 100644 --- a/src/main/java/io/bitsquare/gui/main/account/setup/AccountSetupViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/account/setup/AccountSetupViewCB.java @@ -53,20 +53,23 @@ public class AccountSetupViewCB extends ViewCB implements MultiStepNavigation { private static final Logger log = LoggerFactory.getLogger(AccountSetupViewCB.class); private WizardItem seedWords, password, fiatAccount, restrictions, registration; - private final Navigation navigation; private Navigation.Listener listener; @FXML VBox leftVBox; @FXML AnchorPane content; + private final ViewLoader viewLoader; + private final Navigation navigation; + /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// @Inject - private AccountSetupViewCB(Navigation navigation) { + private AccountSetupViewCB(ViewLoader viewLoader, Navigation navigation) { super(); + this.viewLoader = viewLoader; this.navigation = navigation; } @@ -186,10 +189,9 @@ public class AccountSetupViewCB extends ViewCB implements MultiStepNavigation { @Override protected Initializable loadView(Navigation.Item navigationItem) { - final ViewLoader loader = new ViewLoader(navigationItem); - final Pane view = loader.load(); - content.getChildren().setAll(view); - childController = loader.getController(); + ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl()); + content.getChildren().setAll(loaded.view); + childController = loaded.controller; ((ViewCB) childController).setParent(this); ((ContextAware) childController).useSettingsContext(false); return childController; diff --git a/src/main/java/io/bitsquare/gui/main/funds/FundsViewCB.java b/src/main/java/io/bitsquare/gui/main/funds/FundsViewCB.java index a7a736ccf1..ee24e60796 100644 --- a/src/main/java/io/bitsquare/gui/main/funds/FundsViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/funds/FundsViewCB.java @@ -34,13 +34,7 @@ import javafx.fxml.Initializable; import javafx.scene.*; import javafx.scene.control.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class FundsViewCB extends CachedViewCB { - private static final Logger log = LoggerFactory.getLogger(FundsViewCB.class); - - private final Navigation navigation; private Navigation.Listener navigationListener; private ChangeListener tabChangeListener; @@ -48,15 +42,18 @@ public class FundsViewCB extends CachedViewCB { @FXML Tab withdrawalTab, transactionsTab; + private final ViewLoader viewLoader; + private final Navigation navigation; + /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// @Inject - FundsViewCB(Navigation navigation) { + FundsViewCB(ViewLoader viewLoader, Navigation navigation) { super(); - + this.viewLoader = viewLoader; this.navigation = navigation; } @@ -117,8 +114,7 @@ public class FundsViewCB extends CachedViewCB { if (currentTab != null) currentTab.setContent(null); - final ViewLoader loader = new ViewLoader(navigationItem); - Node view = loader.load(); + ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl()); switch (navigationItem) { case WITHDRAWAL: currentTab = withdrawalTab; @@ -127,9 +123,9 @@ public class FundsViewCB extends CachedViewCB { currentTab = transactionsTab; break; } - currentTab.setContent(view); + currentTab.setContent(loaded.view); ((TabPane) root).getSelectionModel().select(currentTab); - Initializable childController = loader.getController(); + Initializable childController = loaded.controller; ((ViewCB) childController).setParent(this); return childController; diff --git a/src/main/java/io/bitsquare/gui/main/portfolio/PortfolioViewCB.java b/src/main/java/io/bitsquare/gui/main/portfolio/PortfolioViewCB.java index 306bafd651..db794e51ba 100644 --- a/src/main/java/io/bitsquare/gui/main/portfolio/PortfolioViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/portfolio/PortfolioViewCB.java @@ -35,14 +35,7 @@ import javafx.fxml.Initializable; import javafx.scene.*; import javafx.scene.control.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class PortfolioViewCB extends CachedViewCB { - private static final Logger log = LoggerFactory.getLogger(PortfolioViewCB.class); - - private final Navigation navigation; - private final TradeManager tradeManager; private Tab currentTab; private Navigation.Listener navigationListener; @@ -50,15 +43,19 @@ public class PortfolioViewCB extends CachedViewCB { @FXML Tab offersTab, openTradesTab, closedTradesTab; + private final ViewLoader viewLoader; + private final Navigation navigation; + private final TradeManager tradeManager; + /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// @Inject - PortfolioViewCB(Navigation navigation, TradeManager tradeManager) { + PortfolioViewCB(ViewLoader viewLoader, Navigation navigation, TradeManager tradeManager) { super(); - + this.viewLoader = viewLoader; this.navigation = navigation; this.tradeManager = tradeManager; } @@ -130,8 +127,7 @@ public class PortfolioViewCB extends CachedViewCB { if (currentTab != null) currentTab.setContent(null); - final ViewLoader loader = new ViewLoader(navigationItem); - Node view = loader.load(); + ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl()); switch (navigationItem) { case OFFERS: currentTab = offersTab; @@ -143,9 +139,9 @@ public class PortfolioViewCB extends CachedViewCB { currentTab = closedTradesTab; break; } - currentTab.setContent(view); + currentTab.setContent(loaded.view); ((TabPane) root).getSelectionModel().select(currentTab); - Initializable childController = loader.getController(); + Initializable childController = loaded.controller; ((ViewCB) childController).setParent(this); return childController; diff --git a/src/main/java/io/bitsquare/gui/main/settings/SettingsViewCB.java b/src/main/java/io/bitsquare/gui/main/settings/SettingsViewCB.java index d7cf2179f4..3f44b9386d 100644 --- a/src/main/java/io/bitsquare/gui/main/settings/SettingsViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/settings/SettingsViewCB.java @@ -35,12 +35,9 @@ import javafx.fxml.Initializable; import javafx.scene.*; import javafx.scene.control.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class SettingsViewCB extends CachedViewCB { - private static final Logger log = LoggerFactory.getLogger(SettingsViewCB.class); + private final ViewLoader viewLoader; private final Navigation navigation; private Preferences preferences; @@ -55,9 +52,9 @@ public class SettingsViewCB extends CachedViewCB { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - SettingsViewCB(Navigation navigation, Preferences preferences) { + SettingsViewCB(ViewLoader viewLoader, Navigation navigation, Preferences preferences) { super(); - + this.viewLoader = viewLoader; this.navigation = navigation; this.preferences = preferences; } @@ -121,9 +118,8 @@ public class SettingsViewCB extends CachedViewCB { protected Initializable loadView(Navigation.Item navigationItem) { super.loadView(navigationItem); - final ViewLoader loader = new ViewLoader(navigationItem); - Parent view = loader.load(); - Tab tab = null; + ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl()); + final Tab tab; switch (navigationItem) { case PREFERENCES: tab = preferencesTab; @@ -131,10 +127,12 @@ public class SettingsViewCB extends CachedViewCB { case NETWORK_SETTINGS: tab = networkSettingsTab; break; + default: + throw new IllegalArgumentException("navigation item of type " + navigationItem + " is not allowed"); } - tab.setContent(view); + tab.setContent(loaded.view); ((TabPane) root).getSelectionModel().select(tab); - Initializable childController = loader.getController(); + Initializable childController = loaded.controller; if (childController instanceof ViewCB) ((ViewCB) childController).setParent(this); diff --git a/src/main/java/io/bitsquare/gui/main/trade/BuyViewCB.java b/src/main/java/io/bitsquare/gui/main/trade/BuyViewCB.java index 00c0cf5388..929c36702a 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/BuyViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/trade/BuyViewCB.java @@ -18,14 +18,15 @@ package io.bitsquare.gui.main.trade; import io.bitsquare.gui.Navigation; +import io.bitsquare.gui.ViewLoader; import javax.inject.Inject; public class BuyViewCB extends TradeViewCB { @Inject - public BuyViewCB(Navigation navigation) { - super(navigation); + public BuyViewCB(ViewLoader viewLoader, Navigation navigation) { + super(viewLoader, navigation); } } diff --git a/src/main/java/io/bitsquare/gui/main/trade/SellViewCB.java b/src/main/java/io/bitsquare/gui/main/trade/SellViewCB.java index 84992f4128..36be3dbf36 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/SellViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/trade/SellViewCB.java @@ -18,14 +18,15 @@ package io.bitsquare.gui.main.trade; import io.bitsquare.gui.Navigation; +import io.bitsquare.gui.ViewLoader; import javax.inject.Inject; public class SellViewCB extends TradeViewCB { @Inject - public SellViewCB(Navigation navigation) { - super(navigation); + public SellViewCB(ViewLoader viewLoader, Navigation navigation) { + super(viewLoader, navigation); } } diff --git a/src/main/java/io/bitsquare/gui/main/trade/TradeViewCB.java b/src/main/java/io/bitsquare/gui/main/trade/TradeViewCB.java index 84ceb03e55..2daba92d4f 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/TradeViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/trade/TradeViewCB.java @@ -47,13 +47,11 @@ import org.slf4j.LoggerFactory; public class TradeViewCB extends CachedViewCB implements TradeNavigator { private static final Logger log = LoggerFactory.getLogger(TradeViewCB.class); - // private final OfferBookInfo offerBookInfo = new OfferBookInfo(); private OfferBookViewCB offerBookViewCB; private CreateOfferViewCB createOfferViewCB; private TakeOfferViewCB takeOfferViewCB; private Node createOfferView; private Node takeOfferView; - private final Navigation navigation; private Navigation.Listener listener; private Navigation.Item navigationItem; private Direction direction; @@ -61,14 +59,17 @@ public class TradeViewCB extends CachedViewCB implements TradeNavigator { private Fiat price; private Offer offer; + private final ViewLoader viewLoader; + private final Navigation navigation; + /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// - protected TradeViewCB(Navigation navigation) { + protected TradeViewCB(ViewLoader viewLoader, Navigation navigation) { super(); - + this.viewLoader = viewLoader; this.navigation = navigation; } @@ -166,13 +167,12 @@ public class TradeViewCB extends CachedViewCB implements TradeNavigator { TabPane tabPane = (TabPane) root; if (navigationItem == Navigation.Item.OFFER_BOOK && offerBookViewCB == null) { // Offerbook must not be cached by ViewLoader as we use 2 instances for sell and buy screens. - ViewLoader offerBookLoader = new ViewLoader(navigationItem, false); - final Parent view = offerBookLoader.load(); + ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl(), false); final Tab tab = new Tab(direction == Direction.BUY ? "Buy Bitcoin" : "Sell Bitcoin"); tab.setClosable(false); - tab.setContent(view); + tab.setContent(loaded.view); tabPane.getTabs().add(tab); - offerBookViewCB = offerBookLoader.getController(); + offerBookViewCB = (OfferBookViewCB) loaded.controller; offerBookViewCB.setParent(this); offerBookViewCB.setDirection(direction); @@ -183,9 +183,9 @@ public class TradeViewCB extends CachedViewCB implements TradeNavigator { else if (navigationItem == Navigation.Item.CREATE_OFFER && createOfferViewCB == null) { // CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times // in different graphs - final ViewLoader loader = new ViewLoader(navigationItem, false); - createOfferView = loader.load(); - createOfferViewCB = loader.getController(); + ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl(), false); + createOfferView = loaded.view; + createOfferViewCB = (CreateOfferViewCB) loaded.controller; createOfferViewCB.setParent(this); createOfferViewCB.initWithData(direction, amount, price); final Tab tab = new Tab("Create offer"); @@ -199,9 +199,9 @@ public class TradeViewCB extends CachedViewCB implements TradeNavigator { offer != null) { // CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times // in different graphs - ViewLoader loader = new ViewLoader(Navigation.Item.TAKE_OFFER, false); - takeOfferView = loader.load(); - takeOfferViewCB = loader.getController(); + ViewLoader.Item loaded = viewLoader.load(Navigation.Item.TAKE_OFFER.getFxmlUrl(), false); + takeOfferView = loaded.view; + takeOfferViewCB = (TakeOfferViewCB) loaded.controller; takeOfferViewCB.setParent(this); takeOfferViewCB.initWithData(direction, amount, offer); final Tab tab = new Tab("Take offer"); diff --git a/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java b/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java index 7f2f3a0453..442509a355 100644 --- a/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java +++ b/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java @@ -19,16 +19,19 @@ package io.bitsquare.app.gui; import io.bitsquare.BitsquareException; import io.bitsquare.app.BitsquareEnvironment; +import io.bitsquare.gui.GuiceControllerFactory; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.ViewLoader; import com.google.inject.Guice; import com.google.inject.Injector; +import java.net.MalformedURLException; +import java.net.URL; + import javafx.application.Application; import javafx.stage.Stage; -import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -59,27 +62,24 @@ public class ViewLoaderTests { Thread.sleep(10); } + private GuiceControllerFactory controllerFactory; @Before public void setUp() { OptionParser parser = new OptionParser(); BitsquareEnvironment env = new BitsquareEnvironment(parser.parse(new String[]{})); Injector injector = Guice.createInjector(new BitsquareAppModule(env, TestApp.primaryStage)); - ViewLoader.setInjector(injector); - } - - @After - public void tearDown() { - ViewLoader.setInjector(null); + controllerFactory = injector.getInstance(GuiceControllerFactory.class); + controllerFactory.setInjector(injector); } @Test(expected = BitsquareException.class) - public void loadingBogusFxmlResourceShouldThrow() { - new ViewLoader(() -> "a bogus fxml resource", false).load(); + public void loadingBogusFxmlResourceShouldThrow() throws MalformedURLException { + new ViewLoader(controllerFactory).load(Navigation.Item.BOGUS.getFxmlUrl(), false); } @Test public void loadingValidFxmlResourceShouldNotThrow() { - new ViewLoader(Navigation.Item.ACCOUNT, false).load(); + new ViewLoader(controllerFactory).load(Navigation.Item.ACCOUNT.getFxmlUrl(), false); } } \ No newline at end of file