diff --git a/src/main/java/io/bitsquare/app/gui/BitsquareApp.java b/src/main/java/io/bitsquare/app/gui/BitsquareApp.java index 21cb4be151..8b66a99c1c 100644 --- a/src/main/java/io/bitsquare/app/gui/BitsquareApp.java +++ b/src/main/java/io/bitsquare/app/gui/BitsquareApp.java @@ -19,9 +19,9 @@ package io.bitsquare.app.gui; import io.bitsquare.BitsquareException; import io.bitsquare.account.AccountSettings; -import io.bitsquare.gui.FxmlView; import io.bitsquare.gui.SystemTray; import io.bitsquare.gui.components.Popups; +import io.bitsquare.gui.main.MainView; import io.bitsquare.gui.util.ImageUtil; import io.bitsquare.persistence.Persistence; import io.bitsquare.user.User; @@ -97,7 +97,7 @@ public class BitsquareApp extends Application { // load the main view and create the main scene ViewLoader viewLoader = injector.getInstance(CachingViewLoader.class); - View view = viewLoader.load(FxmlView.MAIN.getLocation()); + View view = viewLoader.load(MainView.class); Scene scene = new Scene((Parent) view.getRoot(), 1000, 600); scene.getStylesheets().setAll( diff --git a/src/main/java/io/bitsquare/gui/FxmlView.java b/src/main/java/io/bitsquare/gui/FxmlView.java deleted file mode 100644 index f33e779b8b..0000000000 --- a/src/main/java/io/bitsquare/gui/FxmlView.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 io.bitsquare.BitsquareException; - -import java.net.URL; - -public enum FxmlView { - - // ~ Application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - MAIN("/io/bitsquare/gui/main/MainView.fxml"), - - - // ~ Main menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - 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"), - - - // ~ Sub menus ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - // buy/sell (trade) - OFFER_BOOK("/io/bitsquare/gui/main/trade/offerbook/OfferBookView.fxml"), - CREATE_OFFER("/io/bitsquare/gui/main/trade/createoffer/CreateOfferView.fxml"), - TAKE_OFFER("/io/bitsquare/gui/main/trade/takeoffer/TakeOfferView.fxml"), - - // portfolio - OFFERS("/io/bitsquare/gui/main/portfolio/offer/OffersView.fxml"), - PENDING_TRADES("/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.fxml"), - CLOSED_TRADES("/io/bitsquare/gui/main/portfolio/closed/ClosedTradesView.fxml"), - - // funds - WITHDRAWAL("/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.fxml"), - TRANSACTIONS("/io/bitsquare/gui/main/funds/transactions/TransactionsView.fxml"), - - // settings - PREFERENCES("/io/bitsquare/gui/main/settings/application/PreferencesView.fxml"), - NETWORK_SETTINGS("/io/bitsquare/gui/main/settings/network/NetworkSettingsView.fxml"), - - // account - ACCOUNT_SETUP("/io/bitsquare/gui/main/account/setup/AccountSetupWizard.fxml"), - ACCOUNT_SETTINGS("/io/bitsquare/gui/main/account/settings/AccountSettingsView.fxml"), - ARBITRATOR_SETTINGS("/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsView.fxml"), - - - // ~ Content in sub menus ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - // account content - SEED_WORDS("/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.fxml"), - ADD_PASSWORD("/io/bitsquare/gui/main/account/content/password/PasswordView.fxml"), - CHANGE_PASSWORD("/io/bitsquare/gui/main/account/content/password/PasswordView.fxml"), - RESTRICTIONS("/io/bitsquare/gui/main/account/content/restrictions/RestrictionsView.fxml"), - REGISTRATION("/io/bitsquare/gui/main/account/content/registration/RegistrationView.fxml"), - FIAT_ACCOUNT("/io/bitsquare/gui/main/account/content/irc/IrcAccountView.fxml"), - - - // ~ Popups ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - // arbitration - 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"), - - - // ~ Testing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - BOGUS("/io/bitsquare/BogusView.fxml"); - - - private final String location; - private final String displayName; - - FxmlView(String location) { - this(location, "NONE"); - } - - FxmlView(String location, String displayName) { - this.location = location; - this.displayName = displayName; - } - - public URL getLocation() { - URL url = Navigation.class.getResource(location); - if (url == null) - throw new BitsquareException("'%s' could not be loaded as a resource", location); - return url; - } - - public String getDisplayName() { - return displayName; - } - - public String getId() { - return location.substring(location.lastIndexOf("/") + 1, location.lastIndexOf("View.fxml")).toLowerCase(); - } -} diff --git a/src/main/java/io/bitsquare/gui/Navigation.java b/src/main/java/io/bitsquare/gui/Navigation.java index 41ffbdb4cc..69df589deb 100644 --- a/src/main/java/io/bitsquare/gui/Navigation.java +++ b/src/main/java/io/bitsquare/gui/Navigation.java @@ -17,20 +17,26 @@ package io.bitsquare.gui; +import io.bitsquare.gui.main.MainView; +import io.bitsquare.gui.main.trade.BuyView; import io.bitsquare.persistence.Persistence; import com.google.inject.Inject; +import java.io.Serializable; + import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import viewfx.view.View; +import viewfx.view.ViewPath; + public class Navigation { private static final String CURRENT_PATH_KEY = "currentPath"; - // TODO: MAIN->BUY is the default view for now; should be MAIN->HOME later - private static final FxmlView[] DEFAULT_PATH = new FxmlView[]{ FxmlView.MAIN, FxmlView.BUY }; + private static final ViewPath DEFAULT_VIEW_PATH = ViewPath.to(MainView.class, BuyView.class); // New listeners can be added during iteration so we use CopyOnWriteArrayList to // prevent invalid array modification @@ -38,11 +44,11 @@ public class Navigation { private final Persistence persistence; - private FxmlView[] currentPath; + private ViewPath currentPath; // Used for returning to the last important view. After setup is done we want to // return to the last opened view (e.g. sell/buy) - private FxmlView[] returnPath; + private ViewPath returnPath; @Inject @@ -50,46 +56,50 @@ public class Navigation { this.persistence = persistence; } - public void navigateTo(FxmlView... newPath) { + public void navigateTo(Class... viewClasses) { + navigateTo(ViewPath.to(viewClasses)); + } + + public void navigateTo(ViewPath newPath) { if (newPath == null) return; - List temp = new ArrayList<>(); - for (int i = 0; i < newPath.length; i++) { - FxmlView element = newPath[i]; - temp.add(element); + ArrayList> temp = new ArrayList<>(); + for (int i = 0; i < newPath.size(); i++) { + Class viewClass = newPath.get(i); + temp.add(viewClass); if (currentPath == null || (currentPath != null && - currentPath.length > i && - element != currentPath[i] && - i != newPath.length - 1)) { - List temp2 = new ArrayList<>(temp); - for (int n = i + 1; n < newPath.length; n++) { - FxmlView[] newTemp = new FxmlView[i + 1]; - currentPath = temp2.toArray(newTemp); + currentPath.size() > i && + viewClass != currentPath.get(i) && + i != newPath.size() - 1)) { + ArrayList> temp2 = new ArrayList<>(temp); + for (int n = i + 1; n < newPath.size(); n++) { + Class[] newTemp = new Class[i + 1]; + currentPath = ViewPath.to(temp2.toArray(newTemp)); navigateTo(currentPath); - element = newPath[n]; - temp2.add(element); + viewClass = newPath.get(n); + temp2.add(viewClass); } } } currentPath = newPath; - persistence.write(this, CURRENT_PATH_KEY, currentPath); + persistence.write(this, CURRENT_PATH_KEY, (List)currentPath); listeners.stream().forEach((e) -> e.onNavigationRequested(currentPath)); } public void navigateToLastOpenView() { - FxmlView[] lastPath = (FxmlView[]) persistence.read(this, CURRENT_PATH_KEY); + ViewPath lastPath = (ViewPath) persistence.read(this, CURRENT_PATH_KEY); - if (lastPath == null || lastPath.length == 0) - lastPath = DEFAULT_PATH; + if (lastPath == null || lastPath.size() == 0) + lastPath = DEFAULT_VIEW_PATH; navigateTo(lastPath); } public static interface Listener { - void onNavigationRequested(FxmlView... path); + void onNavigationRequested(ViewPath path); } public void addListener(Listener listener) { @@ -100,16 +110,15 @@ public class Navigation { listeners.remove(listener); } - public FxmlView[] getReturnPath() { + public ViewPath getReturnPath() { return returnPath; } - public FxmlView[] getCurrentPath() { + public ViewPath getCurrentPath() { return currentPath; } - public void setReturnPath(FxmlView[] returnPath) { + public void setReturnPath(ViewPath returnPath) { this.returnPath = returnPath; } - } diff --git a/src/main/java/io/bitsquare/gui/main/MainView.java b/src/main/java/io/bitsquare/gui/main/MainView.java index 8d96000d1f..fe05d762e4 100644 --- a/src/main/java/io/bitsquare/gui/main/MainView.java +++ b/src/main/java/io/bitsquare/gui/main/MainView.java @@ -19,16 +19,24 @@ package io.bitsquare.gui.main; import io.bitsquare.BitsquareException; import io.bitsquare.bank.BankAccount; -import io.bitsquare.gui.FxmlView; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.OverlayManager; import io.bitsquare.gui.components.Popups; import io.bitsquare.gui.components.SystemNotification; +import io.bitsquare.gui.main.account.AccountView; +import io.bitsquare.gui.main.funds.FundsView; +import io.bitsquare.gui.main.home.HomeView; +import io.bitsquare.gui.main.msg.MsgView; +import io.bitsquare.gui.main.portfolio.PortfolioView; +import io.bitsquare.gui.main.settings.SettingsView; +import io.bitsquare.gui.main.trade.BuyView; +import io.bitsquare.gui.main.trade.SellView; import io.bitsquare.gui.util.Transitions; import javax.inject.Inject; import javax.inject.Named; +import viewfx.view.FxmlView; import viewfx.view.View; import viewfx.view.ViewLoader; import viewfx.view.support.ActivatableView; @@ -44,9 +52,9 @@ import javafx.scene.layout.*; import javafx.scene.paint.*; import javafx.scene.text.*; -import static io.bitsquare.gui.FxmlView.*; import static javafx.scene.layout.AnchorPane.*; +@FxmlView public class MainView extends ActivatableView { public static final String TITLE_KEY = "view.title"; @@ -79,18 +87,18 @@ public class MainView extends ActivatableView { @Override protected void activate() { - ToggleButton homeButton = new NavButton(HOME) {{ + ToggleButton homeButton = new NavButton(HomeView.class, "Overview") {{ 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) {{ + ToggleButton buyButton = new NavButton(BuyView.class, "Buy BTC"); + ToggleButton sellButton = new NavButton(SellView.class, "Sell BTC"); + ToggleButton portfolioButton = new NavButton(PortfolioView.class, "Portfolio"); + ToggleButton fundsButton = new NavButton(FundsView.class, "Funds"); + ToggleButton msgButton = new NavButton(MsgView.class, "Messages") {{ setDisable(true); // during irc demo }}; - ToggleButton settingsButton = new NavButton(SETTINGS); - ToggleButton accountButton = new NavButton(ACCOUNT); + ToggleButton settingsButton = new NavButton(SettingsView.class, "Settings"); + ToggleButton accountButton = new NavButton(AccountView.class, "Account"); Pane portfolioButtonHolder = new Pane(portfolioButton); Pane bankAccountComboBoxHolder = new Pane(); @@ -123,19 +131,19 @@ public class MainView extends ActivatableView { setId("base-content-container"); }}; - navigation.addListener(navItems -> { - if (navItems == null || navItems.length != 2 || navItems[0] != FxmlView.MAIN) + navigation.addListener(viewPath -> { + if (viewPath.size() != 2 || viewPath.indexOf(MainView.class) != 0) return; - View view = viewLoader.load(navItems[1].getLocation()); + Class viewClass = viewPath.tip(); + View view = viewLoader.load(viewClass); contentContainer.getChildren().setAll(view.getRoot()); navButtons.getToggles().stream() - .filter(toggle -> toggle instanceof ToggleButton) - .filter(button -> navItems[1].getDisplayName().equals(((ToggleButton) button).getText())) + .filter(toggle -> toggle instanceof NavButton) + .filter(button -> viewClass == ((NavButton) button).viewClass) .findFirst() - .orElseThrow(() -> - new BitsquareException("No button matching %s found", navItems[1].getDisplayName())) + .orElseThrow(() -> new BitsquareException("No button matching %s found", viewClass)) .setSelected(true); }); @@ -334,11 +342,15 @@ public class MainView extends ActivatableView { private class NavButton extends ToggleButton { - public NavButton(FxmlView item) { - super(item.getDisplayName(), new ImageView() {{ - setId("image-nav-" + item.getId()); + private final Class viewClass; + + public NavButton(Class viewClass, String title) { + super(title, new ImageView() {{ + setId("image-nav-" + viewId(viewClass)); }}); + this.viewClass = viewClass; + this.setToggleGroup(navButtons); this.setId("nav-button"); this.setPadding(new Insets(0, -10, -10, -10)); @@ -353,14 +365,24 @@ public class MainView extends ActivatableView { this.setMaxSize(50, 50); this.setGraphicTextGap(newValue ? -1 : 0); if (newValue) { - this.getGraphic().setId("image-nav-" + item.getId() + "-active"); + this.getGraphic().setId("image-nav-" + viewId(viewClass) + "-active"); } else { - this.getGraphic().setId("image-nav-" + item.getId()); + this.getGraphic().setId("image-nav-" + viewId(viewClass)); } }); - this.setOnAction(e -> navigation.navigateTo(FxmlView.MAIN, item)); + this.setOnAction(e -> navigation.navigateTo(MainView.class, viewClass)); } + + } + + private static String viewId(Class viewClass) { + String viewName = viewClass.getSimpleName(); + String suffix = "View"; + int suffixIdx = viewName.indexOf(suffix); + if (suffixIdx != viewName.length() - suffix.length()) + throw new IllegalArgumentException("Cannot get ID for " + viewClass + ": class must end in " + suffix); + return viewName.substring(0, suffixIdx).toLowerCase(); } } \ No newline at end of file diff --git a/src/main/java/io/bitsquare/gui/main/account/AccountView.java b/src/main/java/io/bitsquare/gui/main/account/AccountView.java index 0bb01a6861..8f9c46c337 100644 --- a/src/main/java/io/bitsquare/gui/main/account/AccountView.java +++ b/src/main/java/io/bitsquare/gui/main/account/AccountView.java @@ -17,19 +17,25 @@ package io.bitsquare.gui.main.account; -import io.bitsquare.gui.FxmlView; import io.bitsquare.gui.Navigation; +import io.bitsquare.gui.main.MainView; +import io.bitsquare.gui.main.account.arbitrator.ArbitratorSettingsView; +import io.bitsquare.gui.main.account.settings.AccountSettingsView; +import io.bitsquare.gui.main.account.setup.AccountSetupWizard; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.View; import viewfx.view.ViewLoader; +import viewfx.view.ViewPath; import viewfx.view.support.ActivatableView; import javafx.beans.value.ChangeListener; import javafx.fxml.FXML; import javafx.scene.control.*; +@FxmlView public class AccountView extends ActivatableView { @FXML Tab accountSettingsTab, arbitratorSettingsTab; @@ -49,21 +55,16 @@ public class AccountView extends ActivatableView { @Override public void initialize() { - navigationListener = navigationItems -> { - if (navigationItems != null && - navigationItems.length == 3 && - navigationItems[1] == FxmlView.ACCOUNT) - loadView(navigationItems[2]); + navigationListener = viewPath -> { + if (viewPath.size() == 3 && viewPath.indexOf(AccountView.class) == 1) + loadView(viewPath); }; tabChangeListener = (ov, oldValue, newValue) -> { if (newValue == accountSettingsTab) - navigation.navigateTo(FxmlView.MAIN, FxmlView.ACCOUNT, - FxmlView.ACCOUNT_SETTINGS); + navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class); else - navigation.navigateTo(FxmlView.MAIN, FxmlView.ACCOUNT, - FxmlView.ARBITRATOR_SETTINGS); - + navigation.navigateTo(MainView.class, AccountView.class, ArbitratorSettingsView.class); }; } @@ -72,21 +73,16 @@ public class AccountView extends ActivatableView { navigation.addListener(navigationListener); root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener); - if (navigation.getCurrentPath().length == 2 && - navigation.getCurrentPath()[1] == FxmlView.ACCOUNT) { - if (model.getNeedRegistration()) { - navigation.navigateTo(FxmlView.MAIN, FxmlView.ACCOUNT, - FxmlView.ACCOUNT_SETUP); - } - else { - if (root.getSelectionModel().getSelectedItem() == accountSettingsTab) - navigation.navigateTo(FxmlView.MAIN, FxmlView.ACCOUNT, - FxmlView.ACCOUNT_SETTINGS); - else - navigation.navigateTo(FxmlView.MAIN, FxmlView.ACCOUNT, - FxmlView.ARBITRATOR_SETTINGS); - } - } + if (!navigation.getCurrentPath().contains(AccountView.class)) + return; + + if (model.getNeedRegistration()) + navigation.navigateTo(MainView.class, AccountView.class, AccountSetupWizard.class); + + else if (root.getSelectionModel().getSelectedItem() == accountSettingsTab) + navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class); + + navigation.navigateTo(MainView.class, AccountView.class, ArbitratorSettingsView.class); } @Override @@ -95,31 +91,31 @@ public class AccountView extends ActivatableView { root.getSelectionModel().selectedItemProperty().removeListener(tabChangeListener); } + private void loadView(ViewPath viewPath) { + Tab tab; + Class viewClass = viewPath.tip(); - private void loadView(FxmlView navigationItem) { - View view = viewLoader.load(navigationItem.getLocation()); - final Tab tab; - switch (navigationItem) { - case ACCOUNT_SETTINGS: - tab = accountSettingsTab; - tab.setText("Account settings"); - arbitratorSettingsTab.setDisable(false); - break; - case ACCOUNT_SETUP: - tab = accountSettingsTab; - tab.setText("Account setup"); - arbitratorSettingsTab.setDisable(true); - break; - case ARBITRATOR_SETTINGS: - tab = arbitratorSettingsTab; - break; - default: - throw new IllegalArgumentException("navigation item of type " + navigationItem + " is not allowed"); + if (viewClass == AccountSettingsView.class) { + tab = accountSettingsTab; + tab.setText("Account settings"); + arbitratorSettingsTab.setDisable(false); + } + else if (viewClass == AccountSetupWizard.class) { + tab = accountSettingsTab; + tab.setText("Account setup"); + arbitratorSettingsTab.setDisable(true); + } + else if (viewClass == ArbitratorSettingsView.class) { + tab = arbitratorSettingsTab; + } + else { + throw new IllegalArgumentException("Loading " + viewClass + " from " + this + " is not supported"); } // for IRC demo we deactivate the arbitratorSettingsTab arbitratorSettingsTab.setDisable(true); + View view = viewLoader.load(viewClass); tab.setContent(view.getRoot()); root.getSelectionModel().select(tab); } diff --git a/src/main/java/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsView.java b/src/main/java/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsView.java index eb1f3f1dd4..7466f5720e 100644 --- a/src/main/java/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsView.java +++ b/src/main/java/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsView.java @@ -17,43 +17,48 @@ package io.bitsquare.gui.main.account.arbitrator; -import io.bitsquare.gui.FxmlView; -import io.bitsquare.gui.Navigation; import io.bitsquare.gui.main.account.arbitrator.registration.ArbitratorRegistrationView; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.View; import viewfx.view.ViewLoader; -import viewfx.view.support.CachingViewLoader; import viewfx.view.support.AbstractView; +import viewfx.view.support.CachingViewLoader; import javafx.fxml.FXML; import javafx.scene.*; import javafx.stage.Modality; import javafx.stage.Stage; -// TODO Arbitration is very basic yet -class ArbitratorSettingsView extends AbstractView { - - private ArbitratorRegistrationView arbitratorRegistrationView; +@FxmlView +public class ArbitratorSettingsView extends AbstractView { private final ViewLoader viewLoader; - private final Navigation navigation; private final Stage primaryStage; @Inject - private ArbitratorSettingsView(CachingViewLoader viewLoader, Navigation navigation, Stage primaryStage) { + private ArbitratorSettingsView(CachingViewLoader viewLoader, Stage primaryStage) { this.viewLoader = viewLoader; - this.navigation = navigation; this.primaryStage = primaryStage; } - private void loadView(FxmlView navigationItem) { - View view = viewLoader.load(navigationItem.getLocation()); - arbitratorRegistrationView = (ArbitratorRegistrationView) view; + @FXML + public void onArbitratorRegistration() { + View view = viewLoader.load(ArbitratorRegistrationView.class); + showStage(view); + } - final Stage stage = new Stage(); + @FXML + public void onArbitratorEdit() { + View view = viewLoader.load(ArbitratorRegistrationView.class); + showStage(view); + ((ArbitratorRegistrationView) view).setEditMode(true); + } + + private void showStage(View view) { + Stage stage = new Stage(); stage.setTitle("Arbitrator"); stage.setMinWidth(800); stage.setMinHeight(400); @@ -67,16 +72,5 @@ class ArbitratorSettingsView extends AbstractView { stage.setScene(scene); stage.show(); } - - @FXML - public void onArbitratorRegistration() { - loadView(FxmlView.ARBITRATOR_REGISTRATION); - } - - @FXML - public void onArbitratorEdit() { - loadView(FxmlView.ARBITRATOR_REGISTRATION); - arbitratorRegistrationView.setEditMode(true); - } } diff --git a/src/main/java/io/bitsquare/gui/main/account/arbitrator/browser/ArbitratorBrowserView.java b/src/main/java/io/bitsquare/gui/main/account/arbitrator/browser/ArbitratorBrowserView.java index 1a5b4b40e3..8e89d37719 100644 --- a/src/main/java/io/bitsquare/gui/main/account/arbitrator/browser/ArbitratorBrowserView.java +++ b/src/main/java/io/bitsquare/gui/main/account/arbitrator/browser/ArbitratorBrowserView.java @@ -19,7 +19,6 @@ package io.bitsquare.gui.main.account.arbitrator.browser; import io.bitsquare.account.AccountSettings; import io.bitsquare.arbitrator.Arbitrator; -import io.bitsquare.gui.FxmlView; import io.bitsquare.gui.main.account.arbitrator.profile.ArbitratorProfileView; import io.bitsquare.locale.LanguageUtil; import io.bitsquare.msg.MessageService; @@ -31,6 +30,7 @@ import java.util.List; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.View; import viewfx.view.ViewLoader; import viewfx.view.support.ActivatableView; @@ -40,8 +40,8 @@ import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.stage.Stage; -// TODO Arbitration is very basic yet -class ArbitratorBrowserView extends ActivatableView implements ArbitratorListener { +@FxmlView +public class ArbitratorBrowserView extends ActivatableView implements ArbitratorListener { @FXML Button prevButton, nextButton, selectButton, closeButton; @FXML Pane arbitratorProfile; @@ -71,30 +71,11 @@ class ArbitratorBrowserView extends ActivatableView implements Arbit messageService.addArbitratorListener(this); messageService.getArbitrators(LanguageUtil.getDefaultLanguageLocale()); - loadView(FxmlView.ARBITRATOR_PROFILE); - checkButtonState(); - } - - /* public Initializable loadViewAndGetChildController(Navigation.Item item) { - final ViewLoader loader = new ViewLoader(getClass().getResource(item.getFxmlUrl())); - try { - final Node view = loader.load(); - arbitratorProfileView = loader.getController(); - arbitratorProfileView.setParentController(this); - root.getChildren().set(0, view); - - return arbitratorProfileView; - } catch (IOException e) { - e.printStackTrace(); - } - return null; - }*/ - - - private void loadView(FxmlView navigationItem) { - View view = viewLoader.load(navigationItem.getLocation()); + View view = viewLoader.load(ArbitratorProfileView.class); root.getChildren().set(0, view.getRoot()); arbitratorProfileView = (ArbitratorProfileView) view; + + checkButtonState(); } @Override @@ -118,7 +99,6 @@ class ArbitratorBrowserView extends ActivatableView implements Arbit public void onArbitratorRemoved(Arbitrator arbitrator) { } - @FXML public void onPrevious() { if (index > 0) { @@ -151,7 +131,6 @@ class ArbitratorBrowserView extends ActivatableView implements Arbit stage.close(); } - private void checkButtonState() { prevButton.setDisable(index < 1); nextButton.setDisable(index == allArbitrators.size() - 1 || index == -1); diff --git a/src/main/java/io/bitsquare/gui/main/account/arbitrator/profile/ArbitratorProfileView.java b/src/main/java/io/bitsquare/gui/main/account/arbitrator/profile/ArbitratorProfileView.java index fdb2b7e201..166cf5b4cd 100644 --- a/src/main/java/io/bitsquare/gui/main/account/arbitrator/profile/ArbitratorProfileView.java +++ b/src/main/java/io/bitsquare/gui/main/account/arbitrator/profile/ArbitratorProfileView.java @@ -19,17 +19,16 @@ package io.bitsquare.gui.main.account.arbitrator.profile; import io.bitsquare.arbitrator.Arbitrator; import io.bitsquare.gui.util.BSFormatter; -import io.bitsquare.persistence.Persistence; -import io.bitsquare.settings.Preferences; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.AbstractView; import javafx.fxml.FXML; import javafx.scene.control.*; -// TODO Arbitration is very basic yet +@FxmlView public class ArbitratorProfileView extends AbstractView { @FXML Label nameLabel; @@ -37,14 +36,10 @@ public class ArbitratorProfileView extends AbstractView { @FXML TextField nameTextField, languagesTextField, reputationTextField, feeTextField, methodsTextField, passiveServiceFeeTextField, idVerificationsTextField, webPageTextField, maxTradeVolumeTextField; - private final Preferences preferences; - private final Persistence persistence; private final BSFormatter formatter; @Inject - public ArbitratorProfileView(Preferences preferences, Persistence persistence, BSFormatter formatter) { - this.preferences = preferences; - this.persistence = persistence; + public ArbitratorProfileView(BSFormatter formatter) { this.formatter = formatter; } diff --git a/src/main/java/io/bitsquare/gui/main/account/arbitrator/registration/ArbitratorRegistrationView.java b/src/main/java/io/bitsquare/gui/main/account/arbitrator/registration/ArbitratorRegistrationView.java index 6044382ef7..6c2fd2cac3 100644 --- a/src/main/java/io/bitsquare/gui/main/account/arbitrator/registration/ArbitratorRegistrationView.java +++ b/src/main/java/io/bitsquare/gui/main/account/arbitrator/registration/ArbitratorRegistrationView.java @@ -44,6 +44,7 @@ import java.util.Locale; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.ActivatableView; import javafx.collections.FXCollections; @@ -56,7 +57,7 @@ import javafx.util.StringConverter; import de.jensd.fx.fontawesome.AwesomeDude; import de.jensd.fx.fontawesome.AwesomeIcon; -// TODO Arbitration is very basic yet +@FxmlView public class ArbitratorRegistrationView extends ActivatableView { @FXML Accordion accordion; @@ -119,7 +120,6 @@ public class ArbitratorRegistrationView extends ActivatableView(EnumSet.allOf(Arbitrator.ID_TYPE.class)))); idTypeComboBox.setConverter(new StringConverter() { - @Override public String toString(Arbitrator.ID_TYPE item) { return BSResources.get(item.toString()); } - @Override public Arbitrator.ID_TYPE fromString(String s) { return null; @@ -145,13 +143,11 @@ public class ArbitratorRegistrationView extends ActivatableView(EnumSet.allOf(Arbitrator.METHOD .class)))); methodsComboBox.setConverter(new StringConverter() { - @Override public String toString(Arbitrator.METHOD item) { return BSResources.get(item.toString()); } - @Override public Arbitrator.METHOD fromString(String s) { return null; @@ -161,13 +157,11 @@ public class ArbitratorRegistrationView extends ActivatableView(EnumSet.allOf(Arbitrator.ID_VERIFICATION.class)))); idVerificationsComboBox.setConverter(new StringConverter() { - @Override public String toString(Arbitrator.ID_VERIFICATION item) { return BSResources.get(item.toString()); } - @Override public Arbitrator.ID_VERIFICATION fromString(String s) { return null; @@ -375,7 +369,6 @@ public class ArbitratorRegistrationView extends ActivatableView implements Wizard.Step { +@FxmlView +public class ChangePasswordView extends InitializableView implements Wizard.Step { @FXML HBox buttonsHBox; @FXML Button saveButton, skipButton; diff --git a/src/main/java/io/bitsquare/gui/main/account/content/fiat/FiatAccountView.java b/src/main/java/io/bitsquare/gui/main/account/content/fiat/FiatAccountView.java index 08b4831b50..296c96c925 100644 --- a/src/main/java/io/bitsquare/gui/main/account/content/fiat/FiatAccountView.java +++ b/src/main/java/io/bitsquare/gui/main/account/content/fiat/FiatAccountView.java @@ -35,8 +35,9 @@ import java.util.List; import javax.inject.Inject; -import viewfx.view.support.ActivatableViewAndModel; +import viewfx.view.FxmlView; import viewfx.view.Wizard; +import viewfx.view.support.ActivatableViewAndModel; import javafx.collections.ListChangeListener; import javafx.event.ActionEvent; @@ -50,7 +51,8 @@ import org.controlsfx.dialog.Dialog; import static javafx.beans.binding.Bindings.createBooleanBinding; -class FiatAccountView extends ActivatableViewAndModel implements Wizard.Step { +@FxmlView +public class FiatAccountView extends ActivatableViewAndModel implements Wizard.Step { @FXML HBox buttonsHBox; @FXML ComboBox regionComboBox; diff --git a/src/main/java/io/bitsquare/gui/main/account/content/irc/IrcAccountView.java b/src/main/java/io/bitsquare/gui/main/account/content/irc/IrcAccountView.java index d7bc4aa315..80bb74b089 100644 --- a/src/main/java/io/bitsquare/gui/main/account/content/irc/IrcAccountView.java +++ b/src/main/java/io/bitsquare/gui/main/account/content/irc/IrcAccountView.java @@ -28,6 +28,7 @@ import java.util.Currency; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.ActivatableViewAndModel; import viewfx.view.Wizard; @@ -40,6 +41,7 @@ import javafx.util.Callback; /** * Just temporary for giving the user a possibility to test the app via simulating the bank transfer in a IRC chat. */ +@FxmlView public class IrcAccountView extends ActivatableViewAndModel implements Wizard.Step { @FXML HBox buttonsHBox; diff --git a/src/main/java/io/bitsquare/gui/main/account/content/password/PasswordView.java b/src/main/java/io/bitsquare/gui/main/account/content/password/PasswordView.java index 635384c643..ce57a61279 100644 --- a/src/main/java/io/bitsquare/gui/main/account/content/password/PasswordView.java +++ b/src/main/java/io/bitsquare/gui/main/account/content/password/PasswordView.java @@ -22,13 +22,15 @@ import io.bitsquare.gui.main.help.HelpId; import javax.inject.Inject; -import viewfx.view.support.InitializableView; +import viewfx.view.FxmlView; import viewfx.view.Wizard; +import viewfx.view.support.InitializableView; import javafx.fxml.FXML; import javafx.scene.control.*; import javafx.scene.layout.*; +@FxmlView public class PasswordView extends InitializableView implements Wizard.Step { @FXML HBox buttonsHBox; diff --git a/src/main/java/io/bitsquare/gui/main/account/content/registration/RegistrationView.java b/src/main/java/io/bitsquare/gui/main/account/content/registration/RegistrationView.java index 78b8cee6b1..5b9cb9bd5f 100644 --- a/src/main/java/io/bitsquare/gui/main/account/content/registration/RegistrationView.java +++ b/src/main/java/io/bitsquare/gui/main/account/content/registration/RegistrationView.java @@ -30,8 +30,9 @@ import java.util.List; import javax.inject.Inject; -import viewfx.view.support.InitializableView; +import viewfx.view.FxmlView; import viewfx.view.Wizard; +import viewfx.view.support.InitializableView; import javafx.event.ActionEvent; import javafx.fxml.FXML; @@ -42,6 +43,7 @@ import org.controlsfx.control.action.AbstractAction; import org.controlsfx.control.action.Action; import org.controlsfx.dialog.Dialog; +@FxmlView public class RegistrationView extends InitializableView implements Wizard.Step { @FXML TextField feeTextField; diff --git a/src/main/java/io/bitsquare/gui/main/account/content/restrictions/RestrictionsView.java b/src/main/java/io/bitsquare/gui/main/account/content/restrictions/RestrictionsView.java index ab0054b174..d029d8e726 100644 --- a/src/main/java/io/bitsquare/gui/main/account/content/restrictions/RestrictionsView.java +++ b/src/main/java/io/bitsquare/gui/main/account/content/restrictions/RestrictionsView.java @@ -18,7 +18,7 @@ package io.bitsquare.gui.main.account.content.restrictions; import io.bitsquare.arbitrator.Arbitrator; -import io.bitsquare.gui.FxmlView; +import io.bitsquare.gui.main.account.arbitrator.browser.ArbitratorBrowserView; import io.bitsquare.gui.main.help.Help; import io.bitsquare.gui.main.help.HelpId; import io.bitsquare.gui.util.ImageUtil; @@ -29,6 +29,7 @@ import java.util.Locale; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.View; import viewfx.view.ViewLoader; import viewfx.view.Wizard; @@ -45,6 +46,7 @@ import javafx.stage.Stage; import javafx.util.Callback; import javafx.util.StringConverter; +@FxmlView public class RestrictionsView extends ActivatableViewAndModel implements Wizard.Step { @FXML ListView languagesListView; @@ -120,8 +122,9 @@ public class RestrictionsView extends ActivatableViewAndModel { - if (navigationItem == FxmlView.ARBITRATOR_BROWSER) + if (view instanceof ArbitratorBrowserView) updateArbitratorList(); }); stage.show(); diff --git a/src/main/java/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.java b/src/main/java/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.java index 3a85a63ed6..0a06990a8b 100644 --- a/src/main/java/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.java +++ b/src/main/java/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.java @@ -22,13 +22,15 @@ import io.bitsquare.gui.main.help.HelpId; import javax.inject.Inject; -import viewfx.view.support.InitializableView; +import viewfx.view.FxmlView; import viewfx.view.Wizard; +import viewfx.view.support.InitializableView; import javafx.fxml.FXML; import javafx.scene.control.*; import javafx.scene.layout.*; +@FxmlView public class SeedWordsView extends InitializableView implements Wizard.Step { @FXML Button completedButton; diff --git a/src/main/java/io/bitsquare/gui/main/account/settings/AccountSettingsView.java b/src/main/java/io/bitsquare/gui/main/account/settings/AccountSettingsView.java index 2930e8c9e5..b1cd1785a6 100644 --- a/src/main/java/io/bitsquare/gui/main/account/settings/AccountSettingsView.java +++ b/src/main/java/io/bitsquare/gui/main/account/settings/AccountSettingsView.java @@ -17,14 +17,23 @@ package io.bitsquare.gui.main.account.settings; -import io.bitsquare.gui.FxmlView; +import io.bitsquare.BitsquareException; import io.bitsquare.gui.Navigation; +import io.bitsquare.gui.main.MainView; +import io.bitsquare.gui.main.account.AccountView; +import io.bitsquare.gui.main.account.content.changepassword.ChangePasswordView; +import io.bitsquare.gui.main.account.content.fiat.FiatAccountView; +import io.bitsquare.gui.main.account.content.registration.RegistrationView; +import io.bitsquare.gui.main.account.content.restrictions.RestrictionsView; +import io.bitsquare.gui.main.account.content.seedwords.SeedWordsView; import io.bitsquare.gui.util.Colors; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.View; import viewfx.view.ViewLoader; +import viewfx.view.ViewPath; import viewfx.view.Wizard; import viewfx.view.support.ActivatableViewAndModel; @@ -37,7 +46,8 @@ import javafx.scene.paint.*; import de.jensd.fx.fontawesome.AwesomeDude; import de.jensd.fx.fontawesome.AwesomeIcon; -class AccountSettingsView extends ActivatableViewAndModel { +@FxmlView +public class AccountSettingsView extends ActivatableViewAndModel { private final ViewLoader viewLoader; private final Navigation navigation; @@ -56,51 +66,40 @@ class AccountSettingsView extends ActivatableViewAndModel { @Override public void initialize() { - listener = navigationItems -> { - if (navigationItems != null && - navigationItems.length == 4 && - navigationItems[2] == FxmlView.ACCOUNT_SETTINGS) { - loadView(navigationItems[3]); - selectMainMenuButton(navigationItems[3]); - } + listener = viewPath -> { + if (viewPath.size() != 4 || !viewPath.contains(AccountSettingsView.class)) + return; + + loadView(viewPath.tip()); + selectMainMenuButton(viewPath.tip()); }; ToggleGroup toggleGroup = new ToggleGroup(); - seedWords = new MenuItem(navigation, "Wallet seed", - FxmlView.SEED_WORDS, toggleGroup); - password = new MenuItem(navigation, "Wallet password", - FxmlView.CHANGE_PASSWORD, toggleGroup); - restrictions = new MenuItem(navigation, "Arbitrator selection", - FxmlView.RESTRICTIONS, toggleGroup); - fiatAccount = new MenuItem(navigation, "Payments account(s)", - FxmlView.FIAT_ACCOUNT, toggleGroup); - registration = new MenuItem(navigation, "Renew your account", - FxmlView.REGISTRATION, toggleGroup); + seedWords = new MenuItem(navigation, toggleGroup, "Wallet seed", SeedWordsView.class); + password = new MenuItem(navigation, toggleGroup, "Wallet password", ChangePasswordView.class); + restrictions = new MenuItem(navigation, toggleGroup, "Arbitrator selection", RestrictionsView.class); + fiatAccount = new MenuItem(navigation, toggleGroup, "Payments account(s)", FiatAccountView.class); + registration = new MenuItem(navigation, toggleGroup, "Renew your account", RegistrationView.class); seedWords.setDisable(true); password.setDisable(true); restrictions.setDisable(true); registration.setDisable(true); - leftVBox.getChildren().addAll(seedWords, password, - restrictions, fiatAccount, registration); + leftVBox.getChildren().addAll(seedWords, password, restrictions, fiatAccount, registration); } @Override public void doActivate() { navigation.addListener(listener); - FxmlView[] items = navigation.getCurrentPath(); - if (items.length == 3 && - items[2] == FxmlView.ACCOUNT_SETTINGS) { - navigation.navigateTo(FxmlView.MAIN, FxmlView.ACCOUNT, - FxmlView.ACCOUNT_SETTINGS, FxmlView.FIAT_ACCOUNT); + ViewPath viewPath = navigation.getCurrentPath(); + if (viewPath.size() == 3 && viewPath.indexOf(AccountSettingsView.class) == 2) { + navigation.navigateTo( + ViewPath.to(MainView.class, AccountView.class, AccountSettingsView.class, FiatAccountView.class)); } - else { - if (items.length == 4 && - items[2] == FxmlView.ACCOUNT_SETTINGS) { - loadView(items[3]); - selectMainMenuButton(items[3]); - } + else if (viewPath.size() == 4 && viewPath.indexOf(AccountSettingsView.class) == 2) { + loadView(viewPath.get(3)); + selectMainMenuButton(viewPath.get(3)); } } @@ -109,42 +108,27 @@ class AccountSettingsView extends ActivatableViewAndModel { navigation.removeListener(listener); } - private void loadView(FxmlView navigationItem) { - View view = viewLoader.load(navigationItem.getLocation()); + private void loadView(Class viewClass) { + View view = viewLoader.load(viewClass); content.getChildren().setAll(view.getRoot()); if (view instanceof Wizard.Step) ((Wizard.Step) view).hideWizardNavigation(); } - private void selectMainMenuButton(FxmlView item) { - switch (item) { - case SEED_WORDS: - seedWords.setSelected(true); - break; - case CHANGE_PASSWORD: - password.setSelected(true); - break; - case RESTRICTIONS: - restrictions.setSelected(true); - break; - case FIAT_ACCOUNT: - fiatAccount.setSelected(true); - break; - case REGISTRATION: - registration.setSelected(true); - break; - default: - log.error(item.getLocation() + " is invalid"); - break; - } + private void selectMainMenuButton(Class viewClass) { + if (viewClass == SeedWordsView.class) seedWords.setSelected(true); + else if (viewClass == ChangePasswordView.class) password.setSelected(true); + else if (viewClass == RestrictionsView.class) restrictions.setSelected(true); + else if (viewClass == FiatAccountView.class) fiatAccount.setSelected(true); + else if (viewClass == RegistrationView.class) registration.setSelected(true); + else throw new BitsquareException("Selecting main menu button for " + viewClass + " is not supported"); } } class MenuItem extends ToggleButton { - MenuItem(Navigation navigation, String title, FxmlView navigationItem, - ToggleGroup toggleGroup) { + MenuItem(Navigation navigation, ToggleGroup toggleGroup, String title, Class viewClass) { setToggleGroup(toggleGroup); setText(title); @@ -155,17 +139,17 @@ class MenuItem extends ToggleButton { Label icon = new Label(); icon.setTextFill(Paint.valueOf("#999")); - if (navigationItem.equals(FxmlView.SEED_WORDS)) + if (viewClass == SeedWordsView.class) AwesomeDude.setIcon(icon, AwesomeIcon.INFO_SIGN); - else if (navigationItem.equals(FxmlView.REGISTRATION)) + else if (viewClass == RegistrationView.class) AwesomeDude.setIcon(icon, AwesomeIcon.BRIEFCASE); else AwesomeDude.setIcon(icon, AwesomeIcon.EDIT_SIGN); setGraphic(icon); - setOnAction((event) -> navigation.navigateTo(FxmlView.MAIN, FxmlView.ACCOUNT, - FxmlView.ACCOUNT_SETTINGS, navigationItem)); + setOnAction((event) -> navigation.navigateTo( + ViewPath.to(MainView.class, AccountView.class, AccountSettingsView.class, viewClass))); selectedProperty().addListener((ov, oldValue, newValue) -> { if (newValue) { diff --git a/src/main/java/io/bitsquare/gui/main/account/setup/AccountSetupWizard.java b/src/main/java/io/bitsquare/gui/main/account/setup/AccountSetupWizard.java index ceaf7a4589..e0aef7182a 100644 --- a/src/main/java/io/bitsquare/gui/main/account/setup/AccountSetupWizard.java +++ b/src/main/java/io/bitsquare/gui/main/account/setup/AccountSetupWizard.java @@ -17,16 +17,19 @@ package io.bitsquare.gui.main.account.setup; -import io.bitsquare.gui.FxmlView; import io.bitsquare.gui.Navigation; +import io.bitsquare.gui.main.MainView; +import io.bitsquare.gui.main.account.content.fiat.FiatAccountView; import io.bitsquare.gui.main.account.content.irc.IrcAccountView; import io.bitsquare.gui.main.account.content.password.PasswordView; import io.bitsquare.gui.main.account.content.registration.RegistrationView; import io.bitsquare.gui.main.account.content.restrictions.RestrictionsView; import io.bitsquare.gui.main.account.content.seedwords.SeedWordsView; +import io.bitsquare.gui.main.trade.BuyView; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.View; import viewfx.view.ViewLoader; import viewfx.view.Wizard; @@ -38,7 +41,8 @@ import javafx.scene.control.*; import javafx.scene.image.*; import javafx.scene.layout.*; -class AccountSetupWizard extends ActivatableView implements Wizard { +@FxmlView +public class AccountSetupWizard extends ActivatableView implements Wizard { @FXML VBox leftVBox; @FXML AnchorPane content; @@ -57,54 +61,49 @@ class AccountSetupWizard extends ActivatableView implements Wizard { @Override public void initialize() { - listener = navigationItems -> { - if (navigationItems != null && - navigationItems.length == 4 && - navigationItems[2] == FxmlView.ACCOUNT_SETUP) { + listener = viewPath -> { + if (viewPath.size() != 4 || !viewPath.contains(this.getClass())) + return; - switch (navigationItems[3]) { - case SEED_WORDS: - seedWords.show(); - break; - case ADD_PASSWORD: - seedWords.onCompleted(); - password.show(); - break; - case RESTRICTIONS: - seedWords.onCompleted(); - password.onCompleted(); - restrictions.show(); - break; - case FIAT_ACCOUNT: - seedWords.onCompleted(); - password.onCompleted(); - restrictions.onCompleted(); - fiatAccount.show(); - break; - case REGISTRATION: - seedWords.onCompleted(); - password.onCompleted(); - restrictions.onCompleted(); - fiatAccount.onCompleted(); - registration.show(); - break; - } + Class viewClass = viewPath.tip(); + + if (viewClass == SeedWordsView.class) { + seedWords.show(); + } + else if (viewClass == PasswordView.class) { + seedWords.onCompleted(); + password.show(); + } + else if (viewClass == RestrictionsView.class) { + seedWords.onCompleted(); + password.onCompleted(); + restrictions.show(); + } + else if (viewClass == FiatAccountView.class) { + seedWords.onCompleted(); + password.onCompleted(); + restrictions.onCompleted(); + fiatAccount.show(); + } + else if (viewClass == RegistrationView.class) { + seedWords.onCompleted(); + password.onCompleted(); + restrictions.onCompleted(); + fiatAccount.onCompleted(); + registration.show(); } }; - seedWords = new WizardItem(this, "Backup wallet seed", "Write down the seed word for your wallet", - FxmlView.SEED_WORDS); - password = new WizardItem(this, "Setup password", "Protect your wallet with a password", - FxmlView.ADD_PASSWORD); - restrictions = new WizardItem(this, "Select arbitrators", - "Select which arbitrators you want to use for trading", - FxmlView.RESTRICTIONS); - fiatAccount = new WizardItem(this, " Setup Payments account(s)", - "You need to setup at least one payment account", - FxmlView.FIAT_ACCOUNT); - registration = new WizardItem(this, "Register your account", - "The registration in the Blockchain requires a payment of 0.0002 BTC", - FxmlView.REGISTRATION); + seedWords = new WizardItem(SeedWordsView.class, + "Backup wallet seed", "Write down the seed word for your wallet"); + password = new WizardItem(PasswordView.class, + "Setup password", "Protect your wallet with a password"); + restrictions = new WizardItem(RestrictionsView.class, + "Select arbitrators", "Select which arbitrators you want to use for trading"); + fiatAccount = new WizardItem(FiatAccountView.class, + " Setup Payments account(s)", "You need to setup at least one payment account"); + registration = new WizardItem(RegistrationView.class, + "Register your account", "The registration in the Blockchain requires a payment of 0.0002 BTC"); leftVBox.getChildren().addAll(seedWords, password, restrictions, fiatAccount, registration); @@ -149,83 +148,77 @@ class AccountSetupWizard extends ActivatableView implements Wizard { if (navigation.getReturnPath() != null) navigation.navigateTo(navigation.getReturnPath()); else - navigation.navigateTo(FxmlView.MAIN, FxmlView.BUY); + navigation.navigateTo(MainView.class, BuyView.class); } } - protected void loadView(FxmlView navigationItem) { - View view = viewLoader.load(navigationItem.getLocation()); + protected void loadView(Class viewClass) { + View view = viewLoader.load(viewClass); content.getChildren().setAll(view.getRoot()); if (view instanceof Wizard.Step) ((Step) view).setParent(this); } -} -class WizardItem extends HBox { + private class WizardItem extends HBox { - private final ImageView imageView; - private final Label titleLabel; - private final Label subTitleLabel; - private final AccountSetupWizard parent; - private final FxmlView navigationItem; + private final ImageView imageView; + private final Label titleLabel; + private final Label subTitleLabel; + private final Class viewClass; - WizardItem(AccountSetupWizard parent, String title, String subTitle, - FxmlView navigationItem) { - this.parent = parent; - this.navigationItem = navigationItem; + WizardItem(Class viewClass, String title, String subTitle) { + this.viewClass = viewClass; - setId("wizard-item-background-deactivated"); - setSpacing(5); - setPrefWidth(200); + setId("wizard-item-background-deactivated"); + setSpacing(5); + setPrefWidth(200); - imageView = new ImageView(); - imageView.setId("image-arrow-grey"); - imageView.setFitHeight(15); - imageView.setFitWidth(20); - imageView.setPickOnBounds(true); - imageView.setMouseTransparent(true); - HBox.setMargin(imageView, new Insets(8, 0, 0, 8)); + imageView = new ImageView(); + imageView.setId("image-arrow-grey"); + imageView.setFitHeight(15); + imageView.setFitWidth(20); + imageView.setPickOnBounds(true); + imageView.setMouseTransparent(true); + HBox.setMargin(imageView, new Insets(8, 0, 0, 8)); - titleLabel = new Label(title); - titleLabel.setId("wizard-title-deactivated"); - titleLabel.setLayoutX(7); - titleLabel.setMouseTransparent(true); + titleLabel = new Label(title); + titleLabel.setId("wizard-title-deactivated"); + titleLabel.setLayoutX(7); + titleLabel.setMouseTransparent(true); - subTitleLabel = new Label(subTitle); - subTitleLabel.setId("wizard-sub-title-deactivated"); - subTitleLabel.setLayoutX(40); - subTitleLabel.setLayoutY(33); - subTitleLabel.setMaxWidth(250); - subTitleLabel.setWrapText(true); - subTitleLabel.setMouseTransparent(true); + subTitleLabel = new Label(subTitle); + subTitleLabel.setId("wizard-sub-title-deactivated"); + subTitleLabel.setLayoutX(40); + subTitleLabel.setLayoutY(33); + subTitleLabel.setMaxWidth(250); + subTitleLabel.setWrapText(true); + subTitleLabel.setMouseTransparent(true); - final VBox vBox = new VBox(); - vBox.setSpacing(1); - HBox.setMargin(vBox, new Insets(5, 0, 8, 0)); - vBox.setMouseTransparent(true); - vBox.getChildren().addAll(titleLabel, subTitleLabel); + final VBox vBox = new VBox(); + vBox.setSpacing(1); + HBox.setMargin(vBox, new Insets(5, 0, 8, 0)); + vBox.setMouseTransparent(true); + vBox.getChildren().addAll(titleLabel, subTitleLabel); - getChildren().addAll(imageView, vBox); - } + getChildren().addAll(imageView, vBox); + } - void show() { - parent.loadView(navigationItem); - /* navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ACCOUNT, Navigation - .Item.ACCOUNT_SETUP, - navigationItem);*/ + void show() { + loadView(viewClass); - setId("wizard-item-background-active"); - imageView.setId("image-arrow-blue"); - titleLabel.setId("wizard-title-active"); - subTitleLabel.setId("wizard-sub-title-active"); - } + setId("wizard-item-background-active"); + imageView.setId("image-arrow-blue"); + titleLabel.setId("wizard-title-active"); + subTitleLabel.setId("wizard-sub-title-active"); + } - void onCompleted() { - setId("wizard-item-background-completed"); - imageView.setId("image-tick"); - titleLabel.setId("wizard-title-completed"); - subTitleLabel.setId("wizard-sub-title-completed"); + void onCompleted() { + setId("wizard-item-background-completed"); + imageView.setId("image-tick"); + titleLabel.setId("wizard-title-completed"); + subTitleLabel.setId("wizard-sub-title-completed"); + } } } diff --git a/src/main/java/io/bitsquare/gui/main/funds/FundsView.java b/src/main/java/io/bitsquare/gui/main/funds/FundsView.java index 516228be5d..a77f43d4e1 100644 --- a/src/main/java/io/bitsquare/gui/main/funds/FundsView.java +++ b/src/main/java/io/bitsquare/gui/main/funds/FundsView.java @@ -17,12 +17,15 @@ package io.bitsquare.gui.main.funds; -import io.bitsquare.gui.FxmlView; import io.bitsquare.gui.Navigation; +import io.bitsquare.gui.main.MainView; +import io.bitsquare.gui.main.funds.transactions.TransactionsView; +import io.bitsquare.gui.main.funds.withdrawal.WithdrawalView; import javax.inject.Inject; import viewfx.model.Activatable; +import viewfx.view.FxmlView; import viewfx.view.View; import viewfx.view.ViewLoader; import viewfx.view.support.ActivatableViewAndModel; @@ -31,7 +34,8 @@ import javafx.beans.value.ChangeListener; import javafx.fxml.FXML; import javafx.scene.control.*; -class FundsView extends ActivatableViewAndModel { +@FxmlView +public class FundsView extends ActivatableViewAndModel { @FXML Tab withdrawalTab, transactionsTab; @@ -43,24 +47,23 @@ class FundsView extends ActivatableViewAndModel { private final Navigation navigation; @Inject - FundsView(ViewLoader viewLoader, Navigation navigation) { + public FundsView(ViewLoader viewLoader, Navigation navigation) { this.viewLoader = viewLoader; this.navigation = navigation; } @Override public void initialize() { - navigationListener = navigationItems -> { - if (navigationItems != null && navigationItems.length == 3 - && navigationItems[1] == FxmlView.FUNDS) - loadView(navigationItems[2]); + navigationListener = viewPath -> { + if (viewPath.size() == 3 && viewPath.indexOf(FundsView.class) == 1) + loadView(viewPath.tip()); }; tabChangeListener = (ov, oldValue, newValue) -> { if (newValue == withdrawalTab) - navigation.navigateTo(FxmlView.MAIN, FxmlView.FUNDS, FxmlView.WITHDRAWAL); + navigation.navigateTo(MainView.class, FundsView.class, WithdrawalView.class); else if (newValue == transactionsTab) - navigation.navigateTo(FxmlView.MAIN, FxmlView.FUNDS, FxmlView.TRANSACTIONS); + navigation.navigateTo(MainView.class, FundsView.class, TransactionsView.class); }; } @@ -70,9 +73,9 @@ class FundsView extends ActivatableViewAndModel { navigation.addListener(navigationListener); if (root.getSelectionModel().getSelectedItem() == transactionsTab) - navigation.navigateTo(FxmlView.MAIN, FxmlView.FUNDS, FxmlView.TRANSACTIONS); + navigation.navigateTo(MainView.class, FundsView.class, TransactionsView.class); else - navigation.navigateTo(FxmlView.MAIN, FxmlView.FUNDS, FxmlView.WITHDRAWAL); + navigation.navigateTo(MainView.class, FundsView.class, WithdrawalView.class); } @Override @@ -81,20 +84,17 @@ class FundsView extends ActivatableViewAndModel { navigation.removeListener(navigationListener); } - private void loadView(FxmlView navigationItem) { + private void loadView(Class viewClass) { // we want to get activate/deactivate called, so we remove the old view on tab change if (currentTab != null) currentTab.setContent(null); - View view = viewLoader.load(navigationItem.getLocation()); - switch (navigationItem) { - case WITHDRAWAL: - currentTab = withdrawalTab; - break; - case TRANSACTIONS: - currentTab = transactionsTab; - break; - } + if (viewClass == WithdrawalView.class) + currentTab = withdrawalTab; + if (viewClass == TransactionsView.class) + currentTab = transactionsTab; + + View view = viewLoader.load(viewClass); currentTab.setContent(view.getRoot()); root.getSelectionModel().select(currentTab); } diff --git a/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.java b/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.java index 5c61c1add5..9dfb002275 100644 --- a/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.java +++ b/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.java @@ -28,6 +28,7 @@ import java.util.stream.Collectors; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.ActivatableViewAndModel; import javafx.beans.property.ReadOnlyObjectWrapper; @@ -37,7 +38,8 @@ import javafx.fxml.FXML; import javafx.scene.control.*; import javafx.util.Callback; -class TransactionsView extends ActivatableViewAndModel { +@FxmlView +public class TransactionsView extends ActivatableViewAndModel { @FXML TableView table; @FXML TableColumn dateColumn, addressColumn, amountColumn, typeColumn, diff --git a/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java b/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java index 5b911fe029..d215db3de2 100644 --- a/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java +++ b/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java @@ -38,6 +38,7 @@ import java.util.stream.Collectors; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.ActivatableViewAndModel; import javafx.beans.property.ReadOnlyObjectWrapper; @@ -54,7 +55,8 @@ import org.controlsfx.control.action.Action; import org.jetbrains.annotations.NotNull; -class WithdrawalView extends ActivatableViewAndModel { +@FxmlView +public class WithdrawalView extends ActivatableViewAndModel { @FXML TableView table; @FXML Button addNewAddressButton; diff --git a/src/main/java/io/bitsquare/gui/main/home/HomeView.java b/src/main/java/io/bitsquare/gui/main/home/HomeView.java index 0318fc7cd3..f507f2a25c 100644 --- a/src/main/java/io/bitsquare/gui/main/home/HomeView.java +++ b/src/main/java/io/bitsquare/gui/main/home/HomeView.java @@ -17,9 +17,11 @@ package io.bitsquare.gui.main.home; +import viewfx.view.FxmlView; import viewfx.view.support.AbstractView; // home is just hosting the arbiters buttons yet, but that's just for dev, not clear yet what will be in home, // probably overview, event history, news, charts,... -> low prio -class HomeView extends AbstractView { +@FxmlView +public class HomeView extends AbstractView { } diff --git a/src/main/java/io/bitsquare/gui/main/msg/MsgView.java b/src/main/java/io/bitsquare/gui/main/msg/MsgView.java index 0774d163c8..9f400386cd 100644 --- a/src/main/java/io/bitsquare/gui/main/msg/MsgView.java +++ b/src/main/java/io/bitsquare/gui/main/msg/MsgView.java @@ -17,9 +17,11 @@ package io.bitsquare.gui.main.msg; +import viewfx.view.FxmlView; import viewfx.view.support.AbstractView; // will be probably only used for arbitration communication, will be renamed and the icon changed -class MsgView extends AbstractView { +@FxmlView +public class MsgView extends AbstractView { } diff --git a/src/main/java/io/bitsquare/gui/main/portfolio/PortfolioView.java b/src/main/java/io/bitsquare/gui/main/portfolio/PortfolioView.java index 0cfe1c1d15..cca894f583 100644 --- a/src/main/java/io/bitsquare/gui/main/portfolio/PortfolioView.java +++ b/src/main/java/io/bitsquare/gui/main/portfolio/PortfolioView.java @@ -17,13 +17,17 @@ package io.bitsquare.gui.main.portfolio; -import io.bitsquare.gui.FxmlView; import io.bitsquare.gui.Navigation; +import io.bitsquare.gui.main.MainView; +import io.bitsquare.gui.main.portfolio.closed.ClosedTradesView; +import io.bitsquare.gui.main.portfolio.offer.OffersView; +import io.bitsquare.gui.main.portfolio.pending.PendingTradesView; import io.bitsquare.trade.TradeManager; import javax.inject.Inject; import viewfx.model.Activatable; +import viewfx.view.FxmlView; import viewfx.view.View; import viewfx.view.ViewLoader; import viewfx.view.support.ActivatableViewAndModel; @@ -32,7 +36,8 @@ import javafx.beans.value.ChangeListener; import javafx.fxml.FXML; import javafx.scene.control.*; -class PortfolioView extends ActivatableViewAndModel { +@FxmlView +public class PortfolioView extends ActivatableViewAndModel { @FXML Tab offersTab, openTradesTab, closedTradesTab; @@ -53,20 +58,18 @@ class PortfolioView extends ActivatableViewAndModel { @Override public void initialize() { - navigationListener = navigationItems -> { - if (navigationItems != null && navigationItems.length == 3 - && navigationItems[1] == FxmlView.PORTFOLIO) - loadView(navigationItems[2]); + navigationListener = viewPath -> { + if (viewPath.size() == 3 && viewPath.indexOf(PortfolioView.class) == 1) + loadView(viewPath.tip()); }; tabChangeListener = (ov, oldValue, newValue) -> { if (newValue == offersTab) - navigation.navigateTo(FxmlView.MAIN, FxmlView.PORTFOLIO, FxmlView.OFFERS); + navigation.navigateTo(MainView.class, PortfolioView.class, OffersView.class); else if (newValue == openTradesTab) - navigation.navigateTo(FxmlView.MAIN, FxmlView.PORTFOLIO, - FxmlView.PENDING_TRADES); + navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class); else if (newValue == closedTradesTab) - navigation.navigateTo(FxmlView.MAIN, FxmlView.PORTFOLIO, FxmlView.CLOSED_TRADES); + navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class); }; } @@ -76,9 +79,9 @@ class PortfolioView extends ActivatableViewAndModel { navigation.addListener(navigationListener); if (tradeManager.getPendingTrades().size() == 0) - navigation.navigateTo(FxmlView.MAIN, FxmlView.PORTFOLIO, FxmlView.OFFERS); + navigation.navigateTo(MainView.class, PortfolioView.class, OffersView.class); else - navigation.navigateTo(FxmlView.MAIN, FxmlView.PORTFOLIO, FxmlView.PENDING_TRADES); + navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class); } @Override @@ -88,24 +91,19 @@ class PortfolioView extends ActivatableViewAndModel { currentTab = null; } - private void loadView(FxmlView navigationItem) { - + private void loadView(Class viewClass) { // we want to get activate/deactivate called, so we remove the old view on tab change if (currentTab != null) currentTab.setContent(null); - View view = viewLoader.load(navigationItem.getLocation()); - switch (navigationItem) { - case OFFERS: + if (viewClass == OffersView.class) currentTab = offersTab; - break; - case PENDING_TRADES: + if (viewClass == PendingTradesView.class) currentTab = openTradesTab; - break; - case CLOSED_TRADES: + if (viewClass == ClosedTradesView.class) currentTab = closedTradesTab; - break; - } + + View view = viewLoader.load(viewClass); currentTab.setContent(view.getRoot()); root.getSelectionModel().select(currentTab); } diff --git a/src/main/java/io/bitsquare/gui/main/portfolio/closed/ClosedTradesView.java b/src/main/java/io/bitsquare/gui/main/portfolio/closed/ClosedTradesView.java index dc02adfe43..8cd4cce04e 100644 --- a/src/main/java/io/bitsquare/gui/main/portfolio/closed/ClosedTradesView.java +++ b/src/main/java/io/bitsquare/gui/main/portfolio/closed/ClosedTradesView.java @@ -21,6 +21,7 @@ import io.bitsquare.gui.components.Popups; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.ActivatableViewAndModel; import javafx.beans.property.ReadOnlyObjectWrapper; @@ -29,7 +30,8 @@ import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.util.Callback; -class ClosedTradesView extends ActivatableViewAndModel { +@FxmlView +public class ClosedTradesView extends ActivatableViewAndModel { @FXML TableView table; @FXML TableColumn priceColumn, amountColumn, volumeColumn, diff --git a/src/main/java/io/bitsquare/gui/main/portfolio/offer/OffersView.java b/src/main/java/io/bitsquare/gui/main/portfolio/offer/OffersView.java index 10fad004d5..947665cc0e 100644 --- a/src/main/java/io/bitsquare/gui/main/portfolio/offer/OffersView.java +++ b/src/main/java/io/bitsquare/gui/main/portfolio/offer/OffersView.java @@ -22,6 +22,7 @@ import io.bitsquare.util.Utilities; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.ActivatableViewAndModel; import javafx.beans.property.ReadOnlyObjectWrapper; @@ -31,7 +32,8 @@ import javafx.scene.image.*; import javafx.scene.layout.*; import javafx.util.Callback; -class OffersView extends ActivatableViewAndModel { +@FxmlView +public class OffersView extends ActivatableViewAndModel { @FXML TableView table; @FXML TableColumn priceColumn, amountColumn, volumeColumn, diff --git a/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.java b/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.java index c4d477e04c..226e0d8267 100644 --- a/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.java +++ b/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.java @@ -17,7 +17,6 @@ package io.bitsquare.gui.main.portfolio.pending; -import io.bitsquare.gui.FxmlView; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.components.InfoDisplay; import io.bitsquare.gui.components.InputTextField; @@ -27,8 +26,11 @@ import io.bitsquare.gui.components.TitledGroupBg; import io.bitsquare.gui.components.TxIdTextField; import io.bitsquare.gui.components.processbar.ProcessStepBar; import io.bitsquare.gui.components.processbar.ProcessStepItem; +import io.bitsquare.gui.main.MainView; import io.bitsquare.gui.main.help.Help; import io.bitsquare.gui.main.help.HelpId; +import io.bitsquare.gui.main.portfolio.PortfolioView; +import io.bitsquare.gui.main.portfolio.closed.ClosedTradesView; import io.bitsquare.locale.BSResources; import io.bitsquare.util.Utilities; @@ -41,6 +43,7 @@ import java.util.List; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.ActivatableViewAndModel; import javafx.application.Platform; @@ -54,7 +57,8 @@ import javafx.scene.layout.*; import javafx.util.Callback; import javafx.util.StringConverter; -class PendingTradesView extends ActivatableViewAndModel { +@FxmlView +public class PendingTradesView extends ActivatableViewAndModel { @FXML GridPane gridPane; @FXML ScrollPane scrollPane; @@ -180,9 +184,7 @@ class PendingTradesView extends ActivatableViewAndModel - navigation.navigateTo(FxmlView.MAIN, FxmlView.PORTFOLIO, - FxmlView.CLOSED_TRADES)); + Platform.runLater(() -> navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class)); } @FXML diff --git a/src/main/java/io/bitsquare/gui/main/settings/SettingsView.java b/src/main/java/io/bitsquare/gui/main/settings/SettingsView.java index 6463fe4678..c0824d195a 100644 --- a/src/main/java/io/bitsquare/gui/main/settings/SettingsView.java +++ b/src/main/java/io/bitsquare/gui/main/settings/SettingsView.java @@ -17,13 +17,16 @@ package io.bitsquare.gui.main.settings; -import io.bitsquare.gui.FxmlView; import io.bitsquare.gui.Navigation; +import io.bitsquare.gui.main.MainView; +import io.bitsquare.gui.main.settings.application.PreferencesView; +import io.bitsquare.gui.main.settings.network.NetworkSettingsView; import io.bitsquare.settings.Preferences; import javax.inject.Inject; import viewfx.model.Activatable; +import viewfx.view.FxmlView; import viewfx.view.View; import viewfx.view.ViewLoader; import viewfx.view.support.ActivatableViewAndModel; @@ -32,7 +35,8 @@ import javafx.beans.value.ChangeListener; import javafx.fxml.FXML; import javafx.scene.control.*; -class SettingsView extends ActivatableViewAndModel { +@FxmlView +public class SettingsView extends ActivatableViewAndModel { @FXML Tab preferencesTab, networkSettingsTab; @@ -52,19 +56,16 @@ class SettingsView extends ActivatableViewAndModel { @Override public void initialize() { - navigationListener = navigationItems -> { - if (navigationItems != null && navigationItems.length == 3 - && navigationItems[1] == FxmlView.SETTINGS) - loadView(navigationItems[2]); + navigationListener = viewPath -> { + if (viewPath.size() == 3 && viewPath.indexOf(SettingsView.class) == 1) + loadView(viewPath.tip()); }; tabChangeListener = (ov, oldValue, newValue) -> { if (newValue == preferencesTab) - navigation.navigateTo(FxmlView.MAIN, FxmlView.SETTINGS, - FxmlView.PREFERENCES); + navigation.navigateTo(MainView.class, SettingsView.class, PreferencesView.class); else if (newValue == networkSettingsTab) - navigation.navigateTo(FxmlView.MAIN, FxmlView.SETTINGS, - FxmlView.NETWORK_SETTINGS); + navigation.navigateTo(MainView.class, SettingsView.class, NetworkSettingsView.class); }; } @@ -74,13 +75,9 @@ class SettingsView extends ActivatableViewAndModel { navigation.addListener(navigationListener); if (root.getSelectionModel().getSelectedItem() == preferencesTab) - navigation.navigateTo(FxmlView.MAIN, - FxmlView.SETTINGS, - FxmlView.PREFERENCES); + navigation.navigateTo(MainView.class, SettingsView.class, PreferencesView.class); else - navigation.navigateTo(FxmlView.MAIN, - FxmlView.SETTINGS, - FxmlView.NETWORK_SETTINGS); + navigation.navigateTo(MainView.class, SettingsView.class, NetworkSettingsView.class); } @Override @@ -89,19 +86,17 @@ class SettingsView extends ActivatableViewAndModel { navigation.removeListener(navigationListener); } - private void loadView(FxmlView navigationItem) { - View view = viewLoader.load(navigationItem.getLocation()); + private void loadView(Class viewClass) { final Tab tab; - switch (navigationItem) { - case PREFERENCES: - tab = preferencesTab; - break; - case NETWORK_SETTINGS: - tab = networkSettingsTab; - break; - default: - throw new IllegalArgumentException("navigation item of type " + navigationItem + " is not allowed"); - } + + if (viewClass == PreferencesView.class) + tab = preferencesTab; + else if (viewClass == NetworkSettingsView.class) + tab = networkSettingsTab; + else + throw new IllegalArgumentException("Navigation to " + viewClass + " is not supported"); + + View view = viewLoader.load(viewClass); tab.setContent(view.getRoot()); root.getSelectionModel().select(tab); } diff --git a/src/main/java/io/bitsquare/gui/main/settings/application/PreferencesView.java b/src/main/java/io/bitsquare/gui/main/settings/application/PreferencesView.java index 101ef41c47..c694fa6ec8 100644 --- a/src/main/java/io/bitsquare/gui/main/settings/application/PreferencesView.java +++ b/src/main/java/io/bitsquare/gui/main/settings/application/PreferencesView.java @@ -19,13 +19,15 @@ package io.bitsquare.gui.main.settings.application; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.ActivatableViewAndModel; import javafx.fxml.FXML; import javafx.scene.control.*; import javafx.scene.layout.*; -class PreferencesView extends ActivatableViewAndModel { +@FxmlView +public class PreferencesView extends ActivatableViewAndModel { @FXML ComboBox btcDenominationComboBox; @FXML CheckBox useAnimationsCheckBox, useEffectsCheckBox; diff --git a/src/main/java/io/bitsquare/gui/main/settings/network/NetworkSettingsView.java b/src/main/java/io/bitsquare/gui/main/settings/network/NetworkSettingsView.java index 2b8066f63a..e19d37f733 100644 --- a/src/main/java/io/bitsquare/gui/main/settings/network/NetworkSettingsView.java +++ b/src/main/java/io/bitsquare/gui/main/settings/network/NetworkSettingsView.java @@ -22,12 +22,14 @@ import io.bitsquare.network.ClientNode; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.InitializableView; import javafx.fxml.FXML; import javafx.scene.control.*; -class NetworkSettingsView extends InitializableView { +@FxmlView +public class NetworkSettingsView extends InitializableView { private final String bitcoinNetworkValue; private final ClientNode clientNode; diff --git a/src/main/java/io/bitsquare/gui/main/trade/BuyView.java b/src/main/java/io/bitsquare/gui/main/trade/BuyView.java index 176d08e8be..b85f5f218d 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/BuyView.java +++ b/src/main/java/io/bitsquare/gui/main/trade/BuyView.java @@ -21,9 +21,11 @@ import io.bitsquare.gui.Navigation; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.CachingViewLoader; -class BuyView extends TradeView { +@FxmlView +public class BuyView extends TradeView { @Inject public BuyView(CachingViewLoader viewLoader, Navigation navigation) { diff --git a/src/main/java/io/bitsquare/gui/main/trade/SellView.java b/src/main/java/io/bitsquare/gui/main/trade/SellView.java index 525a67f5b0..e22d620275 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/SellView.java +++ b/src/main/java/io/bitsquare/gui/main/trade/SellView.java @@ -21,9 +21,11 @@ import io.bitsquare.gui.Navigation; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.CachingViewLoader; -class SellView extends TradeView { +@FxmlView +public class SellView extends TradeView { @Inject public SellView(CachingViewLoader viewLoader, Navigation navigation) { diff --git a/src/main/java/io/bitsquare/gui/main/trade/TradeView.java b/src/main/java/io/bitsquare/gui/main/trade/TradeView.java index f618145216..a44ea8ec57 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/TradeView.java +++ b/src/main/java/io/bitsquare/gui/main/trade/TradeView.java @@ -17,9 +17,9 @@ package io.bitsquare.gui.main.trade; -import io.bitsquare.gui.FxmlView; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.components.InputTextField; +import io.bitsquare.gui.main.MainView; import io.bitsquare.gui.main.trade.createoffer.CreateOfferView; import io.bitsquare.gui.main.trade.offerbook.OfferBookView; import io.bitsquare.gui.main.trade.takeoffer.TakeOfferView; @@ -33,15 +33,16 @@ import java.util.List; import viewfx.view.View; import viewfx.view.ViewLoader; -import viewfx.view.support.CachingViewLoader; import viewfx.view.support.ActivatableView; +import viewfx.view.support.CachingViewLoader; import javafx.application.Platform; import javafx.collections.ListChangeListener; import javafx.scene.*; import javafx.scene.control.*; -public class TradeView extends ActivatableView { + +public abstract class TradeView extends ActivatableView { private OfferBookView offerBookView; private CreateOfferView createOfferView; @@ -49,28 +50,25 @@ public class TradeView extends ActivatableView { private Node createOfferRoot; private Node takeOfferRoot; private Navigation.Listener listener; - private FxmlView navigationItem; - private Direction direction; private Coin amount; private Fiat price; private Offer offer; private final ViewLoader viewLoader; private final Navigation navigation; + private final Direction direction; protected TradeView(CachingViewLoader viewLoader, Navigation navigation) { this.viewLoader = viewLoader; this.navigation = navigation; + this.direction = (this instanceof BuyView) ? Direction.BUY : Direction.SELL; } @Override protected void initialize() { - direction = (this instanceof BuyView) ? Direction.BUY : Direction.SELL; - navigationItem = (direction == Direction.BUY) ? FxmlView.BUY : FxmlView.SELL; - - listener = navigationItems -> { - if (navigationItems != null && navigationItems.length == 3 && navigationItems[1] == navigationItem) { - loadView(navigationItems[2]); + listener = viewPath -> { + if (viewPath.size() == 3 && viewPath.indexOf(this.getClass()) == 1) { + loadView(viewPath.tip()); } }; } @@ -98,7 +96,7 @@ public class TradeView extends ActivatableView { }); navigation.addListener(listener); - navigation.navigateTo(FxmlView.MAIN, navigationItem, FxmlView.OFFER_BOOK); + navigation.navigateTo(MainView.class, this.getClass(), OfferBookView.class); } @Override @@ -110,21 +108,21 @@ public class TradeView extends ActivatableView { public void createOffer(Coin amount, Fiat price) { this.amount = amount; this.price = price; - navigation.navigateTo(FxmlView.MAIN, navigationItem, FxmlView.CREATE_OFFER); + navigation.navigateTo(MainView.class, this.getClass(), CreateOfferView.class); } public void takeOffer(Coin amount, Fiat price, Offer offer) { this.amount = amount; this.price = price; this.offer = offer; - navigation.navigateTo(FxmlView.MAIN, navigationItem, FxmlView.TAKE_OFFER); + navigation.navigateTo(MainView.class, this.getClass(), TakeOfferView.class); } - private View loadView(FxmlView navigationItem) { + private View loadView(Class viewClass) { TabPane tabPane = root; - if (navigationItem == FxmlView.OFFER_BOOK && offerBookView == null) { + if (viewClass == OfferBookView.class && offerBookView == null) { // Offerbook must not be cached by ViewLoader as we use 2 instances for sell and buy screens. - View view = viewLoader.load(navigationItem.getLocation()); + View view = viewLoader.load(viewClass); final Tab tab = new Tab(direction == Direction.BUY ? "Buy Bitcoin" : "Sell Bitcoin"); tab.setClosable(false); tab.setContent(view.getRoot()); @@ -136,10 +134,10 @@ public class TradeView extends ActivatableView { return offerBookView; } - else if (navigationItem == FxmlView.CREATE_OFFER && createOfferView == null) { + else if (viewClass == CreateOfferView.class && createOfferView == null) { // CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times // in different graphs - View view = viewLoader.load(navigationItem.getLocation()); + View view = viewLoader.load(viewClass); createOfferView = (CreateOfferView) view; createOfferView.initWithData(direction, amount, price); createOfferRoot = view.getRoot(); @@ -150,11 +148,11 @@ public class TradeView extends ActivatableView { tabPane.getSelectionModel().select(tab); return createOfferView; } - else if (navigationItem == FxmlView.TAKE_OFFER && takeOfferView == null && + else if (viewClass == TakeOfferView.class && takeOfferView == null && offer != null) { // CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times // in different graphs - View view = viewLoader.load(FxmlView.TAKE_OFFER.getLocation()); + View view = viewLoader.load(TakeOfferView.class); takeOfferView = (TakeOfferView) view; takeOfferView.initWithData(direction, amount, offer); takeOfferRoot = view.getRoot(); @@ -173,14 +171,14 @@ public class TradeView extends ActivatableView { offerBookView.enableCreateOfferButton(); // update the navigation state - navigation.navigateTo(FxmlView.MAIN, navigationItem, FxmlView.OFFER_BOOK); + navigation.navigateTo(MainView.class, this.getClass(), OfferBookView.class); } private void onTakeOfferViewRemoved() { takeOfferView = null; // update the navigation state - navigation.navigateTo(FxmlView.MAIN, navigationItem, FxmlView.OFFER_BOOK); + navigation.navigateTo(MainView.class, this.getClass(), OfferBookView.class); } } diff --git a/src/main/java/io/bitsquare/gui/main/trade/createoffer/CreateOfferView.java b/src/main/java/io/bitsquare/gui/main/trade/createoffer/CreateOfferView.java index 67c96c4527..47ced99999 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/createoffer/CreateOfferView.java +++ b/src/main/java/io/bitsquare/gui/main/trade/createoffer/CreateOfferView.java @@ -17,7 +17,6 @@ package io.bitsquare.gui.main.trade.createoffer; -import io.bitsquare.gui.FxmlView; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.OverlayManager; import io.bitsquare.gui.components.AddressTextField; @@ -26,8 +25,14 @@ import io.bitsquare.gui.components.InfoDisplay; import io.bitsquare.gui.components.InputTextField; import io.bitsquare.gui.components.Popups; import io.bitsquare.gui.components.TitledGroupBg; +import io.bitsquare.gui.main.MainView; +import io.bitsquare.gui.main.account.AccountView; +import io.bitsquare.gui.main.account.content.restrictions.RestrictionsView; +import io.bitsquare.gui.main.account.settings.AccountSettingsView; import io.bitsquare.gui.main.help.Help; import io.bitsquare.gui.main.help.HelpId; +import io.bitsquare.gui.main.portfolio.PortfolioView; +import io.bitsquare.gui.main.portfolio.offer.OffersView; import io.bitsquare.gui.util.ImageUtil; import io.bitsquare.locale.BSResources; import io.bitsquare.offer.Direction; @@ -40,6 +45,7 @@ import java.util.List; import javax.inject.Inject; +import viewfx.view.FxmlView; import viewfx.view.support.ActivatableViewAndModel; import javafx.beans.property.BooleanProperty; @@ -67,6 +73,7 @@ import static javafx.beans.binding.Bindings.createStringBinding; // TODO Implement other positioning method in InoutTextField to display it over the field instead of right side // priceAmountHBox is too large after redesign as to be used as layoutReference. +@FxmlView public class CreateOfferView extends ActivatableViewAndModel { @FXML ScrollPane scrollPane; @@ -222,17 +229,14 @@ public class CreateOfferView extends ActivatableViewAndModel implements ChildView { @@ -204,8 +210,7 @@ public class OfferBookView extends ActivatableViewAndModel { @FXML ScrollPane scrollPane; @@ -281,8 +285,7 @@ public class TakeOfferView extends ActivatableViewAndModel. + */ + +package viewfx; + +public class ViewfxException extends RuntimeException { + + public ViewfxException(Throwable cause, String format, Object... args) { + super(String.format(format, args), cause); + } +} diff --git a/src/main/java/viewfx/view/FxmlView.java b/src/main/java/viewfx/view/FxmlView.java new file mode 100644 index 0000000000..b8c046c55c --- /dev/null +++ b/src/main/java/viewfx/view/FxmlView.java @@ -0,0 +1,51 @@ +/* + * 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 viewfx.view; + +import java.util.function.Function; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.springframework.util.ClassUtils; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface FxmlView { + + /** + * The location of the FXML file associated with annotated {@link View} class. By default the location will be + * determined by {@link #convention()}. + */ + String location() default ""; + + /** + * The function used to determine the location of the FXML file associated with the annotated {@link View} class. + * By default it is the fully-qualified view class name, converted to a resource path, replacing the + * {@code .class} suffix replaced with {@code .fxml}. + */ + Class, String>> convention() default DefaultFxmlPathConvention.class; + + static class DefaultFxmlPathConvention implements Function, String> { + @Override + public String apply(Class viewClass) { + return ClassUtils.convertClassNameToResourcePath(viewClass.getName()).concat(".fxml"); + } + } +} diff --git a/src/main/java/viewfx/view/ViewPath.java b/src/main/java/viewfx/view/ViewPath.java new file mode 100644 index 0000000000..f2ac8cfc17 --- /dev/null +++ b/src/main/java/viewfx/view/ViewPath.java @@ -0,0 +1,46 @@ +/* + * 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 viewfx.view; + +import java.util.ArrayList; +import java.util.Arrays; + +public class ViewPath extends ArrayList> { + + public ViewPath() { + } + + public static ViewPath to(Class... elements) { + ViewPath path = new ViewPath(); + path.addAll(Arrays.asList(elements)); + return path; + } + + public static ViewPath from(ViewPath original) { + ViewPath path = new ViewPath(); + path.addAll(original); + return path; + } + + public Class tip() { + if (size() == 0) + return null; + + return get(size()-1); + } +} diff --git a/src/main/java/viewfx/view/support/fxml/FxmlViewLoader.java b/src/main/java/viewfx/view/support/fxml/FxmlViewLoader.java index f5231532a3..997a894dc1 100644 --- a/src/main/java/viewfx/view/support/fxml/FxmlViewLoader.java +++ b/src/main/java/viewfx/view/support/fxml/FxmlViewLoader.java @@ -25,12 +25,16 @@ import java.util.ResourceBundle; import javax.inject.Inject; +import viewfx.ViewfxException; +import viewfx.view.FxmlView; import viewfx.view.View; import viewfx.view.ViewFactory; import viewfx.view.ViewLoader; import javafx.fxml.FXMLLoader; +import org.springframework.core.annotation.AnnotationUtils; + public class FxmlViewLoader implements ViewLoader { private final ViewFactory viewFactory; @@ -42,20 +46,41 @@ public class FxmlViewLoader implements ViewLoader { this.resourceBundle = resourceBundle; } - public View load(Object location) { - if (!(location instanceof URL)) - throw new IllegalArgumentException("FXML view locations must be of type URL"); + public View load(Class clazz) { + if (!View.class.isAssignableFrom(clazz)) + throw new IllegalArgumentException("Class must be of generic type Class: " + clazz); - URL url = (URL) location; + @SuppressWarnings("unchecked") + Class viewClass = (Class) clazz; + FxmlView fxmlView = AnnotationUtils.getAnnotation(viewClass, FxmlView.class); + try { + String path = fxmlView.convention().newInstance().apply(viewClass); + return load(viewClass.getClassLoader().getResource(path)); + } catch (InstantiationException | IllegalAccessException ex) { + throw new ViewfxException(ex, "Failed to load View from class %s", viewClass); + } + } + + public View load(URL url) { try { FXMLLoader loader = new FXMLLoader(url, resourceBundle); loader.setControllerFactory(viewFactory); loader.load(); return loader.getController(); } catch (IOException ex) { - throw new RuntimeException("Failed to load View at location " + url, ex); + throw new ViewfxException(ex, "Failed to load View at location %s", url); } } + + public View load(Object location) { + if (location instanceof URL) + return load((URL) location); + if (location instanceof Class) + return load((Class) location); + + throw new IllegalArgumentException("Argument is not of type URL or Class: " + location); + + } } diff --git a/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java b/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java index 4413e48d28..b15d669048 100644 --- a/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java +++ b/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java @@ -17,18 +17,21 @@ package io.bitsquare.app.gui; -import io.bitsquare.BitsquareException; import io.bitsquare.app.BitsquareEnvironment; -import io.bitsquare.gui.FxmlView; +import io.bitsquare.gui.main.funds.FundsView; import io.bitsquare.locale.BSResources; import com.google.inject.Guice; import com.google.inject.Injector; +import java.io.File; + import java.net.MalformedURLException; +import java.net.URL; import java.util.ResourceBundle; +import viewfx.ViewfxException; import viewfx.view.support.fxml.FxmlViewLoader; import viewfx.view.support.guice.GuiceViewFactory; @@ -79,13 +82,26 @@ public class ViewLoaderTests { resourceBundle = BSResources.getResourceBundle(); } - @Test(expected = BitsquareException.class) + @Test(expected = ViewfxException.class) public void loadingBogusFxmlResourceShouldThrow() throws MalformedURLException { - new FxmlViewLoader(viewFactory, resourceBundle).load(FxmlView.BOGUS.getLocation()); + URL uri = new File("/tmp/bogus1234").toURI().toURL(); + new FxmlViewLoader(viewFactory, resourceBundle).load(uri); } @Test - public void loadingValidFxmlResourceShouldNotThrow() { - new FxmlViewLoader(viewFactory, resourceBundle).load(FxmlView.ACCOUNT.getLocation()); + public void loadingValidFxmlResourceShouldNotThrow() throws MalformedURLException { + String path = "/Users/cbeams/Desktop/bitsquare/bitsquare/build/resources/main/" + + "io/bitsquare/gui/main/account/AccountView.fxml"; + new FxmlViewLoader(viewFactory, resourceBundle).load(new File(path).toURI().toURL()); + } + + @Test + public void loadingFromValidFxmlViewClassShouldNotThrow() { + new FxmlViewLoader(viewFactory, resourceBundle).load(FundsView.class); + } + + @Test(expected = IllegalArgumentException.class) + public void loadingFromNonViewClassShouldThrow() { + new FxmlViewLoader(viewFactory, resourceBundle).load(File.class); } } \ No newline at end of file