diff --git a/src/main/java/io/bitsquare/gui/Navigation.java b/src/main/java/io/bitsquare/gui/Navigation.java index fac91eaa61..a9501fa260 100644 --- a/src/main/java/io/bitsquare/gui/Navigation.java +++ b/src/main/java/io/bitsquare/gui/Navigation.java @@ -159,14 +159,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,13 +218,19 @@ 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"); + 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; } @@ -232,5 +238,13 @@ public class Navigation { public String getFxmlUrl() { return fxmlUrl; } + + public String getDisplayName() { + return displayName; + } + + public String getId() { + return fxmlUrl.substring(fxmlUrl.lastIndexOf("/") + 1, fxmlUrl.lastIndexOf("View.fxml")).toLowerCase(); + } } } diff --git a/src/main/java/io/bitsquare/gui/main/MainViewCB.java b/src/main/java/io/bitsquare/gui/main/MainViewCB.java index 835a4f1974..7e37ded02e 100644 --- a/src/main/java/io/bitsquare/gui/main/MainViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/MainViewCB.java @@ -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,38 +47,31 @@ 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 { - private static final Logger log = LoggerFactory.getLogger(MainViewCB.class); + + private final ToggleGroup navButtons = new ToggleGroup(); + + private final AnchorPane contentContainer = new AnchorPane() {{ + setId("content-pane"); + setLeftAnchor(this, 0d); + setRightAnchor(this, 0d); + setTopAnchor(this, 60d); + setBottomAnchor(this, 25d); + }}; 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, Navigation navigation, OverlayManager overlayManager, + TradeManager tradeManager, Transitions transitions, BitcoinNetwork bitcoinNetwork, + @Named(TITLE_KEY) String title) { super(presentationModel); this.navigation = navigation; @@ -96,188 +88,113 @@ public class MainViewCB extends ViewCB { }); } - - /////////////////////////////////////////////////////////////////////////////////////////// - // 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); }}; + 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); }}; + ToggleButton settingsButton = new NavButton(SETTINGS); + ToggleButton accountButton = new NavButton(ACCOUNT); + Pane portfolioButtonHolder = new Pane(portfolioButton); + Pane bankAccountComboBoxHolder = new Pane(); + + 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 applicationContainer = new AnchorPane(leftNavPane, rightNavPane, contentContainer) {{ + setId("content-pane"); + }}; + + BorderPane baseApplicationContainer = new BorderPane(applicationContainer) {{ + setId("base-content-container"); + }}; navigation.addListener(navigationItems -> { - if (navigationItems != null && navigationItems.length == 2) { - if (navigationItems[0] == Navigation.Item.MAIN) { - loadView(navigationItems[1]); - selectMainMenuButton(navigationItems[1]); - } - } + if (isRequestToChangeNavigation(navigationItems)) + loadSelectedNavigation(navigationItems[1]); }); - overlayManager.addListener(new OverlayManager.OverlayListener() { - @Override - public void onBlurContentRequested() { - transitions.blur(baseApplicationContainer); - } + configureBlurring(baseApplicationContainer); - @Override - public void onRemoveBlurContentRequested() { - transitions.removeBlur(baseApplicationContainer); - } - }); + VBox splashScreen = createSplashScreen(); - startup(); - } + ((Pane) root).getChildren().addAll(baseApplicationContainer, splashScreen); - @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(); - } + if (newValue) { + bankAccountComboBoxHolder.getChildren().setAll(createBankAccountComboBox()); - private void onBackendReady() { - Profiler.printMsgWithTime("MainController.onBackendInited"); - addMainNavigation(); - } + applyPendingTradesInfoIcon(presentationModel.numPendingTrades.get(), portfolioButtonHolder); + presentationModel.numPendingTrades.addListener((ov1, oldValue1, newValue1) -> + applyPendingTradesInfoIcon((int) newValue1, portfolioButtonHolder)); - 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); + navigation.navigateToLastStoredItem(); + transitions.fadeOutAndRemove(splashScreen, 1500); } - 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(); + + Platform.runLater(presentationModel::initBackend); } - private void onContentAdded() { - Profiler.printMsgWithTime("MainController.onContentAdded"); - transitions.fadeOutAndRemove(splashScreen, 1500); + 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); + + navButtons.getToggles().stream() + .filter(toggle -> toggle instanceof ToggleButton) + .filter(button -> selected.getDisplayName().equals(((ToggleButton) button).getText())) + .findFirst() + .orElseThrow(() -> new BitsquareException("No button matching %s found", selected.getDisplayName())) + .setSelected(true); } - - /////////////////////////////////////////////////////////////////////////////////////////// - // 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 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 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 +284,7 @@ public class MainViewCB extends ViewCB { 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 comboBox = new ComboBox<>(presentationModel.getBankAccounts()); comboBox.setLayoutY(12); comboBox.setVisibleRowCount(5); @@ -485,6 +312,60 @@ public class MainViewCB extends ViewCB { vBox.setSpacing(2); vBox.setAlignment(Pos.CENTER); vBox.getChildren().setAll(comboBox, titleLabel); - parent.getChildren().add(vBox); + + return vBox; + } + + 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 boolean isRequestToChangeNavigation(Navigation.Item[] navigationItems) { + return navigationItems != null && navigationItems.length == 2 && navigationItems[0] == Navigation.Item.MAIN; + } + + + 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)); + } } } \ No newline at end of file