mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-18 23:06:02 -04:00
Merge branch 'cbeams'
Changes made during the effort to decouple "backend initialization" for the purpose of developing and testing the GUI while offline and/or without having to actually connect to the bitcoin / tomp2p networks. This decoupling is not yet possible--these changes just prepare for it. These changes also represent the first steps in streamlining controller archictecture toward maximum maintainability. See individual commit comments for details. * cbeams: Polish MainViewCB Refactor ViewLoader for proper injection Refactor MainViewCB and Navigation.Item
This commit is contained in:
commit
b9a1095578
@ -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<BitsquareModule> modules = Sets.newHashSet();
|
||||
|
||||
protected BitsquareModule(Environment env) {
|
||||
checkNotNull(env, "Environment must not be null");
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
47
src/main/java/io/bitsquare/gui/GuiceControllerFactory.java
Normal file
47
src/main/java/io/bitsquare/gui/GuiceControllerFactory.java
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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)}.
|
||||
* <p>
|
||||
* Once set, make sure you do <b>not</b> use the static methods on
|
||||
* {@link javafx.fxml.FXMLLoader} when creating your JavaFX node.
|
||||
*/
|
||||
public class GuiceControllerFactory implements Callback<Class<?>, 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);
|
||||
}
|
||||
}
|
@ -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
|
||||
@ -159,14 +158,14 @@ public class Navigation {
|
||||
// Main menu screens
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HOME("/io/bitsquare/gui/main/home/HomeView.fxml"),
|
||||
BUY("/io/bitsquare/gui/main/trade/BuyView.fxml"),
|
||||
SELL("/io/bitsquare/gui/main/trade/SellView.fxml"),
|
||||
PORTFOLIO("/io/bitsquare/gui/main/portfolio/PortfolioView.fxml"),
|
||||
FUNDS("/io/bitsquare/gui/main/funds/FundsView.fxml"),
|
||||
MSG("/io/bitsquare/gui/main/msg/MsgView.fxml"),
|
||||
SETTINGS("/io/bitsquare/gui/main/settings/SettingsView.fxml"),
|
||||
ACCOUNT("/io/bitsquare/gui/main/account/AccountView.fxml"),
|
||||
HOME("/io/bitsquare/gui/main/home/HomeView.fxml", "Overview"),
|
||||
BUY("/io/bitsquare/gui/main/trade/BuyView.fxml", "Buy BTC"),
|
||||
SELL("/io/bitsquare/gui/main/trade/SellView.fxml", "Sell BTC"),
|
||||
PORTFOLIO("/io/bitsquare/gui/main/portfolio/PortfolioView.fxml", "Portfolio"),
|
||||
FUNDS("/io/bitsquare/gui/main/funds/FundsView.fxml", "Funds"),
|
||||
MSG("/io/bitsquare/gui/main/msg/MsgView.fxml", "Messages"),
|
||||
SETTINGS("/io/bitsquare/gui/main/settings/SettingsView.fxml", "Settings"),
|
||||
ACCOUNT("/io/bitsquare/gui/main/account/AccountView.fxml", "Account"),
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -218,19 +217,38 @@ 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");
|
||||
ARBITRATOR_REGISTRATION(
|
||||
"/io/bitsquare/gui/main/account/arbitrator/registration/ArbitratorRegistrationView.fxml"),
|
||||
|
||||
// for testing, does not actually exist
|
||||
BOGUS("/io/bitsquare/BogusView.fxml");
|
||||
|
||||
|
||||
private final String displayName;
|
||||
private final String fxmlUrl;
|
||||
|
||||
Item(String fxmlUrl) {
|
||||
this(fxmlUrl, "NONE");
|
||||
}
|
||||
|
||||
Item(String fxmlUrl, String displayName) {
|
||||
this.displayName = displayName;
|
||||
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() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return fxmlUrl.substring(fxmlUrl.lastIndexOf("/") + 1, fxmlUrl.lastIndexOf("View.fxml")).toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public class ViewCB<T extends PresentationModel> implements Initializable {
|
||||
public static final String TITLE_KEY = "view.title";
|
||||
|
||||
protected T presentationModel;
|
||||
protected ViewCB<? extends PresentationModel> childController;
|
||||
protected Initializable childController;
|
||||
protected ViewCB<? extends PresentationModel> parent;
|
||||
|
||||
@FXML protected Parent root;
|
||||
|
@ -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<URL, Item> 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<URL, Item> 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> 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> T getController() {
|
||||
return (T) item.controller;
|
||||
}
|
||||
public static class Item {
|
||||
public final Node view;
|
||||
public final Initializable controller;
|
||||
|
||||
|
||||
class Item<T> {
|
||||
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)}.
|
||||
* <p>
|
||||
* Once set, make sure you do <b>not</b> use the static methods on
|
||||
* {@link javafx.fxml.FXMLLoader} when creating your JavaFX node.
|
||||
*/
|
||||
class GuiceControllerFactory implements Callback<Class<?>, Object> {
|
||||
|
||||
private final Injector injector;
|
||||
|
||||
public GuiceControllerFactory(Injector injector) {
|
||||
this.injector = injector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call(Class<?> aClass) {
|
||||
return injector.getInstance(aClass);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
package io.bitsquare.gui.main;
|
||||
|
||||
import io.bitsquare.BitsquareException;
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.btc.BitcoinNetwork;
|
||||
import io.bitsquare.gui.Navigation;
|
||||
@ -25,7 +26,6 @@ import io.bitsquare.gui.ViewCB;
|
||||
import io.bitsquare.gui.ViewLoader;
|
||||
import io.bitsquare.gui.components.Popups;
|
||||
import io.bitsquare.gui.components.SystemNotification;
|
||||
import io.bitsquare.gui.util.Profiler;
|
||||
import io.bitsquare.gui.util.Transitions;
|
||||
import io.bitsquare.trade.TradeManager;
|
||||
|
||||
@ -37,7 +37,6 @@ import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.*;
|
||||
@ -48,40 +47,26 @@ import javafx.scene.layout.*;
|
||||
import javafx.scene.paint.*;
|
||||
import javafx.scene.text.*;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import static io.bitsquare.gui.Navigation.Item.*;
|
||||
import static javafx.scene.layout.AnchorPane.*;
|
||||
|
||||
public class MainViewCB extends ViewCB<MainPM> {
|
||||
private static final Logger log = LoggerFactory.getLogger(MainViewCB.class);
|
||||
|
||||
private final ToggleGroup navButtons = new ToggleGroup();
|
||||
|
||||
private final ViewLoader viewLoader;
|
||||
private final Navigation navigation;
|
||||
private final OverlayManager overlayManager;
|
||||
private final ToggleGroup navButtonsGroup = new ToggleGroup();
|
||||
private Transitions transitions;
|
||||
private BitcoinNetwork bitcoinNetwork;
|
||||
private final Transitions transitions;
|
||||
private final BitcoinNetwork bitcoinNetwork;
|
||||
private final String title;
|
||||
|
||||
private BorderPane baseApplicationContainer;
|
||||
private VBox splashScreen;
|
||||
private AnchorPane contentContainer;
|
||||
private HBox leftNavPane, rightNavPane;
|
||||
private ToggleButton buyButton, sellButton, homeButton, msgButton, portfolioButton, fundsButton, settingsButton,
|
||||
accountButton;
|
||||
private Pane portfolioButtonButtonPane;
|
||||
private Label numPendingTradesLabel;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private 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;
|
||||
@ -96,188 +81,97 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
super.initialize(url, rb);
|
||||
Profiler.printMsgWithTime("MainController.initialize");
|
||||
|
||||
// just temp. ugly hack... Popups will be removed
|
||||
Popups.setOverlayManager(overlayManager);
|
||||
ToggleButton homeButton = new NavButton(HOME) {{
|
||||
setDisable(true); // during irc demo
|
||||
}};
|
||||
ToggleButton buyButton = new NavButton(BUY);
|
||||
ToggleButton sellButton = new NavButton(SELL);
|
||||
ToggleButton portfolioButton = new NavButton(PORTFOLIO);
|
||||
ToggleButton fundsButton = new NavButton(FUNDS);
|
||||
ToggleButton msgButton = new NavButton(MSG) {{
|
||||
setDisable(true); // during irc demo
|
||||
}};
|
||||
ToggleButton settingsButton = new NavButton(SETTINGS);
|
||||
ToggleButton accountButton = new NavButton(ACCOUNT);
|
||||
Pane portfolioButtonHolder = new Pane(portfolioButton);
|
||||
Pane bankAccountComboBoxHolder = new Pane();
|
||||
|
||||
navigation.addListener(navigationItems -> {
|
||||
if (navigationItems != null && navigationItems.length == 2) {
|
||||
if (navigationItems[0] == Navigation.Item.MAIN) {
|
||||
loadView(navigationItems[1]);
|
||||
selectMainMenuButton(navigationItems[1]);
|
||||
}
|
||||
}
|
||||
HBox leftNavPane = new HBox(
|
||||
homeButton, buyButton, sellButton, portfolioButtonHolder, fundsButton, new Pane(msgButton)) {{
|
||||
setSpacing(10);
|
||||
setLeftAnchor(this, 10d);
|
||||
setTopAnchor(this, 0d);
|
||||
}};
|
||||
|
||||
HBox rightNavPane = new HBox(bankAccountComboBoxHolder, settingsButton, accountButton) {{
|
||||
setSpacing(10);
|
||||
setRightAnchor(this, 10d);
|
||||
setTopAnchor(this, 0d);
|
||||
}};
|
||||
|
||||
AnchorPane contentContainer = new AnchorPane() {{
|
||||
setId("content-pane");
|
||||
setLeftAnchor(this, 0d);
|
||||
setRightAnchor(this, 0d);
|
||||
setTopAnchor(this, 60d);
|
||||
setBottomAnchor(this, 25d);
|
||||
}};
|
||||
|
||||
AnchorPane applicationContainer = new AnchorPane(leftNavPane, rightNavPane, contentContainer) {{
|
||||
setId("content-pane");
|
||||
}};
|
||||
|
||||
BorderPane baseApplicationContainer = new BorderPane(applicationContainer) {{
|
||||
setId("base-content-container");
|
||||
}};
|
||||
|
||||
navigation.addListener(navItems -> {
|
||||
if (navItems == null || navItems.length != 2 || navItems[0] != Navigation.Item.MAIN)
|
||||
return;
|
||||
|
||||
ViewLoader.Item loaded = viewLoader.load(navItems[1].getFxmlUrl());
|
||||
contentContainer.getChildren().setAll(loaded.view);
|
||||
if (loaded.controller instanceof ViewCB)
|
||||
((ViewCB) loaded.controller).setParent(this);
|
||||
|
||||
navButtons.getToggles().stream()
|
||||
.filter(toggle -> toggle instanceof ToggleButton)
|
||||
.filter(button -> navItems[1].getDisplayName().equals(((ToggleButton) button).getText()))
|
||||
.findFirst()
|
||||
.orElseThrow(() ->
|
||||
new BitsquareException("No button matching %s found", navItems[1].getDisplayName()))
|
||||
.setSelected(true);
|
||||
});
|
||||
|
||||
overlayManager.addListener(new OverlayManager.OverlayListener() {
|
||||
@Override
|
||||
public void onBlurContentRequested() {
|
||||
transitions.blur(baseApplicationContainer);
|
||||
}
|
||||
configureBlurring(baseApplicationContainer);
|
||||
|
||||
@Override
|
||||
public void onRemoveBlurContentRequested() {
|
||||
transitions.removeBlur(baseApplicationContainer);
|
||||
}
|
||||
VBox splashScreen = createSplashScreen();
|
||||
|
||||
((Pane) root).getChildren().addAll(baseApplicationContainer, splashScreen);
|
||||
|
||||
presentationModel.backendReady.addListener((ov1, prev1, ready) -> {
|
||||
if (!ready)
|
||||
return;
|
||||
|
||||
bankAccountComboBoxHolder.getChildren().setAll(createBankAccountComboBox());
|
||||
|
||||
applyPendingTradesInfoIcon(presentationModel.numPendingTrades.get(), portfolioButtonHolder);
|
||||
presentationModel.numPendingTrades.addListener((ov2, prev2, numPendingTrades) ->
|
||||
applyPendingTradesInfoIcon((int) numPendingTrades, portfolioButtonHolder));
|
||||
|
||||
navigation.navigateToLastStoredItem();
|
||||
|
||||
transitions.fadeOutAndRemove(splashScreen, 1500);
|
||||
});
|
||||
|
||||
startup();
|
||||
Platform.runLater(presentationModel::initBackend);
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
@Override
|
||||
public void terminate() {
|
||||
super.terminate();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Navigation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected Initializable loadView(Navigation.Item navigationItem) {
|
||||
super.loadView((navigationItem));
|
||||
final ViewLoader loader = new ViewLoader(navigationItem);
|
||||
final Node view = loader.load();
|
||||
contentContainer.getChildren().setAll(view);
|
||||
childController = loader.getController();
|
||||
|
||||
if (childController instanceof ViewCB)
|
||||
((ViewCB) childController).setParent(this);
|
||||
|
||||
return childController;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private Methods: Startup
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void startup() {
|
||||
baseApplicationContainer = getBaseApplicationContainer();
|
||||
splashScreen = getSplashScreen();
|
||||
((StackPane) root).getChildren().addAll(baseApplicationContainer, splashScreen);
|
||||
baseApplicationContainer.setCenter(getApplicationContainer());
|
||||
|
||||
Platform.runLater(this::onSplashScreenAdded);
|
||||
}
|
||||
|
||||
private void onSplashScreenAdded() {
|
||||
presentationModel.backendReady.addListener((ov, oldValue, newValue) -> {
|
||||
if (newValue)
|
||||
onBackendReady();
|
||||
});
|
||||
presentationModel.initBackend();
|
||||
}
|
||||
|
||||
private void onBackendReady() {
|
||||
Profiler.printMsgWithTime("MainController.onBackendInited");
|
||||
addMainNavigation();
|
||||
}
|
||||
|
||||
private void applyPendingTradesInfoIcon(int numPendingTrades) {
|
||||
log.debug("numPendingTrades " + numPendingTrades);
|
||||
if (numPendingTrades > 0) {
|
||||
if (portfolioButtonButtonPane.getChildren().size() == 1) {
|
||||
ImageView icon = new ImageView();
|
||||
icon.setLayoutX(0.5);
|
||||
icon.setId("image-alert-round");
|
||||
|
||||
numPendingTradesLabel = new Label(String.valueOf(numPendingTrades));
|
||||
numPendingTradesLabel.relocate(5, 1);
|
||||
numPendingTradesLabel.setId("nav-alert-label");
|
||||
|
||||
Pane alert = new Pane();
|
||||
alert.relocate(30, 9);
|
||||
alert.setMouseTransparent(true);
|
||||
alert.setEffect(new DropShadow(4, 1, 2, Color.GREY));
|
||||
alert.getChildren().addAll(icon, numPendingTradesLabel);
|
||||
portfolioButtonButtonPane.getChildren().add(alert);
|
||||
}
|
||||
else {
|
||||
numPendingTradesLabel.setText(String.valueOf(numPendingTrades));
|
||||
}
|
||||
|
||||
SystemNotification.openInfoNotification(title, "You got a new trade message.");
|
||||
}
|
||||
else {
|
||||
if (portfolioButtonButtonPane.getChildren().size() > 1)
|
||||
portfolioButtonButtonPane.getChildren().remove(1);
|
||||
}
|
||||
}
|
||||
|
||||
private void onMainNavigationAdded() {
|
||||
Profiler.printMsgWithTime("MainController.ondMainNavigationAdded");
|
||||
|
||||
presentationModel.numPendingTrades.addListener((ov, oldValue, newValue) ->
|
||||
{
|
||||
//if ((int) newValue > (int) oldValue)
|
||||
applyPendingTradesInfoIcon((int) newValue);
|
||||
});
|
||||
applyPendingTradesInfoIcon(presentationModel.numPendingTrades.get());
|
||||
navigation.navigateToLastStoredItem();
|
||||
onContentAdded();
|
||||
}
|
||||
|
||||
private void onContentAdded() {
|
||||
Profiler.printMsgWithTime("MainController.onContentAdded");
|
||||
transitions.fadeOutAndRemove(splashScreen, 1500);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void selectMainMenuButton(Navigation.Item item) {
|
||||
switch (item) {
|
||||
case HOME:
|
||||
homeButton.setSelected(true);
|
||||
break;
|
||||
case FUNDS:
|
||||
fundsButton.setSelected(true);
|
||||
break;
|
||||
case MSG:
|
||||
msgButton.setSelected(true);
|
||||
break;
|
||||
case PORTFOLIO:
|
||||
portfolioButton.setSelected(true);
|
||||
break;
|
||||
case SETTINGS:
|
||||
settingsButton.setSelected(true);
|
||||
break;
|
||||
case SELL:
|
||||
sellButton.setSelected(true);
|
||||
break;
|
||||
case BUY:
|
||||
buyButton.setSelected(true);
|
||||
break;
|
||||
case ACCOUNT:
|
||||
accountButton.setSelected(true);
|
||||
break;
|
||||
default:
|
||||
log.error(item.getFxmlUrl() + " is no main navigation item");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private BorderPane getBaseApplicationContainer() {
|
||||
BorderPane borderPane = new BorderPane();
|
||||
borderPane.setId("base-content-container");
|
||||
return borderPane;
|
||||
}
|
||||
|
||||
private VBox getSplashScreen() {
|
||||
private VBox createSplashScreen() {
|
||||
VBox vBox = new VBox();
|
||||
vBox.setAlignment(Pos.CENTER);
|
||||
vBox.setSpacing(10);
|
||||
@ -367,97 +261,7 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
return vBox;
|
||||
}
|
||||
|
||||
private AnchorPane getApplicationContainer() {
|
||||
AnchorPane anchorPane = new AnchorPane();
|
||||
anchorPane.setId("content-pane");
|
||||
|
||||
leftNavPane = new HBox();
|
||||
leftNavPane.setSpacing(10);
|
||||
AnchorPane.setLeftAnchor(leftNavPane, 10d);
|
||||
AnchorPane.setTopAnchor(leftNavPane, 0d);
|
||||
|
||||
rightNavPane = new HBox();
|
||||
rightNavPane.setSpacing(10);
|
||||
AnchorPane.setRightAnchor(rightNavPane, 10d);
|
||||
AnchorPane.setTopAnchor(rightNavPane, 0d);
|
||||
|
||||
contentContainer = new AnchorPane();
|
||||
contentContainer.setId("content-pane");
|
||||
AnchorPane.setLeftAnchor(contentContainer, 0d);
|
||||
AnchorPane.setRightAnchor(contentContainer, 0d);
|
||||
AnchorPane.setTopAnchor(contentContainer, 60d);
|
||||
AnchorPane.setBottomAnchor(contentContainer, 25d);
|
||||
|
||||
anchorPane.getChildren().addAll(leftNavPane, rightNavPane, contentContainer);
|
||||
return anchorPane;
|
||||
}
|
||||
|
||||
private void addMainNavigation() {
|
||||
homeButton = addNavButton(leftNavPane, "Overview", Navigation.Item.HOME);
|
||||
buyButton = addNavButton(leftNavPane, "Buy BTC", Navigation.Item.BUY);
|
||||
sellButton = addNavButton(leftNavPane, "Sell BTC", Navigation.Item.SELL);
|
||||
|
||||
portfolioButtonButtonPane = new Pane();
|
||||
portfolioButton = addNavButton(portfolioButtonButtonPane, "Portfolio", Navigation.Item.PORTFOLIO);
|
||||
leftNavPane.getChildren().add(portfolioButtonButtonPane);
|
||||
|
||||
fundsButton = addNavButton(leftNavPane, "Funds", Navigation.Item.FUNDS);
|
||||
|
||||
final Pane msgButtonHolder = new Pane();
|
||||
msgButton = addNavButton(msgButtonHolder, "Messages", Navigation.Item.MSG);
|
||||
leftNavPane.getChildren().add(msgButtonHolder);
|
||||
|
||||
addBankAccountComboBox(rightNavPane);
|
||||
|
||||
settingsButton = addNavButton(rightNavPane, "Settings", Navigation.Item.SETTINGS);
|
||||
accountButton = addNavButton(rightNavPane, "Account", Navigation.Item.ACCOUNT);
|
||||
|
||||
|
||||
// for irc demo
|
||||
homeButton.setDisable(true);
|
||||
msgButton.setDisable(true);
|
||||
|
||||
onMainNavigationAdded();
|
||||
}
|
||||
|
||||
private ToggleButton addNavButton(Pane parent, String title, Navigation.Item navigationItem) {
|
||||
final String url = navigationItem.getFxmlUrl();
|
||||
int lastSlash = url.lastIndexOf("/") + 1;
|
||||
int end = url.lastIndexOf("View.fxml");
|
||||
final String id = url.substring(lastSlash, end).toLowerCase();
|
||||
|
||||
ImageView iconImageView = new ImageView();
|
||||
iconImageView.setId("image-nav-" + id);
|
||||
|
||||
final ToggleButton toggleButton = new ToggleButton(title, iconImageView);
|
||||
toggleButton.setToggleGroup(navButtonsGroup);
|
||||
toggleButton.setId("nav-button");
|
||||
toggleButton.setPadding(new Insets(0, -10, -10, -10));
|
||||
toggleButton.setMinSize(50, 50);
|
||||
toggleButton.setMaxSize(50, 50);
|
||||
toggleButton.setContentDisplay(ContentDisplay.TOP);
|
||||
toggleButton.setGraphicTextGap(0);
|
||||
|
||||
toggleButton.selectedProperty().addListener((ov, oldValue, newValue) -> {
|
||||
toggleButton.setMouseTransparent(newValue);
|
||||
toggleButton.setMinSize(50, 50);
|
||||
toggleButton.setMaxSize(50, 50);
|
||||
toggleButton.setGraphicTextGap(newValue ? -1 : 0);
|
||||
if (newValue) {
|
||||
toggleButton.getGraphic().setId("image-nav-" + id + "-active");
|
||||
}
|
||||
else {
|
||||
toggleButton.getGraphic().setId("image-nav-" + id);
|
||||
}
|
||||
});
|
||||
|
||||
toggleButton.setOnAction(e -> navigation.navigationTo(Navigation.Item.MAIN, navigationItem));
|
||||
|
||||
parent.getChildren().add(toggleButton);
|
||||
return toggleButton;
|
||||
}
|
||||
|
||||
private void addBankAccountComboBox(Pane parent) {
|
||||
private VBox createBankAccountComboBox() {
|
||||
final ComboBox<BankAccount> comboBox = new ComboBox<>(presentationModel.getBankAccounts());
|
||||
comboBox.setLayoutY(12);
|
||||
comboBox.setVisibleRowCount(5);
|
||||
@ -485,6 +289,84 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
vBox.setSpacing(2);
|
||||
vBox.setAlignment(Pos.CENTER);
|
||||
vBox.getChildren().setAll(comboBox, titleLabel);
|
||||
parent.getChildren().add(vBox);
|
||||
|
||||
return vBox;
|
||||
}
|
||||
|
||||
private void applyPendingTradesInfoIcon(int numPendingTrades, Pane targetPane) {
|
||||
if (numPendingTrades <= 0) {
|
||||
if (targetPane.getChildren().size() > 1) {
|
||||
targetPane.getChildren().remove(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Label numPendingTradesLabel = new Label(String.valueOf(numPendingTrades));
|
||||
if (targetPane.getChildren().size() == 1) {
|
||||
ImageView icon = new ImageView();
|
||||
icon.setLayoutX(0.5);
|
||||
icon.setId("image-alert-round");
|
||||
|
||||
numPendingTradesLabel.relocate(5, 1);
|
||||
numPendingTradesLabel.setId("nav-alert-label");
|
||||
|
||||
Pane alert = new Pane();
|
||||
alert.relocate(30, 9);
|
||||
alert.setMouseTransparent(true);
|
||||
alert.setEffect(new DropShadow(4, 1, 2, Color.GREY));
|
||||
alert.getChildren().addAll(icon, numPendingTradesLabel);
|
||||
targetPane.getChildren().add(alert);
|
||||
}
|
||||
|
||||
SystemNotification.openInfoNotification(title, "You got a new trade message.");
|
||||
}
|
||||
|
||||
private void configureBlurring(Node node) {
|
||||
Popups.setOverlayManager(overlayManager);
|
||||
|
||||
overlayManager.addListener(new OverlayManager.OverlayListener() {
|
||||
@Override
|
||||
public void onBlurContentRequested() {
|
||||
transitions.blur(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoveBlurContentRequested() {
|
||||
transitions.removeBlur(node);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private class NavButton extends ToggleButton {
|
||||
|
||||
public NavButton(Navigation.Item item) {
|
||||
super(item.getDisplayName(), new ImageView() {{
|
||||
setId("image-nav-" + item.getId());
|
||||
}});
|
||||
|
||||
this.setToggleGroup(navButtons);
|
||||
this.setId("nav-button");
|
||||
this.setPadding(new Insets(0, -10, -10, -10));
|
||||
this.setMinSize(50, 50);
|
||||
this.setMaxSize(50, 50);
|
||||
this.setContentDisplay(ContentDisplay.TOP);
|
||||
this.setGraphicTextGap(0);
|
||||
|
||||
this.selectedProperty().addListener((ov, oldValue, newValue) -> {
|
||||
this.setMouseTransparent(newValue);
|
||||
this.setMinSize(50, 50);
|
||||
this.setMaxSize(50, 50);
|
||||
this.setGraphicTextGap(newValue ? -1 : 0);
|
||||
if (newValue) {
|
||||
this.getGraphic().setId("image-nav-" + item.getId() + "-active");
|
||||
}
|
||||
else {
|
||||
this.getGraphic().setId("image-nav-" + item.getId());
|
||||
}
|
||||
});
|
||||
|
||||
this.setOnAction(e -> navigation.navigationTo(Navigation.Item.MAIN, item));
|
||||
}
|
||||
}
|
||||
}
|
@ -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<AccountPM> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AccountViewCB.class);
|
||||
|
||||
private final Navigation navigation;
|
||||
private Navigation.Listener navigationListener;
|
||||
|
||||
private ChangeListener<Tab> 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<AccountPM> {
|
||||
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<AccountPM> {
|
||||
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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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<Arbitrator> 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;
|
||||
|
@ -53,7 +53,6 @@ import org.slf4j.LoggerFactory;
|
||||
public class RestrictionsViewCB extends CachedViewCB<RestrictionsPM> implements ContextAware {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RestrictionsViewCB.class);
|
||||
private final Stage primaryStage;
|
||||
|
||||
@FXML ListView<Locale> languagesListView;
|
||||
@FXML ListView<Country> countriesListView;
|
||||
@ -63,14 +62,18 @@ public class RestrictionsViewCB extends CachedViewCB<RestrictionsPM> implements
|
||||
@FXML ComboBox<Country> 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<RestrictionsPM> 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<RestrictionsPM> 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<RestrictionsPM> implements
|
||||
});
|
||||
stage.show();
|
||||
|
||||
return childController;
|
||||
return loaded.controller;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<? extends PresentationModel>) childController).setParent(this);
|
||||
((ContextAware) childController).useSettingsContext(true);
|
||||
return childController;
|
||||
|
@ -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<? extends PresentationModel>) childController).setParent(this);
|
||||
((ContextAware) childController).useSettingsContext(false);
|
||||
return childController;
|
||||
|
@ -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<Tab> 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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user