Introduce @FxmlView, replace Navigation.Item

This commit is contained in:
Chris Beams 2014-11-25 00:12:57 +01:00
parent 5a5bfd0826
commit 70d9577e32
No known key found for this signature in database
GPG Key ID: 3D214F8F5BC5ED73
41 changed files with 645 additions and 601 deletions

View File

@ -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(

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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();
}
}

View File

@ -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<? extends View>... viewClasses) {
navigateTo(ViewPath.to(viewClasses));
}
public void navigateTo(ViewPath newPath) {
if (newPath == null)
return;
List<FxmlView> temp = new ArrayList<>();
for (int i = 0; i < newPath.length; i++) {
FxmlView element = newPath[i];
temp.add(element);
ArrayList<Class<? extends View>> temp = new ArrayList<>();
for (int i = 0; i < newPath.size(); i++) {
Class<? extends View> viewClass = newPath.get(i);
temp.add(viewClass);
if (currentPath == null ||
(currentPath != null &&
currentPath.length > i &&
element != currentPath[i] &&
i != newPath.length - 1)) {
List<FxmlView> 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<Class<? extends View>> temp2 = new ArrayList<>(temp);
for (int n = i + 1; n < newPath.size(); n++) {
Class<? extends View>[] 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<? extends Serializable>)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;
}
}

View File

@ -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<StackPane, MainViewModel> {
public static final String TITLE_KEY = "view.title";
@ -79,18 +87,18 @@ public class MainView extends ActivatableView<StackPane, MainViewModel> {
@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<StackPane, MainViewModel> {
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<? extends View> 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<StackPane, MainViewModel> {
private class NavButton extends ToggleButton {
public NavButton(FxmlView item) {
super(item.getDisplayName(), new ImageView() {{
setId("image-nav-" + item.getId());
private final Class<? extends View> viewClass;
public NavButton(Class<? extends View> 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<StackPane, MainViewModel> {
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<? extends View> 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();
}
}

View File

@ -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<TabPane, AccountViewModel> {
@FXML Tab accountSettingsTab, arbitratorSettingsTab;
@ -49,21 +55,16 @@ public class AccountView extends ActivatableView<TabPane, AccountViewModel> {
@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<TabPane, AccountViewModel> {
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<TabPane, AccountViewModel> {
root.getSelectionModel().selectedItemProperty().removeListener(tabChangeListener);
}
private void loadView(ViewPath viewPath) {
Tab tab;
Class<? extends View> 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);
}

View File

@ -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);
}
}

View File

@ -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<Pane, Void> implements ArbitratorListener {
@FxmlView
public class ArbitratorBrowserView extends ActivatableView<Pane, Void> implements ArbitratorListener {
@FXML Button prevButton, nextButton, selectButton, closeButton;
@FXML Pane arbitratorProfile;
@ -71,30 +71,11 @@ class ArbitratorBrowserView extends ActivatableView<Pane, Void> 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<Pane, Void> implements Arbit
public void onArbitratorRemoved(Arbitrator arbitrator) {
}
@FXML
public void onPrevious() {
if (index > 0) {
@ -151,7 +131,6 @@ class ArbitratorBrowserView extends ActivatableView<Pane, Void> implements Arbit
stage.close();
}
private void checkButtonState() {
prevButton.setDisable(index < 1);
nextButton.setDisable(index == allArbitrators.size() - 1 || index == -1);

View File

@ -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;
}

View File

@ -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<AnchorPane, Void> {
@FXML Accordion accordion;
@ -119,7 +120,6 @@ public class ArbitratorRegistrationView extends ActivatableView<AnchorPane, Void
return locale.getDisplayLanguage();
}
@Override
public Locale fromString(String s) {
return null;
@ -129,13 +129,11 @@ public class ArbitratorRegistrationView extends ActivatableView<AnchorPane, Void
idTypeComboBox.setItems(FXCollections.observableArrayList(
new ArrayList<>(EnumSet.allOf(Arbitrator.ID_TYPE.class))));
idTypeComboBox.setConverter(new StringConverter<Arbitrator.ID_TYPE>() {
@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<AnchorPane, Void
methodsComboBox.setItems(FXCollections.observableArrayList(new ArrayList<>(EnumSet.allOf(Arbitrator.METHOD
.class))));
methodsComboBox.setConverter(new StringConverter<Arbitrator.METHOD>() {
@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<AnchorPane, Void
idVerificationsComboBox.setItems(
FXCollections.observableArrayList(new ArrayList<>(EnumSet.allOf(Arbitrator.ID_VERIFICATION.class))));
idVerificationsComboBox.setConverter(new StringConverter<Arbitrator.ID_VERIFICATION>() {
@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<AnchorPane, Void
}
}
private Arbitrator getEditedArbitrator() {
String pubKeyAsHex = walletService.getArbitratorDepositAddressEntry().getPubKeyAsHexString();
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getMessagePublicKey());

View File

@ -22,14 +22,16 @@ 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.*;
class ChangePasswordView extends InitializableView<GridPane, ChangePasswordViewModel> implements Wizard.Step {
@FxmlView
public class ChangePasswordView extends InitializableView<GridPane, ChangePasswordViewModel> implements Wizard.Step {
@FXML HBox buttonsHBox;
@FXML Button saveButton, skipButton;

View File

@ -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<GridPane, FiatAccountViewModel> implements Wizard.Step {
@FxmlView
public class FiatAccountView extends ActivatableViewAndModel<GridPane, FiatAccountViewModel> implements Wizard.Step {
@FXML HBox buttonsHBox;
@FXML ComboBox<Region> regionComboBox;

View File

@ -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<GridPane, IrcAccountViewModel> implements Wizard.Step {
@FXML HBox buttonsHBox;

View File

@ -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<GridPane, PasswordViewModel> implements Wizard.Step {
@FXML HBox buttonsHBox;

View File

@ -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<GridPane, RegistrationViewModel> implements Wizard.Step {
@FXML TextField feeTextField;

View File

@ -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<GridPane, RestrictionsViewModel> implements Wizard.Step {
@FXML ListView<Locale> languagesListView;
@ -120,8 +122,9 @@ public class RestrictionsView extends ActivatableViewAndModel<GridPane, Restrict
}
@FXML
private void onOpenArbitratorScreen() {
loadView(FxmlView.ARBITRATOR_BROWSER);
private void onOpenArbitratorScreen(){
View view = viewLoader.load(ArbitratorBrowserView.class);
showStage(view);
}
@ -146,9 +149,7 @@ public class RestrictionsView extends ActivatableViewAndModel<GridPane, Restrict
Help.openWindow(HelpId.SETUP_RESTRICTION_ARBITRATORS);
}
private void loadView(FxmlView navigationItem) {
View view = viewLoader.load(navigationItem.getLocation());
private void showStage(View view) {
final Stage stage = new Stage();
stage.setTitle("Arbitrator selection");
stage.setMinWidth(800);
@ -162,7 +163,7 @@ public class RestrictionsView extends ActivatableViewAndModel<GridPane, Restrict
Scene scene = new Scene((Parent) view.getRoot(), 800, 600);
stage.setScene(scene);
stage.setOnHidden(windowEvent -> {
if (navigationItem == FxmlView.ARBITRATOR_BROWSER)
if (view instanceof ArbitratorBrowserView)
updateArbitratorList();
});
stage.show();

View File

@ -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<GridPane, SeedWordsViewModel> implements Wizard.Step {
@FXML Button completedButton;

View File

@ -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<? extends View> 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<? extends View> 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<? extends View> 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) {

View File

@ -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<? extends View> 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<? extends View> 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<? extends View> viewClass;
WizardItem(AccountSetupWizard parent, String title, String subTitle,
FxmlView navigationItem) {
this.parent = parent;
this.navigationItem = navigationItem;
WizardItem(Class<? extends View> 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");
}
}
}

View File

@ -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<TabPane, Activatable> {
@FxmlView
public class FundsView extends ActivatableViewAndModel<TabPane, Activatable> {
@FXML Tab withdrawalTab, transactionsTab;
@ -43,24 +47,23 @@ class FundsView extends ActivatableViewAndModel<TabPane, Activatable> {
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<TabPane, Activatable> {
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<TabPane, Activatable> {
navigation.removeListener(navigationListener);
}
private void loadView(FxmlView navigationItem) {
private void loadView(Class<? extends View> 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);
}

View File

@ -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<TransactionsListItem> table;
@FXML TableColumn<TransactionsListItem, TransactionsListItem> dateColumn, addressColumn, amountColumn, typeColumn,

View File

@ -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<WithdrawalListItem> table;
@FXML Button addNewAddressButton;

View File

@ -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 {
}

View File

@ -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 {
}

View File

@ -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<TabPane, Activatable> {
@FxmlView
public class PortfolioView extends ActivatableViewAndModel<TabPane, Activatable> {
@FXML Tab offersTab, openTradesTab, closedTradesTab;
@ -53,20 +58,18 @@ class PortfolioView extends ActivatableViewAndModel<TabPane, Activatable> {
@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<TabPane, Activatable> {
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<TabPane, Activatable> {
currentTab = null;
}
private void loadView(FxmlView navigationItem) {
private void loadView(Class<? extends View> 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);
}

View File

@ -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<GridPane, ClosedTradesViewModel> {
@FxmlView
public class ClosedTradesView extends ActivatableViewAndModel<GridPane, ClosedTradesViewModel> {
@FXML TableView<ClosedTradesListItem> table;
@FXML TableColumn<ClosedTradesListItem, ClosedTradesListItem> priceColumn, amountColumn, volumeColumn,

View File

@ -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<GridPane, OffersViewModel> {
@FxmlView
public class OffersView extends ActivatableViewAndModel<GridPane, OffersViewModel> {
@FXML TableView<OfferListItem> table;
@FXML TableColumn<OfferListItem, OfferListItem> priceColumn, amountColumn, volumeColumn,

View File

@ -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<AnchorPane, PendingTradesViewModel> {
@FxmlView
public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, PendingTradesViewModel> {
@FXML GridPane gridPane;
@FXML ScrollPane scrollPane;
@ -180,9 +184,7 @@ class PendingTradesView extends ActivatableViewAndModel<AnchorPane, PendingTrade
public void onWithdraw() {
setSummaryControlsVisible(false);
model.withdraw(withdrawAddressTextField.getText());
Platform.runLater(() ->
navigation.navigateTo(FxmlView.MAIN, FxmlView.PORTFOLIO,
FxmlView.CLOSED_TRADES));
Platform.runLater(() -> navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class));
}
@FXML

View File

@ -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<TabPane, Activatable> {
@FxmlView
public class SettingsView extends ActivatableViewAndModel<TabPane, Activatable> {
@FXML Tab preferencesTab, networkSettingsTab;
@ -52,19 +56,16 @@ class SettingsView extends ActivatableViewAndModel<TabPane, Activatable> {
@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<TabPane, Activatable> {
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<TabPane, Activatable> {
navigation.removeListener(navigationListener);
}
private void loadView(FxmlView navigationItem) {
View view = viewLoader.load(navigationItem.getLocation());
private void loadView(Class<? extends View> 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);
}

View File

@ -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<GridPane, PreferencesViewModel> {
@FxmlView
public class PreferencesView extends ActivatableViewAndModel<GridPane, PreferencesViewModel> {
@FXML ComboBox<String> btcDenominationComboBox;
@FXML CheckBox useAnimationsCheckBox, useEffectsCheckBox;

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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<TabPane, Void> {
public abstract class TradeView extends ActivatableView<TabPane, Void> {
private OfferBookView offerBookView;
private CreateOfferView createOfferView;
@ -49,28 +50,25 @@ public class TradeView extends ActivatableView<TabPane, Void> {
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<TabPane, Void> {
});
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<TabPane, Void> {
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<? extends View> 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<TabPane, Void> {
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, Void> {
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<TabPane, Void> {
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);
}
}

View File

@ -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<AnchorPane, CreateOfferViewModel> {
@FXML ScrollPane scrollPane;
@ -222,17 +229,14 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
}
private void openAccountSettings() {
navigation.navigateTo(FxmlView.MAIN,
FxmlView.ACCOUNT,
FxmlView.ACCOUNT_SETTINGS,
FxmlView.RESTRICTIONS);
navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, RestrictionsView.class);
}
private void close() {
TabPane tabPane = ((TabPane) (root.getParent().getParent()));
tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem());
navigation.navigateTo(FxmlView.MAIN, FxmlView.PORTFOLIO, FxmlView.OFFERS);
navigation.navigateTo(MainView.class, PortfolioView.class, OffersView.class);
}
private void setupListeners() {

View File

@ -17,11 +17,15 @@
package io.bitsquare.gui.main.trade.offerbook;
import io.bitsquare.gui.FxmlView;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.OverlayManager;
import io.bitsquare.gui.components.InputTextField;
import io.bitsquare.gui.components.Popups;
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.account.setup.AccountSetupWizard;
import io.bitsquare.gui.main.trade.TradeView;
import io.bitsquare.gui.util.ImageUtil;
import io.bitsquare.gui.util.validation.OptionalBtcValidator;
@ -36,8 +40,9 @@ import java.util.List;
import javax.inject.Inject;
import viewfx.view.support.ActivatableViewAndModel;
import viewfx.view.ChildView;
import viewfx.view.FxmlView;
import viewfx.view.support.ActivatableViewAndModel;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.transformation.SortedList;
@ -55,6 +60,7 @@ import org.controlsfx.dialog.Dialog;
import static javafx.beans.binding.Bindings.createStringBinding;
@FxmlView
public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookViewModel>
implements ChildView<TradeView> {
@ -204,8 +210,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
Dialog.Actions.OK.handle(actionEvent);
overlayManager.removeBlurContent();
navigation.setReturnPath(navigation.getCurrentPath());
navigation.navigateTo(FxmlView.MAIN, FxmlView.ACCOUNT,
FxmlView.ACCOUNT_SETUP);
navigation.navigateTo(MainView.class, AccountView.class, AccountSetupWizard.class);
}
});
Popups.openInfoPopup("You don't have setup a trading account.",
@ -255,9 +260,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
actions);
if (Popups.isYes(response))
navigation.navigateTo(FxmlView.MAIN, FxmlView.ACCOUNT,
FxmlView.ACCOUNT_SETTINGS,
FxmlView.RESTRICTIONS);
navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, RestrictionsView.class);
else
table.getSelectionModel().clearSelection();
}

View File

@ -18,7 +18,6 @@
package io.bitsquare.gui.main.trade.takeoffer;
import io.bitsquare.gui.FxmlView;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.OverlayManager;
import io.bitsquare.gui.components.AddressTextField;
@ -27,8 +26,11 @@ 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.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import io.bitsquare.gui.main.portfolio.PortfolioView;
import io.bitsquare.gui.main.portfolio.pending.PendingTradesView;
import io.bitsquare.gui.util.ImageUtil;
import io.bitsquare.locale.BSResources;
import io.bitsquare.offer.Direction;
@ -41,6 +43,7 @@ import java.util.List;
import javax.inject.Inject;
import viewfx.view.FxmlView;
import viewfx.view.support.ActivatableViewAndModel;
import javafx.beans.property.BooleanProperty;
@ -64,6 +67,7 @@ import org.controlsfx.control.action.AbstractAction;
import org.controlsfx.control.action.Action;
import org.controlsfx.dialog.Dialog;
@FxmlView
public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOfferViewModel> {
@FXML ScrollPane scrollPane;
@ -281,8 +285,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
getProperties().put("type", "CLOSE");
try {
close();
navigation.navigateTo(FxmlView.MAIN, FxmlView.PORTFOLIO,
FxmlView.PENDING_TRADES);
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);
} catch (Exception e) {
e.printStackTrace();
}

View File

@ -0,0 +1,25 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package viewfx;
public class ViewfxException extends RuntimeException {
public ViewfxException(Throwable cause, String format, Object... args) {
super(String.format(format, args), cause);
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<? extends Function<Class<? extends View>, String>> convention() default DefaultFxmlPathConvention.class;
static class DefaultFxmlPathConvention implements Function<Class<? extends View>, String> {
@Override
public String apply(Class<? extends View> viewClass) {
return ClassUtils.convertClassNameToResourcePath(viewClass.getName()).concat(".fxml");
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
package viewfx.view;
import java.util.ArrayList;
import java.util.Arrays;
public class ViewPath extends ArrayList<Class<? extends View>> {
public ViewPath() {
}
public static ViewPath to(Class<? extends View>... 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<? extends View> tip() {
if (size() == 0)
return null;
return get(size()-1);
}
}

View File

@ -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<? extends View>: " + clazz);
URL url = (URL) location;
@SuppressWarnings("unchecked")
Class<? extends View> viewClass = (Class<? extends View>) 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);
}
}

View File

@ -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);
}
}