Merge branch 'cbeams'

Overview of major changes:

 - Introduce top-level `viewfx` package for general-purpose MVVM-style
   infrastructure classes. Note that this package naming will likely
   change, especially if and when we extract it to a physically-separate
   library.

 - Introduce View and Model class hierarchies that capture the various
   lifecycle and model management concerns throughout the existing
   Bitsquare application (see `viewfx.view` and `viewfx.model` packages)

 - Introduce @FxmlView and FxmlViewLoader to support declarative,
   convention-over-configuration support for FXML-based views.
   Eventually, this approach will allow for seamless mixing of FXML- and
   non-FXML based view implementations within the same application.

 - Introduce a type-safe approach to intra-view navigation: eliminate
   the Navigation.Item enum in favor of navigating directly from one
   view to another using *View class literals. This change is closely
   tied to the @FxmlView approach described above.

Many additional smaller changes are included as well; see individual
commits for details.

* cbeams: (75 commits)
  Rename viewfx.view.support.guice.{Guice=>Injector}ViewFactory
  Use instanceof checks on views instead of class equality
  Add CachingViewLoaderTests
  Revert "Remove System#exit call from BitsquareApp#stop"
  Change signature of ViewLoader#load to accept Class
  Complete implementation and testing of @FxmlView support
  Remove System#exit call from BitsquareApp#stop
  fix checkArgument
  Use irc instead of fiat classes
  Remove hardcoded path from ViewLoaderTests
  Fix conditional logic in AccountView#activate
  Polish AccountSettingsView
  Introduce @FxmlView, replace Navigation.Item
  Begin refactoring Navigation
  Rename enum gui.{Navigation#Item => FxmlView}
  Introduce viewfx.view.support.CachingViewLoader
  Extract ViewLoader interface and introduce FxmlViewLoader
  Fix broken tests and app exceptions due to ViewLoader changes
  Bind ViewFactory interface to GuiceViewFactory impl
  Move i.b.gui.ViewLoader.java => viewfx.view.support.ViewLoader
  ...
This commit is contained in:
Chris Beams 2014-11-25 22:13:36 +01:00
commit 58335f036e
No known key found for this signature in database
GPG Key ID: 3D214F8F5BC5ED73
192 changed files with 3988 additions and 6716 deletions

View File

@ -48,6 +48,8 @@
<emptyLine />
<package name="javax.swing" withSubpackages="true" static="false" />
<emptyLine />
<package name="viewfx" withSubpackages="true" static="false" />
<emptyLine />
<package name="javafx" withSubpackages="true" static="false" />
<emptyLine />
<package name="com.sun.javafx" withSubpackages="true" static="false" />
@ -86,5 +88,4 @@
</option>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</component>
</project>
</project>

View File

@ -17,6 +17,7 @@ version = '0.1.0-SNAPSHOT'
sourceCompatibility = 1.8
sourceSets.main.resources.srcDirs += 'src/main/java'
sourceSets.test.resources.srcDirs += 'src/test/java'
mainClassName = "io.bitsquare.app.gui.BitsquareAppMain"
@ -58,6 +59,7 @@ dependencies {
compile 'org.jetbrains:annotations:13.0'
compile 'eu.hansolo.enzo:Enzo:0.1.5'
testCompile 'junit:junit:4.11'
testCompile "org.mockito:mockito-core:1.+"
testCompile 'org.springframework:spring-test:4.1.1.RELEASE'
}

View File

@ -20,7 +20,7 @@ package io.bitsquare.app;
import io.bitsquare.BitsquareException;
import io.bitsquare.btc.UserAgent;
import io.bitsquare.btc.WalletService;
import io.bitsquare.gui.ViewCB;
import io.bitsquare.gui.main.MainView;
import io.bitsquare.persistence.Persistence;
import io.bitsquare.util.Utilities;
import io.bitsquare.util.spring.JOptCommandLinePropertySource;
@ -122,7 +122,7 @@ public class BitsquareEnvironment extends StandardEnvironment {
setProperty(Persistence.DIR_KEY, appDataDir);
setProperty(Persistence.PREFIX_KEY, appName + "_pref");
setProperty(ViewCB.TITLE_KEY, appName);
setProperty(MainView.TITLE_KEY, appName);
}});
}

View File

@ -22,8 +22,7 @@ import joptsimple.OptionParser;
import joptsimple.OptionSet;
import org.springframework.util.StringUtils;
import static java.lang.String.format;
import static java.lang.String.join;
import static java.lang.String.*;
public abstract class BitsquareExecutable {
public static final int EXIT_SUCCESS = 0;

View File

@ -19,11 +19,9 @@ package io.bitsquare.app.gui;
import io.bitsquare.BitsquareException;
import io.bitsquare.account.AccountSettings;
import io.bitsquare.gui.GuiceControllerFactory;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.SystemTray;
import io.bitsquare.gui.ViewLoader;
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;
@ -40,6 +38,11 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import viewfx.view.View;
import viewfx.view.ViewLoader;
import viewfx.view.support.CachingViewLoader;
import viewfx.view.support.guice.InjectorViewFactory;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.image.*;
@ -64,7 +67,7 @@ public class BitsquareApp extends Application {
public void start(Stage primaryStage) throws IOException {
bitsquareAppModule = new BitsquareAppModule(env, primaryStage);
injector = Guice.createInjector(bitsquareAppModule);
injector.getInstance(GuiceControllerFactory.class).setInjector(injector);
injector.getInstance(InjectorViewFactory.class).setInjector(injector);
// route uncaught exceptions to a user-facing dialog
@ -93,10 +96,10 @@ public class BitsquareApp extends Application {
// load the main view and create the main scene
ViewLoader viewLoader = injector.getInstance(ViewLoader.class);
ViewLoader.Item loaded = viewLoader.load(Navigation.Item.MAIN.getFxmlUrl(), false);
ViewLoader viewLoader = injector.getInstance(CachingViewLoader.class);
View view = viewLoader.load(MainView.class);
Scene scene = new Scene((Parent) loaded.view, 1000, 600);
Scene scene = new Scene((Parent) view.getRoot(), 1000, 600);
scene.getStylesheets().setAll(
"/io/bitsquare/gui/bitsquare.css",
"/io/bitsquare/gui/images.css");

View File

@ -30,7 +30,6 @@ import joptsimple.OptionSet;
import static io.bitsquare.app.BitsquareEnvironment.*;
import static io.bitsquare.msg.tomp2p.TomP2PMessageModule.*;
import static io.bitsquare.network.Node.*;
import static java.lang.String.format;
public class BitsquareAppMain extends BitsquareExecutable {

View File

@ -19,9 +19,6 @@ package io.bitsquare.arbitrator;
import java.io.Serializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//TODO still open if we use that really...
/**
@ -30,8 +27,6 @@ import org.slf4j.LoggerFactory;
public class Reputation implements Serializable {
private static final long serialVersionUID = -3073174320050879490L;
private static final Logger log = LoggerFactory.getLogger(Reputation.class);
//TODO
public Reputation() {
}

View File

@ -1,104 +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 java.net.URL;
import java.util.ResourceBundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* If caching is used for loader we use the CachedViewController for turning the controller into sleep mode if not
* active and awake it at reactivation.
* * @param <T> The PresentationModel used in that class
*/
public class CachedViewCB<T extends PresentationModel> extends ViewCB<T> {
private static final Logger log = LoggerFactory.getLogger(CachedViewCB.class);
public CachedViewCB(T presentationModel) {
super(presentationModel);
}
public CachedViewCB() {
super();
}
/**
* Get called form GUI framework when the UI is ready.
* In caching controllers the initialize is only used for static UI setup.
* The activate() method is called to start resources like.
*
* @param url
* @param rb
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
log.trace("Lifecycle: initialize " + this.getClass().getSimpleName());
if (root != null) {
root.sceneProperty().addListener((ov, oldValue, newValue) -> {
// we got removed from the scene
// lets terminate
log.trace("Lifecycle: sceneProperty changed: " + this.getClass().getSimpleName() + " / oldValue=" +
oldValue + " / newValue=" + newValue);
if (oldValue == null && newValue != null)
activate();
else if (oldValue != null && newValue == null)
deactivate();
});
}
if (presentationModel != null)
presentationModel.initialize();
}
/**
* Used to activate resources (adding listeners, starting timers or animations,...)
*/
public void activate() {
log.trace("Lifecycle: activate " + this.getClass().getSimpleName());
if (presentationModel != null)
presentationModel.activate();
}
/**
* Used for deactivating resources (removing listeners, stopping timers or animations,...)
*/
public void deactivate() {
log.trace("Lifecycle: deactivate " + this.getClass().getSimpleName());
if (presentationModel != null)
presentationModel.deactivate();
}
/**
* In caching controllers the terminate calls the deactivate method.
*/
@Override
public void terminate() {
log.trace("Lifecycle: terminate " + this.getClass().getSimpleName());
super.terminate();
if (presentationModel != null)
presentationModel.terminate();
}
}

View File

@ -19,6 +19,7 @@ package io.bitsquare.gui;
import io.bitsquare.BitsquareModule;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.main.MainView;
import io.bitsquare.gui.main.trade.offerbook.OfferBook;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.gui.util.Transitions;
@ -27,9 +28,19 @@ import io.bitsquare.gui.util.validation.BtcValidator;
import io.bitsquare.gui.util.validation.FiatValidator;
import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.gui.util.validation.PasswordValidator;
import io.bitsquare.locale.BSResources;
import com.google.inject.Singleton;
import com.google.inject.name.Names;
import java.util.ResourceBundle;
import viewfx.view.ViewFactory;
import viewfx.view.ViewLoader;
import viewfx.view.support.CachingViewLoader;
import viewfx.view.support.fxml.FxmlViewLoader;
import viewfx.view.support.guice.InjectorViewFactory;
import javafx.stage.Stage;
import org.springframework.core.env.Environment;
@ -45,8 +56,12 @@ public class GuiModule extends BitsquareModule {
@Override
protected void configure() {
bind(GuiceControllerFactory.class).asEagerSingleton();
bind(ViewLoader.class).asEagerSingleton();
bind(InjectorViewFactory.class).in(Singleton.class);
bind(ViewFactory.class).to(InjectorViewFactory.class);
bind(ResourceBundle.class).toInstance(BSResources.getResourceBundle());
bind(ViewLoader.class).to(FxmlViewLoader.class).asEagerSingleton();
bind(CachingViewLoader.class).asEagerSingleton();
bind(OfferBook.class).asEagerSingleton();
bind(Navigation.class).asEagerSingleton();
@ -63,6 +78,6 @@ public class GuiModule extends BitsquareModule {
bind(Stage.class).toInstance(primaryStage);
Popups.primaryStage = primaryStage;
bindConstant().annotatedWith(Names.named(ViewCB.TITLE_KEY)).to(env.getRequiredProperty(ViewCB.TITLE_KEY));
bindConstant().annotatedWith(Names.named(MainView.TITLE_KEY)).to(env.getRequiredProperty(MainView.TITLE_KEY));
}
}

View File

@ -17,89 +17,90 @@
package io.bitsquare.gui;
import io.bitsquare.BitsquareException;
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.net.URL;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import viewfx.view.View;
import viewfx.view.ViewPath;
public class Navigation {
private static final Logger log = LoggerFactory.getLogger(Navigation.class);
// New listeners can be added during iteration so we use CopyOnWriteArrayList to prevent invalid array
// modification
private static final String CURRENT_PATH_KEY = "currentPath";
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
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
private final Persistence persistence;
private Item[] currentItems;
// 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 Item[] itemsForReturning;
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 ViewPath returnPath;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public Navigation(Persistence persistence) {
this.persistence = persistence;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////////////////////////////
public void navigateTo(Class<? extends View>... viewClasses) {
navigateTo(ViewPath.to(viewClasses));
}
public void navigationTo(Item... items) {
List<Item> temp = new ArrayList<>();
if (items != null) {
for (int i = 0; i < items.length; i++) {
Item item = items[i];
temp.add(item);
if (currentItems == null ||
(currentItems != null &&
currentItems.length > i &&
item != currentItems[i] &&
i != items.length - 1)) {
List<Item> temp2 = new ArrayList<>(temp);
for (int n = i + 1; n < items.length; n++) {
Item[] newTemp = new Item[i + 1];
currentItems = temp2.toArray(newTemp);
navigationTo(currentItems);
item = items[n];
temp2.add(item);
}
public void navigateTo(ViewPath newPath) {
if (newPath == null)
return;
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.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);
viewClass = newPath.get(n);
temp2.add(viewClass);
}
}
currentItems = items;
persistence.write(this, "navigationItems", items);
listeners.stream().forEach((e) -> e.onNavigationRequested(items));
}
currentPath = newPath;
persistence.write(this, CURRENT_PATH_KEY, (List<? extends Serializable>)currentPath);
listeners.stream().forEach((e) -> e.onNavigationRequested(currentPath));
}
public void navigateToLastStoredItem() {
Item[] items = (Item[]) persistence.read(this, "navigationItems");
// TODO we set BUY as default yet, should be HOME later
if (items == null || items.length == 0)
items = new Item[]{Item.MAIN, Item.BUY};
public void navigateToLastOpenView() {
ViewPath lastPath = (ViewPath) persistence.read(this, CURRENT_PATH_KEY);
navigationTo(items);
if (lastPath == null || lastPath.size() == 0)
lastPath = DEFAULT_VIEW_PATH;
navigateTo(lastPath);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Listeners
///////////////////////////////////////////////////////////////////////////////////////////
public static interface Listener {
void onNavigationRequested(ViewPath path);
}
public void addListener(Listener listener) {
listeners.add(listener);
@ -109,146 +110,15 @@ public class Navigation {
listeners.remove(listener);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
public Item[] getItemsForReturning() {
return itemsForReturning;
public ViewPath getReturnPath() {
return returnPath;
}
public Item[] getCurrentItems() {
return currentItems;
public ViewPath getCurrentPath() {
return currentPath;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
public void setItemsForReturning(Item[] itemsForReturning) {
this.itemsForReturning = itemsForReturning;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface
///////////////////////////////////////////////////////////////////////////////////////////
public static interface Listener {
void onNavigationRequested(Item... items);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Enum
///////////////////////////////////////////////////////////////////////////////////////////
public static enum Item {
///////////////////////////////////////////////////////////////////////////////////////////
// Application
///////////////////////////////////////////////////////////////////////////////////////////
MAIN("/io/bitsquare/gui/main/MainView.fxml"),
///////////////////////////////////////////////////////////////////////////////////////////
// Main menu screens
///////////////////////////////////////////////////////////////////////////////////////////
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/AccountSetupView.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
///////////////////////////////////////////////////////////////////////////////////////////
// arbitrator
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"),
// for testing, does not actually exist
BOGUS("/io/bitsquare/BogusView.fxml");
private final String displayName;
private final String fxmlUrl;
Item(String fxmlUrl) {
this(fxmlUrl, "NONE");
}
Item(String fxmlUrl, String displayName) {
this.displayName = displayName;
this.fxmlUrl = fxmlUrl;
}
public URL getFxmlUrl() {
URL url = Navigation.class.getResource(fxmlUrl);
if (url == null)
throw new BitsquareException("'%s' could not be loaded as a resource", fxmlUrl);
return url;
}
public String getDisplayName() {
return displayName;
}
public String getId() {
return fxmlUrl.substring(fxmlUrl.lastIndexOf("/") + 1, fxmlUrl.lastIndexOf("View.fxml")).toLowerCase();
}
public void setReturnPath(ViewPath returnPath) {
this.returnPath = returnPath;
}
}

View File

@ -22,11 +22,7 @@ import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OverlayManager {
private static final Logger log = LoggerFactory.getLogger(OverlayManager.class);
private final List<OverlayListener> listeners = new ArrayList<>();

View File

@ -1,58 +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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PresentationModel<T extends UIModel> {
private static final Logger log = LoggerFactory.getLogger(PresentationModel.class);
protected T model;
public PresentationModel(T model) {
this.model = model;
}
public PresentationModel() {
}
public void initialize() {
log.trace("Lifecycle: initialize " + this.getClass().getSimpleName());
if (model != null)
model.initialize();
}
public void activate() {
log.trace("Lifecycle: activate " + this.getClass().getSimpleName());
if (model != null)
model.activate();
}
public void deactivate() {
log.trace("Lifecycle: deactivate " + this.getClass().getSimpleName());
if (model != null)
model.deactivate();
}
public void terminate() {
log.trace("Lifecycle: terminate " + this.getClass().getSimpleName());
if (model != null)
model.terminate();
}
}

View File

@ -1,106 +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 java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Non caching version for code behind classes using the PM pattern
*
* @param <T> The PresentationModel used in that class
*/
public class ViewCB<T extends PresentationModel> implements Initializable {
private static final Logger log = LoggerFactory.getLogger(ViewCB.class);
public static final String TITLE_KEY = "view.title";
protected T presentationModel;
protected Initializable childController;
protected Initializable parent;
@FXML protected Parent root;
protected ViewCB(T presentationModel) {
this.presentationModel = presentationModel;
}
protected ViewCB() {
}
/**
* Get called form GUI framework when the UI is ready.
*
* @param url
* @param rb
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
log.trace("Lifecycle: initialize " + this.getClass().getSimpleName());
if (root != null) {
root.sceneProperty().addListener((ov, oldValue, newValue) -> {
// we got removed from the scene
// lets terminate
if (oldValue != null && newValue == null)
terminate();
});
}
if (presentationModel != null)
presentationModel.initialize();
}
/**
* Called automatically when view gets removed. Used for house keeping (removing listeners,
* stopping timers or animations,...).
*/
public void terminate() {
log.trace("Lifecycle: terminate " + this.getClass().getSimpleName());
if (presentationModel != null)
presentationModel.terminate();
}
/**
* @param parent Controller who has created this.getClass().getSimpleName() instance (via
* navigateToView/FXMLLoader).
*/
public void setParent(Initializable parent) {
log.trace("Lifecycle: setParentController " + this.getClass().getSimpleName() + " / parent = " +
parent);
this.parent = parent;
}
/**
* @param navigationItem NavigationItem to be loaded.
* @return The ViewController of the loaded view.
*/
protected Initializable loadView(Navigation.Item navigationItem) {
log.trace("Lifecycle: loadViewAndGetChildController " + this.getClass().getSimpleName() + " / navigationItem " +
"= " + navigationItem);
return null;
}
}

View File

@ -1,84 +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 io.bitsquare.locale.BSResources;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.fxml.JavaFXBuilderFactory;
import javafx.scene.*;
import javafx.util.BuilderFactory;
/**
* Guice support for fxml controllers
* Support caching to speed up switches between UI screens.
*/
public class ViewLoader {
private final Map<URL, Item> cache = new HashMap<>();
private final BuilderFactory builderFactory = new JavaFXBuilderFactory();
private final GuiceControllerFactory controllerFactory;
@Inject
public ViewLoader(GuiceControllerFactory controllerFactory) {
this.controllerFactory = controllerFactory;
}
public Item load(URL url) {
return load(url, true);
}
public Item load(URL url, boolean useCaching) {
Item item;
if (useCaching && cache.containsKey(url)) {
return cache.get(url);
}
FXMLLoader loader = new FXMLLoader(url, BSResources.getResourceBundle(), builderFactory, controllerFactory);
try {
item = new Item(loader.load(), loader.getController());
cache.put(url, item);
return item;
} catch (IOException e) {
throw new BitsquareException(e, "Failed to load view at %s", url);
}
}
public static class Item {
public final Node view;
public final Initializable controller;
Item(Node view, Initializable controller) {
this.view = view;
this.controller = controller;
}
}
}

View File

@ -32,11 +32,7 @@ import javafx.scene.effect.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BalanceTextField extends AnchorPane {
private static final Logger log = LoggerFactory.getLogger(BalanceTextField.class);
private final TextField textField;
private final Tooltip progressIndicatorTooltip;

View File

@ -39,9 +39,6 @@ import javafx.scene.text.*;
import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Convenience Component for info icon, info text and link display in a GridPane.
* Only the properties needed are supported.
@ -49,7 +46,6 @@ import org.slf4j.LoggerFactory;
* but add the children nodes to the gridPane.
*/
public class InfoDisplay extends Parent {
private static final Logger log = LoggerFactory.getLogger(InfoDisplay.class);
private final StringProperty text = new SimpleStringProperty();
private final IntegerProperty rowIndex = new SimpleIntegerProperty(0);

View File

@ -31,9 +31,6 @@ import javafx.stage.Window;
import org.controlsfx.control.PopOver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* TextField with validation support.
* If validator is set it supports on focus out validation with that validator. If a more sophisticated validation is
@ -48,7 +45,6 @@ import org.slf4j.LoggerFactory;
//TODO There are some rare situation where it behaves buggy. Needs further investigation and improvements. Also
// consider replacement with controlsFX components.
public class InputTextField extends TextField {
private static final Logger log = LoggerFactory.getLogger(InputTextField.class);
private final Effect invalidEffect = new DropShadow(BlurType.THREE_PASS_BOX, Color.RED, 4, 0.0, 0, 0);

View File

@ -19,9 +19,6 @@ package io.bitsquare.gui.components;
import io.bitsquare.util.Utilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.hansolo.enzo.notification.Notification;
import eu.hansolo.enzo.notification.NotificationBuilder;
import eu.hansolo.enzo.notification.NotifierBuilder;
@ -30,7 +27,6 @@ import eu.hansolo.enzo.notification.NotifierBuilder;
* Not sure if we stick with the eu.hansolo.enzo.notification.Notification implementation, so keep it behind a service
*/
public class SystemNotification {
private static final Logger log = LoggerFactory.getLogger(SystemNotification.class);
private static final Notification.Notifier notifier = NotifierBuilder.create().build();
public static void openInfoNotification(String title, String message) {

View File

@ -27,11 +27,7 @@ import javafx.scene.layout.*;
import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TextFieldWithCopyIcon extends AnchorPane {
private static final Logger log = LoggerFactory.getLogger(TextFieldWithCopyIcon.class);
private final StringProperty text = new SimpleStringProperty();

View File

@ -23,11 +23,7 @@ import javafx.geometry.Insets;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TitledGroupBg extends Pane {
private static final Logger log = LoggerFactory.getLogger(TitledGroupBg.class);
private final Label label;
private final StringProperty text = new SimpleStringProperty();

View File

@ -23,11 +23,7 @@ import javafx.geometry.Insets;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TitledSeparator extends Pane {
private static final Logger log = LoggerFactory.getLogger(TitledSeparator.class);
private final Label label;
private final StringProperty text = new SimpleStringProperty();

View File

@ -35,11 +35,7 @@ import com.sun.javafx.scene.control.behavior.BehaviorBase;
import com.sun.javafx.scene.control.behavior.KeyBinding;
import com.sun.javafx.scene.control.skin.BehaviorSkinBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class ProcessStepBarSkin<T> extends BehaviorSkinBase<ProcessStepBar<T>, BehaviorBase<ProcessStepBar<T>>> {
private static final Logger log = LoggerFactory.getLogger(ProcessStepBarSkin.class);
private final ProcessStepBar<T> controller;
private LabelWithBorder currentLabelWithBorder;

View File

@ -17,7 +17,7 @@
-->
<?import javafx.scene.layout.*?>
<StackPane fx:id="root" fx:controller="io.bitsquare.gui.main.MainViewCB"
<StackPane fx:id="root" fx:controller="io.bitsquare.gui.main.MainView"
prefHeight="750" prefWidth="1000" stylesheets="/io/bitsquare/gui/bitsquare.css"
xmlns:fx="http://javafx.com/fxml">
</StackPane>

View File

@ -19,18 +19,28 @@ package io.bitsquare.gui.main;
import io.bitsquare.BitsquareException;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.gui.FxmlController;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.OverlayManager;
import io.bitsquare.gui.ViewCB;
import io.bitsquare.gui.ViewLoader;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.components.SystemNotification;
import io.bitsquare.gui.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;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
@ -42,10 +52,12 @@ import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.text.*;
import static io.bitsquare.gui.Navigation.Item.*;
import static javafx.scene.layout.AnchorPane.*;
public class MainViewCB extends FxmlController<Pane, MainModel> {
@FxmlView
public class MainView extends ActivatableView<StackPane, MainViewModel> {
public static final String TITLE_KEY = "view.title";
private final ToggleGroup navButtons = new ToggleGroup();
@ -56,8 +68,8 @@ public class MainViewCB extends FxmlController<Pane, MainModel> {
private final String title;
@Inject
public MainViewCB(MainModel model, ViewLoader viewLoader, Navigation navigation, OverlayManager overlayManager,
Transitions transitions, @Named(TITLE_KEY) String title) {
public MainView(MainViewModel model, ViewLoader viewLoader, Navigation navigation, OverlayManager overlayManager,
Transitions transitions, @Named(MainView.TITLE_KEY) String title) {
super(model);
this.viewLoader = viewLoader;
this.navigation = navigation;
@ -74,19 +86,19 @@ public class MainViewCB extends FxmlController<Pane, MainModel> {
}
@Override
public void doInitialize() {
ToggleButton homeButton = new NavButton(HOME) {{
protected void activate() {
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();
@ -119,21 +131,19 @@ public class MainViewCB extends FxmlController<Pane, MainModel> {
setId("base-content-container");
}};
navigation.addListener(navItems -> {
if (navItems == null || navItems.length != 2 || navItems[0] != Navigation.Item.MAIN)
navigation.addListener(viewPath -> {
if (viewPath.size() != 2 || viewPath.indexOf(MainView.class) != 0)
return;
ViewLoader.Item loaded = viewLoader.load(navItems[1].getFxmlUrl());
contentContainer.getChildren().setAll(loaded.view);
if (loaded.controller instanceof ViewCB)
((ViewCB) loaded.controller).setParent(this);
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);
});
@ -154,7 +164,7 @@ public class MainViewCB extends FxmlController<Pane, MainModel> {
model.numPendingTrades.addListener((ov2, prev2, numPendingTrades) ->
applyPendingTradesInfoIcon((int) numPendingTrades, portfolioButtonHolder));
navigation.navigateToLastStoredItem();
navigation.navigateToLastOpenView();
transitions.fadeOutAndRemove(splashScreen, 1500);
}
@ -332,11 +342,15 @@ public class MainViewCB extends FxmlController<Pane, MainModel> {
private class NavButton extends ToggleButton {
public NavButton(Navigation.Item 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));
@ -351,14 +365,24 @@ public class MainViewCB extends FxmlController<Pane, MainModel> {
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.navigationTo(Navigation.Item.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

@ -20,7 +20,6 @@ package io.bitsquare.gui.main;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.btc.BitcoinNetwork;
import io.bitsquare.btc.WalletService;
import io.bitsquare.gui.Model;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.msg.MessageService;
import io.bitsquare.network.BootstrapState;
@ -31,6 +30,8 @@ import io.bitsquare.user.User;
import com.google.inject.Inject;
import viewfx.model.ViewModel;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
@ -51,8 +52,8 @@ import org.slf4j.LoggerFactory;
import rx.Observable;
class MainModel implements Model {
private static final Logger log = LoggerFactory.getLogger(MainModel.class);
class MainViewModel implements ViewModel {
private static final Logger log = LoggerFactory.getLogger(MainViewModel.class);
final DoubleProperty networkSyncProgress = new SimpleDoubleProperty(-1);
final IntegerProperty numPendingTrades = new SimpleIntegerProperty(0);
@ -83,8 +84,9 @@ class MainModel implements Model {
@Inject
public MainModel(User user, WalletService walletService, MessageService messageService, TradeManager tradeManager,
BitcoinNetwork bitcoinNetwork, BSFormatter formatter, Persistence persistence) {
public MainViewModel(User user, WalletService walletService, MessageService messageService,
TradeManager tradeManager, BitcoinNetwork bitcoinNetwork, BSFormatter formatter,
Persistence persistence) {
this.user = user;
this.walletService = walletService;
this.messageService = messageService;
@ -93,10 +95,7 @@ class MainModel implements Model {
this.bitcoinNetwork = bitcoinNetwork;
user.getCurrentBankAccount().addListener((observable, oldValue, newValue) -> persistence.write(user));
}
@Override
public void initialize() {
bootstrapState.addListener((ov, oldValue, newValue) -> {
if (newValue == BootstrapState.DISCOVERY_DIRECT_SUCCEEDED ||
newValue == BootstrapState.DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED ||
@ -151,6 +150,7 @@ class MainModel implements Model {
bankAccountsComboBoxPrompt.set(user.getBankAccounts().isEmpty() ? "No accounts" : "");
}
public Observable<?> initBackend() {
walletService.getDownloadProgress().subscribe(

View File

@ -1,83 +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.main.account;
import io.bitsquare.gui.UIModel;
import io.bitsquare.user.User;
import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class AccountModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(AccountModel.class);
private final User user;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private AccountModel(User user) {
this.user = user;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize() {
super.initialize();
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
boolean getNeedRegistration() {
return user.getAccountId() == null;
}
}

View File

@ -1,78 +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.main.account;
import io.bitsquare.gui.PresentationModel;
import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class AccountPM extends PresentationModel<AccountModel> {
private static final Logger log = LoggerFactory.getLogger(AccountPM.class);
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private AccountPM(AccountModel model) {
super(model);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize() {
super.initialize();
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
boolean getNeedRegistration() {
return model.getNeedRegistration();
}
}

View File

@ -19,7 +19,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.AccountViewCB"
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.AccountView"
prefHeight="630.0" prefWidth="1000.0"
AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0"
AnchorPane.rightAnchor="0" AnchorPane.topAnchor="0"

View File

@ -0,0 +1,123 @@
/*
* 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.main.account;
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;
private Navigation.Listener navigationListener;
private ChangeListener<Tab> tabChangeListener;
private final ViewLoader viewLoader;
private final Navigation navigation;
@Inject
private AccountView(AccountViewModel model, ViewLoader viewLoader, Navigation navigation) {
super(model);
this.viewLoader = viewLoader;
this.navigation = navigation;
}
@Override
public void initialize() {
navigationListener = viewPath -> {
if (viewPath.size() == 3 && viewPath.indexOf(AccountView.class) == 1)
loadView(viewPath.tip());
};
tabChangeListener = (ov, oldValue, newValue) -> {
if (newValue == accountSettingsTab)
navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class);
else
navigation.navigateTo(MainView.class, AccountView.class, ArbitratorSettingsView.class);
};
}
@Override
public void activate() {
navigation.addListener(navigationListener);
root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener);
if (navigation.getCurrentPath().size() == 2 &&
navigation.getCurrentPath().get(1) == AccountView.class) {
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);
else
navigation.navigateTo(MainView.class, AccountView.class, ArbitratorSettingsView.class);
}
}
}
@Override
public void deactivate() {
navigation.removeListener(navigationListener);
root.getSelectionModel().selectedItemProperty().removeListener(tabChangeListener);
}
private void loadView(Class<? extends View> viewClass) {
Tab tab;
View view = viewLoader.load(viewClass);
if (view instanceof AccountSettingsView) {
tab = accountSettingsTab;
tab.setText("Account settings");
arbitratorSettingsTab.setDisable(false);
}
else if (view instanceof AccountSetupWizard) {
tab = accountSettingsTab;
tab.setText("Account setup");
arbitratorSettingsTab.setDisable(true);
}
else if (view instanceof ArbitratorSettingsView) {
tab = arbitratorSettingsTab;
}
else {
throw new IllegalArgumentException("View not supported: " + view);
}
// for IRC demo we deactivate the arbitratorSettingsTab
arbitratorSettingsTab.setDisable(true);
tab.setContent(view.getRoot());
root.getSelectionModel().select(tab);
}
}

View File

@ -1,175 +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.main.account;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.ViewCB;
import io.bitsquare.gui.ViewLoader;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AccountViewCB extends CachedViewCB<AccountPM> {
private static final Logger log = LoggerFactory.getLogger(AccountViewCB.class);
private Navigation.Listener navigationListener;
private ChangeListener<Tab> tabChangeListener;
@FXML Tab accountSettingsTab, arbitratorSettingsTab;
private final ViewLoader viewLoader;
private final Navigation navigation;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private AccountViewCB(AccountPM presentationModel, ViewLoader viewLoader, Navigation navigation) {
super(presentationModel);
this.viewLoader = viewLoader;
this.navigation = navigation;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
navigationListener = navigationItems -> {
if (navigationItems != null &&
navigationItems.length == 3 &&
navigationItems[1] == Navigation.Item.ACCOUNT)
loadView(navigationItems[2]);
};
tabChangeListener = (ov, oldValue, newValue) -> {
if (newValue == accountSettingsTab)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ACCOUNT,
Navigation.Item.ACCOUNT_SETTINGS);
else
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ACCOUNT,
Navigation.Item.ARBITRATOR_SETTINGS);
};
super.initialize(url, rb);
}
@Override
public void activate() {
super.activate();
navigation.addListener(navigationListener);
((TabPane) root).getSelectionModel().selectedItemProperty().addListener(tabChangeListener);
if (navigation.getCurrentItems().length == 2 &&
navigation.getCurrentItems()[1] == Navigation.Item.ACCOUNT) {
if (presentationModel.getNeedRegistration()) {
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ACCOUNT,
Navigation.Item.ACCOUNT_SETUP);
}
else {
if (((TabPane) root).getSelectionModel().getSelectedItem() == accountSettingsTab)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ACCOUNT,
Navigation.Item.ACCOUNT_SETTINGS);
else
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ACCOUNT,
Navigation.Item.ARBITRATOR_SETTINGS);
}
}
}
@Override
public void deactivate() {
super.deactivate();
navigation.removeListener(navigationListener);
((TabPane) root).getSelectionModel().selectedItemProperty().removeListener(tabChangeListener);
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Navigation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected Initializable loadView(Navigation.Item navigationItem) {
super.loadView(navigationItem);
ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl());
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");
}
// for IRC demo we deactivate the arbitratorSettingsTab
arbitratorSettingsTab.setDisable(true);
tab.setContent(loaded.view);
((TabPane) root).getSelectionModel().select(tab);
Initializable childController = loaded.controller;
((ViewCB) childController).setParent(this);
return childController;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
}

View File

@ -0,0 +1,38 @@
/*
* 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.main.account;
import io.bitsquare.user.User;
import com.google.inject.Inject;
import viewfx.model.ViewModel;
class AccountViewModel implements ViewModel {
private final User user;
@Inject
public AccountViewModel(User user) {
this.user = user;
}
boolean getNeedRegistration() {
return user.getAccountId() == null;
}
}

View File

@ -21,7 +21,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.arbitrator.ArbitratorSettingsViewCB"
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.arbitrator.ArbitratorSettingsView"
prefHeight="660.0" prefWidth="1000.0"
xmlns:fx="http://javafx.com/fxml">
<VBox spacing="20">

View File

@ -0,0 +1,76 @@
/*
* 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.main.account.arbitrator;
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.AbstractView;
import viewfx.view.support.CachingViewLoader;
import javafx.fxml.FXML;
import javafx.scene.*;
import javafx.stage.Modality;
import javafx.stage.Stage;
@FxmlView
public class ArbitratorSettingsView extends AbstractView {
private final ViewLoader viewLoader;
private final Stage primaryStage;
@Inject
private ArbitratorSettingsView(CachingViewLoader viewLoader, Stage primaryStage) {
this.viewLoader = viewLoader;
this.primaryStage = primaryStage;
}
@FXML
public void onArbitratorRegistration() {
View view = viewLoader.load(ArbitratorRegistrationView.class);
showStage(view);
}
@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);
stage.setWidth(800);
stage.setHeight(600);
stage.setX(primaryStage.getX() + 50);
stage.setY(primaryStage.getY() + 50);
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(primaryStage);
Scene scene = new Scene((Parent) view.getRoot(), 800, 600);
stage.setScene(scene);
stage.show();
}
}

View File

@ -1,131 +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.main.account.arbitrator;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.ViewLoader;
import io.bitsquare.gui.main.account.arbitrator.registration.ArbitratorRegistrationViewCB;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.*;
import javafx.stage.Modality;
import javafx.stage.Stage;
// TODO Arbitration is very basic yet
public class ArbitratorSettingsViewCB extends CachedViewCB {
private final ViewLoader viewLoader;
private final Navigation navigation;
private final Stage primaryStage;
private ArbitratorRegistrationViewCB arbitratorRegistrationViewCB;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private ArbitratorSettingsViewCB(ViewLoader viewLoader, Navigation navigation, Stage primaryStage) {
super();
this.viewLoader = viewLoader;
this.navigation = navigation;
this.primaryStage = primaryStage;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Navigation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected Initializable loadView(Navigation.Item navigationItem) {
ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl(), false);
arbitratorRegistrationViewCB = (ArbitratorRegistrationViewCB) loaded.controller;
final Stage stage = new Stage();
stage.setTitle("Arbitrator");
stage.setMinWidth(800);
stage.setMinHeight(400);
stage.setWidth(800);
stage.setHeight(600);
stage.setX(primaryStage.getX() + 50);
stage.setY(primaryStage.getY() + 50);
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(primaryStage);
Scene scene = new Scene((Parent) loaded.view, 800, 600);
stage.setScene(scene);
stage.show();
return arbitratorRegistrationViewCB;
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI Handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
public void onArbitratorRegistration() {
loadView(Navigation.Item.ARBITRATOR_REGISTRATION);
}
@FXML
public void onArbitratorEdit() {
loadView(Navigation.Item.ARBITRATOR_REGISTRATION);
arbitratorRegistrationViewCB.setEditMode(true);
}
}

View File

@ -18,7 +18,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.arbitrator.browser.ArbitratorBrowserViewCB"
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.arbitrator.browser.ArbitratorBrowserView"
prefHeight="600" prefWidth="800" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="10.0"
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"
xmlns:fx="http://javafx.com/fxml">

View File

@ -0,0 +1,139 @@
/*
* 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.main.account.arbitrator.browser;
import io.bitsquare.account.AccountSettings;
import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.gui.main.account.arbitrator.profile.ArbitratorProfileView;
import io.bitsquare.locale.LanguageUtil;
import io.bitsquare.msg.MessageService;
import io.bitsquare.msg.listeners.ArbitratorListener;
import io.bitsquare.persistence.Persistence;
import java.util.ArrayList;
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;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
@FxmlView
public class ArbitratorBrowserView extends ActivatableView<Pane, Void> implements ArbitratorListener {
@FXML Button prevButton, nextButton, selectButton, closeButton;
@FXML Pane arbitratorProfile;
private Arbitrator currentArbitrator;
private ArbitratorProfileView arbitratorProfileView;
private int index = -1;
private final List<Arbitrator> allArbitrators = new ArrayList<>();
private final ViewLoader viewLoader;
private final AccountSettings accountSettings;
private final Persistence persistence;
private final MessageService messageService;
@Inject
public ArbitratorBrowserView(ViewLoader viewLoader, AccountSettings accountSettings, Persistence persistence,
MessageService messageService) {
this.viewLoader = viewLoader;
this.accountSettings = accountSettings;
this.persistence = persistence;
this.messageService = messageService;
}
@Override
public void initialize() {
messageService.addArbitratorListener(this);
messageService.getArbitrators(LanguageUtil.getDefaultLanguageLocale());
View view = viewLoader.load(ArbitratorProfileView.class);
root.getChildren().set(0, view.getRoot());
arbitratorProfileView = (ArbitratorProfileView) view;
checkButtonState();
}
@Override
public void onArbitratorAdded(Arbitrator arbitrator) {
}
@Override
public void onArbitratorsReceived(List<Arbitrator> arbitrators) {
allArbitrators.clear();
allArbitrators.addAll(arbitrators);
if (!allArbitrators.isEmpty()) {
index = 0;
currentArbitrator = allArbitrators.get(index);
arbitratorProfileView.applyArbitrator(currentArbitrator);
checkButtonState();
}
}
@Override
public void onArbitratorRemoved(Arbitrator arbitrator) {
}
@FXML
public void onPrevious() {
if (index > 0) {
index--;
currentArbitrator = allArbitrators.get(index);
arbitratorProfileView.applyArbitrator(currentArbitrator);
}
checkButtonState();
}
@FXML
public void onNext() {
if (index < allArbitrators.size() - 1) {
index++;
currentArbitrator = allArbitrators.get(index);
arbitratorProfileView.applyArbitrator(currentArbitrator);
}
checkButtonState();
}
@FXML
public void onSelect() {
accountSettings.addAcceptedArbitrator(currentArbitrator);
persistence.write(accountSettings);
}
@FXML
public void onClose() {
Stage stage = (Stage) root.getScene().getWindow();
stage.close();
}
private void checkButtonState() {
prevButton.setDisable(index < 1);
nextButton.setDisable(index == allArbitrators.size() - 1 || index == -1);
}
}

View File

@ -1,222 +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.main.account.arbitrator.browser;
import io.bitsquare.account.AccountSettings;
import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.ViewCB;
import io.bitsquare.gui.ViewLoader;
import io.bitsquare.gui.main.account.arbitrator.profile.ArbitratorProfileViewCB;
import io.bitsquare.locale.LanguageUtil;
import io.bitsquare.msg.MessageService;
import io.bitsquare.msg.listeners.ArbitratorListener;
import io.bitsquare.persistence.Persistence;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
// TODO Arbitration is very basic yet
public class ArbitratorBrowserViewCB extends CachedViewCB implements ArbitratorListener {
private final ViewLoader viewLoader;
private final AccountSettings accountSettings;
private final Persistence persistence;
private final MessageService messageService;
private final List<Arbitrator> allArbitrators = new ArrayList<>();
private Arbitrator currentArbitrator;
private ArbitratorProfileViewCB arbitratorProfileViewCB;
private int index = -1;
@FXML Button prevButton, nextButton, selectButton, closeButton;
@FXML Pane arbitratorProfile;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public ArbitratorBrowserViewCB(ViewLoader viewLoader, AccountSettings accountSettings, Persistence persistence,
MessageService messageService) {
this.viewLoader = viewLoader;
this.accountSettings = accountSettings;
this.persistence = persistence;
this.messageService = messageService;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
messageService.addArbitratorListener(this);
messageService.getArbitrators(LanguageUtil.getDefaultLanguageLocale());
loadView(Navigation.Item.ARBITRATOR_PROFILE);
checkButtonState();
super.initialize(url, rb);
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Navigation
///////////////////////////////////////////////////////////////////////////////////////////
/* public Initializable loadViewAndGetChildController(Navigation.Item item) {
final ViewLoader loader = new ViewLoader(getClass().getResource(item.getFxmlUrl()));
try {
final Node view = loader.load();
arbitratorProfileViewCB = loader.getController();
arbitratorProfileViewCB.setParentController(this);
((Pane) root).getChildren().set(0, view);
return arbitratorProfileViewCB;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}*/
///////////////////////////////////////////////////////////////////////////////////////////
// Navigation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected Initializable loadView(Navigation.Item navigationItem) {
super.loadView(navigationItem);
ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl());
((Pane) root).getChildren().set(0, loaded.view);
Initializable childController = arbitratorProfileViewCB = (ArbitratorProfileViewCB) loaded.controller;
((ViewCB) childController).setParent(this);
return childController;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: ArbitratorListener
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onArbitratorAdded(Arbitrator arbitrator) {
}
@Override
public void onArbitratorsReceived(List<Arbitrator> arbitrators) {
allArbitrators.clear();
allArbitrators.addAll(arbitrators);
if (!allArbitrators.isEmpty()) {
index = 0;
currentArbitrator = allArbitrators.get(index);
arbitratorProfileViewCB.applyArbitrator(currentArbitrator);
checkButtonState();
}
}
@Override
public void onArbitratorRemoved(Arbitrator arbitrator) {
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
public void onPrevious() {
if (index > 0) {
index--;
currentArbitrator = allArbitrators.get(index);
arbitratorProfileViewCB.applyArbitrator(currentArbitrator);
}
checkButtonState();
}
@FXML
public void onNext() {
if (index < allArbitrators.size() - 1) {
index++;
currentArbitrator = allArbitrators.get(index);
arbitratorProfileViewCB.applyArbitrator(currentArbitrator);
}
checkButtonState();
}
@FXML
public void onSelect() {
accountSettings.addAcceptedArbitrator(currentArbitrator);
persistence.write(accountSettings);
}
@FXML
public void onClose() {
Stage stage = (Stage) root.getScene().getWindow();
stage.close();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void checkButtonState() {
prevButton.setDisable(index < 1);
nextButton.setDisable(index == allArbitrators.size() - 1 || index == -1);
}
}

View File

@ -19,7 +19,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.arbitrator.profile.ArbitratorProfileViewCB"
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.arbitrator.profile.ArbitratorProfileView"
hgap="5.0" vgap="5.0" AnchorPane.bottomAnchor="80.0" AnchorPane.leftAnchor="10.0"
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"
xmlns:fx="http://javafx.com/fxml">

View File

@ -18,86 +18,31 @@
package io.bitsquare.gui.main.account.arbitrator.profile;
import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.persistence.Persistence;
import io.bitsquare.settings.Preferences;
import java.net.URL;
import java.util.ResourceBundle;
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
public class ArbitratorProfileViewCB extends CachedViewCB {
private final Preferences preferences;
private final Persistence persistence;
private final BSFormatter formatter;
@FxmlView
public class ArbitratorProfileView extends AbstractView {
@FXML Label nameLabel;
@FXML TextField nameTextField, languagesTextField, reputationTextField,
feeTextField, methodsTextField, passiveServiceFeeTextField,
idVerificationsTextField, webPageTextField, maxTradeVolumeTextField;
@FXML TextArea descriptionTextArea;
@FXML TextField nameTextField, languagesTextField, reputationTextField, feeTextField, methodsTextField,
passiveServiceFeeTextField, idVerificationsTextField, webPageTextField, maxTradeVolumeTextField;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
private final BSFormatter formatter;
@Inject
public ArbitratorProfileViewCB(Preferences preferences, Persistence persistence,
BSFormatter formatter) {
this.preferences = preferences;
this.persistence = persistence;
// ApplicationPreferences persistedApplicationPreferences = (ApplicationPreferences) storage
// .read(settings.getClass().getName());
// settings.applyPersistedSettings(persistedApplicationPreferences);
public ArbitratorProfileView(BSFormatter formatter) {
this.formatter = formatter;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public Methods
///////////////////////////////////////////////////////////////////////////////////////////
public void applyArbitrator(Arbitrator arbitrator) {
if (arbitrator != null && arbitrator.getIdType() != null) {
String name = "";
@ -125,6 +70,5 @@ public class ArbitratorProfileViewCB extends CachedViewCB {
descriptionTextArea.setText(arbitrator.getDescription());
}
}
}

View File

@ -21,7 +21,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="root"
fx:controller="io.bitsquare.gui.main.account.arbitrator.registration.ArbitratorRegistrationViewCB"
fx:controller="io.bitsquare.gui.main.account.arbitrator.registration.ArbitratorRegistrationView"
prefHeight="600" prefWidth="800" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="10.0"
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"
xmlns:fx="http://javafx.com/fxml">

View File

@ -20,7 +20,6 @@ package io.bitsquare.gui.main.account.arbitrator.registration;
import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.arbitrator.Reputation;
import io.bitsquare.btc.WalletService;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.BSResources;
@ -38,70 +37,61 @@ import org.bitcoinj.core.Wallet;
import org.bitcoinj.core.WalletEventListener;
import org.bitcoinj.script.Script;
import java.net.URL;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.inject.Inject;
import viewfx.view.FxmlView;
import viewfx.view.support.ActivatableView;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@FxmlView
public class ArbitratorRegistrationView extends ActivatableView<AnchorPane, Void> {
// TODO Arbitration is very basic yet
public class ArbitratorRegistrationViewCB extends CachedViewCB {
private static final Logger log = LoggerFactory.getLogger(ArbitratorRegistrationViewCB.class);
@FXML Accordion accordion;
@FXML TextArea descriptionTextArea;
@FXML Button saveProfileButton, paymentDoneButton;
@FXML Label nameLabel, infoLabel, copyIcon, confirmationLabel;
@FXML ComboBox<Locale> languageComboBox;
@FXML ComboBox<Arbitrator.ID_TYPE> idTypeComboBox;
@FXML ComboBox<Arbitrator.METHOD> methodsComboBox;
@FXML ConfidenceProgressIndicator progressIndicator;
@FXML ComboBox<Arbitrator.ID_VERIFICATION> idVerificationsComboBox;
@FXML TitledPane profileTitledPane, paySecurityDepositTitledPane;
@FXML TextField nameTextField, idTypeTextField, languagesTextField, maxTradeVolumeTextField,
passiveServiceFeeTextField, minPassiveServiceFeeTextField, arbitrationFeeTextField,
minArbitrationFeeTextField, methodsTextField, idVerificationsTextField, webPageTextField,
securityDepositAddressTextField, balanceTextField;
private boolean isEditMode;
private Arbitrator.ID_TYPE idType;
private List<Locale> languageList = new ArrayList<>();
private List<Arbitrator.METHOD> methodList = new ArrayList<>();
private List<Arbitrator.ID_VERIFICATION> idVerificationList = new ArrayList<>();
private Arbitrator arbitrator = new Arbitrator();
private final Persistence persistence;
private final WalletService walletService;
private final MessageService messageService;
private final User user;
private final BSFormatter formatter;
private Arbitrator arbitrator = new Arbitrator();
private boolean isEditMode;
private List<Locale> languageList = new ArrayList<>();
private List<Arbitrator.METHOD> methodList = new ArrayList<>();
private List<Arbitrator.ID_VERIFICATION> idVerificationList = new ArrayList<>();
private Arbitrator.ID_TYPE idType;
@FXML Accordion accordion;
@FXML TitledPane profileTitledPane, paySecurityDepositTitledPane;
@FXML Button saveProfileButton, paymentDoneButton;
@FXML Label nameLabel, infoLabel, copyIcon, confirmationLabel;
@FXML ComboBox<Locale> languageComboBox;
@FXML ComboBox<Arbitrator.ID_TYPE> idTypeComboBox;
@FXML ComboBox<Arbitrator.METHOD> methodsComboBox;
@FXML ComboBox<Arbitrator.ID_VERIFICATION> idVerificationsComboBox;
@FXML TextField nameTextField, idTypeTextField, languagesTextField, maxTradeVolumeTextField,
passiveServiceFeeTextField, minPassiveServiceFeeTextField, arbitrationFeeTextField,
minArbitrationFeeTextField, methodsTextField, idVerificationsTextField, webPageTextField,
securityDepositAddressTextField, balanceTextField;
@FXML TextArea descriptionTextArea;
@FXML ConfidenceProgressIndicator progressIndicator;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private ArbitratorRegistrationViewCB(Persistence persistence, WalletService walletService,
MessageService messageService, User user, BSFormatter formatter) {
private ArbitratorRegistrationView(Persistence persistence, WalletService walletService,
MessageService messageService, User user, BSFormatter formatter) {
this.persistence = persistence;
this.walletService = walletService;
this.messageService = messageService;
@ -109,15 +99,8 @@ public class ArbitratorRegistrationViewCB extends CachedViewCB {
this.formatter = formatter;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
public void initialize() {
accordion.setExpandedPane(profileTitledPane);
Arbitrator persistedArbitrator = (Arbitrator) persistence.read(arbitrator);
@ -137,7 +120,6 @@ public class ArbitratorRegistrationViewCB extends CachedViewCB {
return locale.getDisplayLanguage();
}
@Override
public Locale fromString(String s) {
return null;
@ -147,13 +129,11 @@ public class ArbitratorRegistrationViewCB extends CachedViewCB {
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;
@ -163,13 +143,11 @@ public class ArbitratorRegistrationViewCB extends CachedViewCB {
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;
@ -179,13 +157,11 @@ public class ArbitratorRegistrationViewCB extends CachedViewCB {
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;
@ -193,28 +169,6 @@ public class ArbitratorRegistrationViewCB extends CachedViewCB {
});
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public Methods
///////////////////////////////////////////////////////////////////////////////////////////
public void setEditMode(boolean isEditMode) {
this.isEditMode = isEditMode;
@ -225,11 +179,6 @@ public class ArbitratorRegistrationViewCB extends CachedViewCB {
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
public void onSelectIDType() {
idType = idTypeComboBox.getSelectionModel().getSelectedItem();
@ -286,7 +235,6 @@ public class ArbitratorRegistrationViewCB extends CachedViewCB {
methodsTextField.setText("");
}
@FXML
public void onAddIDVerification() {
Arbitrator.ID_VERIFICATION idVerification = idVerificationsComboBox.getSelectionModel().getSelectedItem();
@ -329,11 +277,6 @@ public class ArbitratorRegistrationViewCB extends CachedViewCB {
public void onPaymentDone() {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void setupPaySecurityDepositScreen() {
infoLabel.setText("You need to pay 2 x the max. trading volume as security deposit.\n\nThat payment will be " +
"locked into a MultiSig fund and be refunded when you leave the arbitration pool.\nIn case of fraud " +
@ -426,7 +369,6 @@ public class ArbitratorRegistrationViewCB extends CachedViewCB {
}
}
private Arbitrator getEditedArbitrator() {
String pubKeyAsHex = walletService.getArbitratorDepositAddressEntry().getPubKeyAsHexString();
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getMessagePublicKey());

View File

@ -1,78 +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.main.account.content.changepassword;
import io.bitsquare.gui.UIModel;
import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class ChangePasswordModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(ChangePasswordModel.class);
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private ChangePasswordModel() {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize() {
super.initialize();
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
void savePassword(String password) {
//TODO Implement password encryption for wallet
}
}

View File

@ -22,7 +22,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.changepassword.ChangePasswordViewCB"
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.changepassword.ChangePasswordView"
hgap="5.0" vgap="5.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"

View File

@ -0,0 +1,83 @@
/*
* 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.main.account.content.changepassword;
import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import javax.inject.Inject;
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 ChangePasswordView extends InitializableView<GridPane, ChangePasswordViewModel> implements Wizard.Step {
@FXML HBox buttonsHBox;
@FXML Button saveButton, skipButton;
@FXML PasswordField oldPasswordField, passwordField, repeatedPasswordField;
private Wizard parent;
@Inject
private ChangePasswordView(ChangePasswordViewModel model) {
super(model);
}
@Override
public void initialize() {
passwordField.textProperty().bindBidirectional(model.passwordField);
repeatedPasswordField.textProperty().bindBidirectional(model.repeatedPasswordField);
saveButton.disableProperty().bind(model.saveButtonDisabled);
}
@Override
public void setParent(Wizard parent) {
this.parent = parent;
}
@Override
public void hideWizardNavigation() {
buttonsHBox.getChildren().remove(skipButton);
}
@FXML
private void onSaved() {
if (model.requestSavePassword())
parent.nextStep(this);
else
log.debug(model.getErrorMessage()); // TODO use validating TF
}
@FXML
private void onOpenHelp() {
Help.openWindow(HelpId.SETUP_PASSWORD);
}
@FXML
private void onSkipped() {
parent.nextStep(this);
}
}

View File

@ -1,130 +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.main.account.content.changepassword;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.main.account.MultiStepNavigation;
import io.bitsquare.gui.main.account.content.ContextAware;
import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ChangePasswordViewCB extends CachedViewCB<ChangePasswordPM> implements ContextAware {
private static final Logger log = LoggerFactory.getLogger(ChangePasswordViewCB.class);
@FXML HBox buttonsHBox;
@FXML Button saveButton, skipButton;
@FXML PasswordField oldPasswordField, passwordField, repeatedPasswordField;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private ChangePasswordViewCB(ChangePasswordPM presentationModel) {
super(presentationModel);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
passwordField.textProperty().bindBidirectional(presentationModel.passwordField);
repeatedPasswordField.textProperty().bindBidirectional(presentationModel.repeatedPasswordField);
saveButton.disableProperty().bind(presentationModel.saveButtonDisabled);
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// ContextAware implementation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void useSettingsContext(boolean useSettingsContext) {
if (useSettingsContext)
buttonsHBox.getChildren().remove(skipButton);
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
private void onSaved() {
boolean result = presentationModel.requestSavePassword();
if (result) {
if (parent instanceof MultiStepNavigation)
((MultiStepNavigation) parent).nextStep(this);
}
else {
log.debug(presentationModel.getErrorMessage()); // TODO use validating TF
}
}
@FXML
private void onOpenHelp() {
Help.openWindow(HelpId.SETUP_PASSWORD);
}
@FXML
private void onSkipped() {
if (parent instanceof MultiStepNavigation)
((MultiStepNavigation) parent).nextStep(this);
}
}

View File

@ -17,22 +17,19 @@
package io.bitsquare.gui.main.account.content.changepassword;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.gui.util.validation.PasswordValidator;
import com.google.inject.Inject;
import viewfx.model.ViewModel;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class ChangePasswordPM extends PresentationModel<ChangePasswordModel> {
private static final Logger log = LoggerFactory.getLogger(ChangePasswordPM.class);
class ChangePasswordViewModel implements ViewModel {
private final PasswordValidator passwordValidator;
@ -43,13 +40,8 @@ class ChangePasswordPM extends PresentationModel<ChangePasswordModel> {
final BooleanProperty saveButtonDisabled = new SimpleBooleanProperty(true);
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private ChangePasswordPM(ChangePasswordModel model, PasswordValidator passwordValidator) {
super(model);
public ChangePasswordViewModel(PasswordValidator passwordValidator) {
this.passwordValidator = passwordValidator;
passwordField.addListener((ov) -> saveButtonDisabled.set(!validate()));
@ -57,56 +49,23 @@ class ChangePasswordPM extends PresentationModel<ChangePasswordModel> {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize() {
super.initialize();
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public
///////////////////////////////////////////////////////////////////////////////////////////
boolean requestSavePassword() {
if (validate()) {
model.savePassword(passwordField.get());
savePassword(passwordField.get());
return true;
}
return false;
}
void savePassword(String password) {
//TODO Implement password encryption for wallet
}
String getErrorMessage() {
return errorMessage;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private boolean validate() {
InputValidator.ValidationResult result = passwordValidator.validate(passwordField.get());
if (result.isValid) {

View File

@ -20,7 +20,6 @@ package io.bitsquare.gui.main.account.content.fiat;
import io.bitsquare.account.AccountSettings;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.gui.UIModel;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.CountryUtil;
import io.bitsquare.locale.CurrencyUtil;
@ -32,6 +31,9 @@ import com.google.inject.Inject;
import java.util.Currency;
import viewfx.model.Activatable;
import viewfx.model.DataModel;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
@ -41,11 +43,7 @@ import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class FiatAccountModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(FiatAccountModel.class);
class FiatAccountDataModel implements Activatable, DataModel {
private final User user;
private final AccountSettings accountSettings;
@ -70,51 +68,24 @@ class FiatAccountModel extends UIModel {
final ObservableList<Region> allRegions = FXCollections.observableArrayList(CountryUtil.getAllRegions());
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
FiatAccountModel(User user, Persistence persistence, AccountSettings accountSettings) {
public FiatAccountDataModel(User user, Persistence persistence, AccountSettings accountSettings) {
this.persistence = persistence;
this.user = user;
this.accountSettings = accountSettings;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize() {
super.initialize();
}
@Override
public void activate() {
super.activate();
allBankAccounts.setAll(user.getBankAccounts());
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
// no-op
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public
///////////////////////////////////////////////////////////////////////////////////////////
void saveBankAccount() {
BankAccount bankAccount = new BankAccount(type.get(),
@ -168,19 +139,11 @@ class FiatAccountModel extends UIModel {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
ObservableList<Country> getAllCountriesFor(Region selectedRegion) {
return FXCollections.observableArrayList(CountryUtil.getAllCountriesFor(selectedRegion));
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
void setType(BankAccountType type) {
this.type.set(type);
@ -203,10 +166,6 @@ class FiatAccountModel extends UIModel {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void reset() {
title.set(null);
holderName.set(null);

View File

@ -24,7 +24,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.fiat.FiatAccountViewCB" hgap="5.0"
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.fiat.FiatAccountView" hgap="5.0"
vgap="5.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"

View File

@ -19,12 +19,9 @@ package io.bitsquare.gui.main.account.content.fiat;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.OverlayManager;
import io.bitsquare.gui.components.InputTextField;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.main.account.MultiStepNavigation;
import io.bitsquare.gui.main.account.content.ContextAware;
import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import io.bitsquare.gui.util.validation.InputValidator;
@ -32,15 +29,16 @@ import io.bitsquare.locale.BSResources;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.Region;
import java.net.URL;
import java.util.ArrayList;
import java.util.Currency;
import java.util.List;
import java.util.ResourceBundle;
import javax.inject.Inject;
import viewfx.view.FxmlView;
import viewfx.view.Wizard;
import viewfx.view.support.ActivatableViewAndModel;
import javafx.collections.ListChangeListener;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
@ -51,14 +49,10 @@ import org.controlsfx.control.action.AbstractAction;
import org.controlsfx.control.action.Action;
import org.controlsfx.dialog.Dialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static javafx.beans.binding.Bindings.createBooleanBinding;
public class FiatAccountViewCB extends CachedViewCB<FiatAccountPm> implements ContextAware {
private static final Logger log = LoggerFactory.getLogger(FiatAccountViewCB.class);
@FxmlView
public class FiatAccountView extends ActivatableViewAndModel<GridPane, FiatAccountViewModel> implements Wizard.Step {
@FXML HBox buttonsHBox;
@FXML ComboBox<Region> regionComboBox;
@ -68,96 +62,66 @@ public class FiatAccountViewCB extends CachedViewCB<FiatAccountPm> implements Co
@FXML ComboBox<BankAccount> selectionComboBox;
@FXML ComboBox<BankAccountType> typesComboBox;
@FXML ComboBox<Currency> currencyComboBox;
private Wizard parent;
private final OverlayManager overlayManager;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
FiatAccountViewCB(FiatAccountPm presentationModel, OverlayManager overlayManager) {
super(presentationModel);
public FiatAccountView(FiatAccountViewModel model, OverlayManager overlayManager) {
super(model);
this.overlayManager = overlayManager;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
typesComboBox.setItems(presentationModel.getAllTypes());
typesComboBox.setConverter(presentationModel.getTypesConverter());
selectionComboBox.setConverter(presentationModel.getSelectionConverter());
currencyComboBox.setItems(presentationModel.getAllCurrencies());
currencyComboBox.setConverter(presentationModel.getCurrencyConverter());
regionComboBox.setItems(presentationModel.getAllRegions());
regionComboBox.setConverter(presentationModel.getRegionConverter());
countryComboBox.setConverter(presentationModel.getCountryConverter());
public void initialize() {
typesComboBox.setItems(model.getAllTypes());
typesComboBox.setConverter(model.getTypesConverter());
selectionComboBox.setConverter(model.getSelectionConverter());
currencyComboBox.setItems(model.getAllCurrencies());
currencyComboBox.setConverter(model.getCurrencyConverter());
regionComboBox.setItems(model.getAllRegions());
regionComboBox.setConverter(model.getRegionConverter());
countryComboBox.setConverter(model.getCountryConverter());
nameOfBankTextField.setValidator(presentationModel.getBankAccountNumberValidator());
holderNameTextField.setValidator(presentationModel.getBankAccountNumberValidator());
primaryIDTextField.setValidator(presentationModel.getBankAccountNumberValidator());
secondaryIDTextField.setValidator(presentationModel.getBankAccountNumberValidator());
super.initialize(url, rb);
nameOfBankTextField.setValidator(model.getBankAccountNumberValidator());
holderNameTextField.setValidator(model.getBankAccountNumberValidator());
primaryIDTextField.setValidator(model.getBankAccountNumberValidator());
secondaryIDTextField.setValidator(model.getBankAccountNumberValidator());
}
@Override
public void activate() {
super.activate();
public void doActivate() {
setupListeners();
setupBindings();
selectionComboBox.setItems(presentationModel.getAllBankAccounts());
selectionComboBox.setItems(model.getAllBankAccounts());
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// ContextAware implementation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void useSettingsContext(boolean useSettingsContext) {
if (useSettingsContext)
buttonsHBox.getChildren().remove(completedButton);
public void setParent(Wizard parent) {
this.parent = parent;
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void hideWizardNavigation() {
buttonsHBox.getChildren().remove(completedButton);
}
@FXML
void onSelectAccount() {
if (selectionComboBox.getSelectionModel().getSelectedItem() != null)
presentationModel.selectBankAccount(selectionComboBox.getSelectionModel().getSelectedItem());
model.selectBankAccount(selectionComboBox.getSelectionModel().getSelectedItem());
}
@FXML
void onSelectType() {
presentationModel.setType(typesComboBox.getSelectionModel().getSelectedItem());
model.setType(typesComboBox.getSelectionModel().getSelectedItem());
}
@FXML
void onSelectCurrency() {
presentationModel.setCurrency(currencyComboBox.getSelectionModel().getSelectedItem());
model.setCurrency(currencyComboBox.getSelectionModel().getSelectedItem());
}
@FXML
@ -165,19 +129,19 @@ public class FiatAccountViewCB extends CachedViewCB<FiatAccountPm> implements Co
countryComboBox.setVisible(true);
Region region = regionComboBox.getSelectionModel().getSelectedItem();
if (region != null)
countryComboBox.setItems(presentationModel.getAllCountriesFor(region));
countryComboBox.setItems(model.getAllCountriesFor(region));
}
@FXML
void onSelectCountry() {
Country country = countryComboBox.getSelectionModel().getSelectedItem();
if (country != null)
presentationModel.setCountry(country);
model.setCountry(country);
}
@FXML
void onSave() {
InputValidator.ValidationResult result = presentationModel.requestSaveBankAccount();
InputValidator.ValidationResult result = model.requestSaveBankAccount();
if (result.isValid) {
selectionComboBox.getSelectionModel().select(null);
Popups.openInfoPopup("Your payments account has been saved.",
@ -187,13 +151,12 @@ public class FiatAccountViewCB extends CachedViewCB<FiatAccountPm> implements Co
@FXML
void onCompleted() {
if (parent instanceof MultiStepNavigation)
((MultiStepNavigation) parent).nextStep(this);
parent.nextStep(this);
}
@FXML
void onRemoveAccount() {
presentationModel.removeBankAccount();
model.removeBankAccount();
selectionComboBox.getSelectionModel().select(null);
}
@ -208,26 +171,22 @@ public class FiatAccountViewCB extends CachedViewCB<FiatAccountPm> implements Co
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void setupListeners() {
presentationModel.type.addListener((ov, oldValue, newValue) -> {
model.type.addListener((ov, oldValue, newValue) -> {
if (newValue != null)
typesComboBox.getSelectionModel().select(typesComboBox.getItems().indexOf(newValue));
else
typesComboBox.getSelectionModel().clearSelection();
});
presentationModel.currency.addListener((ov, oldValue, newValue) -> {
model.currency.addListener((ov, oldValue, newValue) -> {
if (newValue != null)
currencyComboBox.getSelectionModel().select(currencyComboBox.getItems().indexOf(newValue));
else
currencyComboBox.getSelectionModel().clearSelection();
});
presentationModel.country.addListener((ov, oldValue, newValue) -> {
model.country.addListener((ov, oldValue, newValue) -> {
if (newValue != null) {
int regionIndex = regionComboBox.getItems().indexOf(newValue.getRegion());
if (regionIndex >= 0 && regionIndex < regionComboBox.getItems().size())
@ -243,7 +202,7 @@ public class FiatAccountViewCB extends CachedViewCB<FiatAccountPm> implements Co
}
});
presentationModel.getCountryNotInAcceptedCountriesList().addListener((ov, oldValue, newValue) -> {
model.getCountryNotInAcceptedCountriesList().addListener((ov, oldValue, newValue) -> {
if (newValue) {
overlayManager.blurContent();
List<Action> actions = new ArrayList<>();
@ -271,33 +230,32 @@ public class FiatAccountViewCB extends CachedViewCB<FiatAccountPm> implements Co
actions);
if (Popups.isYes(response))
presentationModel.addCountryToAcceptedCountriesList();
model.addCountryToAcceptedCountriesList();
}
});
presentationModel.getAllBankAccounts().addListener((ListChangeListener<BankAccount>) change ->
completedButton.setDisable(presentationModel.getAllBankAccounts().isEmpty()));
completedButton.setDisable(presentationModel.getAllBankAccounts().isEmpty());
model.getAllBankAccounts().addListener((ListChangeListener<BankAccount>) change ->
completedButton.setDisable(model.getAllBankAccounts().isEmpty()));
completedButton.setDisable(model.getAllBankAccounts().isEmpty());
}
private void setupBindings() {
// input
nameOfBankTextField.textProperty().bindBidirectional(presentationModel.title);
holderNameTextField.textProperty().bindBidirectional(presentationModel.holderName);
primaryIDTextField.textProperty().bindBidirectional(presentationModel.primaryID);
secondaryIDTextField.textProperty().bindBidirectional(presentationModel.secondaryID);
nameOfBankTextField.textProperty().bindBidirectional(model.title);
holderNameTextField.textProperty().bindBidirectional(model.holderName);
primaryIDTextField.textProperty().bindBidirectional(model.primaryID);
secondaryIDTextField.textProperty().bindBidirectional(model.secondaryID);
primaryIDTextField.promptTextProperty().bind(presentationModel.primaryIDPrompt);
secondaryIDTextField.promptTextProperty().bind(presentationModel.secondaryIDPrompt);
selectionComboBox.promptTextProperty().bind(presentationModel.selectionPrompt);
selectionComboBox.disableProperty().bind(presentationModel.selectionDisable);
primaryIDTextField.promptTextProperty().bind(model.primaryIDPrompt);
secondaryIDTextField.promptTextProperty().bind(model.secondaryIDPrompt);
selectionComboBox.promptTextProperty().bind(model.selectionPrompt);
selectionComboBox.disableProperty().bind(model.selectionDisable);
saveButton.disableProperty().bind(presentationModel.saveButtonDisable);
saveButton.disableProperty().bind(model.saveButtonDisable);
removeBankAccountButton.disableProperty().bind(createBooleanBinding(() ->
(selectionComboBox.getSelectionModel().selectedIndexProperty().get() == -1),
selectionComboBox.getSelectionModel().selectedIndexProperty()));
}
}

View File

@ -19,7 +19,6 @@ package io.bitsquare.gui.main.account.content.fiat;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.util.validation.BankAccountNumberValidator;
import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.locale.BSResources;
@ -30,6 +29,9 @@ import com.google.inject.Inject;
import java.util.Currency;
import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
@ -40,11 +42,7 @@ import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.util.StringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class FiatAccountPm extends PresentationModel<FiatAccountModel> {
private static final Logger log = LoggerFactory.getLogger(FiatAccountPm.class);
class FiatAccountViewModel extends ActivatableWithDelegate<FiatAccountDataModel> implements ViewModel {
private final BankAccountNumberValidator bankAccountNumberValidator;
@ -62,96 +60,60 @@ class FiatAccountPm extends PresentationModel<FiatAccountModel> {
final ObjectProperty<Currency> currency = new SimpleObjectProperty<>();
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
FiatAccountPm(FiatAccountModel model, BankAccountNumberValidator bankAccountNumberValidator) {
super(model);
public FiatAccountViewModel(FiatAccountDataModel delegate, BankAccountNumberValidator bankAccountNumberValidator) {
super(delegate);
this.bankAccountNumberValidator = bankAccountNumberValidator;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize() {
// input
title.bindBidirectional(model.title);
holderName.bindBidirectional(model.holderName);
primaryID.bindBidirectional(model.primaryID);
secondaryID.bindBidirectional(model.secondaryID);
type.bindBidirectional(model.type);
country.bindBidirectional(model.country);
currency.bindBidirectional(model.currency);
title.bindBidirectional(delegate.title);
holderName.bindBidirectional(delegate.holderName);
primaryID.bindBidirectional(delegate.primaryID);
secondaryID.bindBidirectional(delegate.secondaryID);
type.bindBidirectional(delegate.type);
country.bindBidirectional(delegate.country);
currency.bindBidirectional(delegate.currency);
primaryIDPrompt.bind(model.primaryIDPrompt);
secondaryIDPrompt.bind(model.secondaryIDPrompt);
primaryIDPrompt.bind(delegate.primaryIDPrompt);
secondaryIDPrompt.bind(delegate.secondaryIDPrompt);
selectionPrompt.set("No bank account available");
selectionDisable.set(true);
model.title.addListener((ov, oldValue, newValue) -> validateInput());
delegate.title.addListener((ov, oldValue, newValue) -> validateInput());
holderName.addListener((ov, oldValue, newValue) -> validateInput());
primaryID.addListener((ov, oldValue, newValue) -> validateInput());
secondaryID.addListener((ov, oldValue, newValue) -> validateInput());
super.initialize();
}
@Override
public void activate() {
super.activate();
model.allBankAccounts.addListener((ListChangeListener<BankAccount>) change -> applyAllBankAccounts());
public void doActivate() {
delegate.allBankAccounts.addListener((ListChangeListener<BankAccount>) change -> applyAllBankAccounts());
applyAllBankAccounts();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public
///////////////////////////////////////////////////////////////////////////////////////////
InputValidator.ValidationResult requestSaveBankAccount() {
InputValidator.ValidationResult result = validateInput();
if (result.isValid) {
model.saveBankAccount();
delegate.saveBankAccount();
}
return result;
}
void removeBankAccount() {
model.removeBankAccount();
delegate.removeBankAccount();
}
void addCountryToAcceptedCountriesList() {
model.addCountryToAcceptedCountriesList();
delegate.addCountryToAcceptedCountriesList();
}
void selectBankAccount(BankAccount bankAccount) {
model.selectBankAccount(bankAccount);
delegate.selectBankAccount(bankAccount);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Converters
///////////////////////////////////////////////////////////////////////////////////////////
StringConverter<BankAccountType> getTypesConverter() {
return new StringConverter<BankAccountType>() {
@Override
@ -225,32 +187,28 @@ class FiatAccountPm extends PresentationModel<FiatAccountModel> {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
ObservableList<BankAccountType> getAllTypes() {
return model.allTypes;
return delegate.allTypes;
}
ObservableList<BankAccount> getAllBankAccounts() {
return model.allBankAccounts;
return delegate.allBankAccounts;
}
ObservableList<Currency> getAllCurrencies() {
return model.allCurrencies;
return delegate.allCurrencies;
}
ObservableList<Region> getAllRegions() {
return model.allRegions;
return delegate.allRegions;
}
BooleanProperty getCountryNotInAcceptedCountriesList() {
return model.countryNotInAcceptedCountriesList;
return delegate.countryNotInAcceptedCountriesList;
}
ObservableList<Country> getAllCountriesFor(Region selectedRegion) {
return model.getAllCountriesFor(selectedRegion);
return delegate.getAllCountriesFor(selectedRegion);
}
BankAccountNumberValidator getBankAccountNumberValidator() {
@ -258,32 +216,24 @@ class FiatAccountPm extends PresentationModel<FiatAccountModel> {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
void setType(BankAccountType type) {
model.setType(type);
delegate.setType(type);
validateInput();
}
void setCountry(Country country) {
model.setCountry(country);
delegate.setCountry(country);
validateInput();
}
void setCurrency(Currency currency) {
model.setCurrency(currency);
delegate.setCurrency(currency);
validateInput();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void applyAllBankAccounts() {
if (model.allBankAccounts.isEmpty()) {
if (delegate.allBankAccounts.isEmpty()) {
selectionPrompt.set("No bank account available");
selectionDisable.set(true);
}
@ -294,23 +244,23 @@ class FiatAccountPm extends PresentationModel<FiatAccountModel> {
}
private InputValidator.ValidationResult validateInput() {
InputValidator.ValidationResult result = bankAccountNumberValidator.validate(model.title.get());
InputValidator.ValidationResult result = bankAccountNumberValidator.validate(delegate.title.get());
if (result.isValid) {
result = bankAccountNumberValidator.validate(model.holderName.get());
result = bankAccountNumberValidator.validate(delegate.holderName.get());
if (result.isValid) {
result = bankAccountNumberValidator.validate(model.primaryID.get());
result = bankAccountNumberValidator.validate(delegate.primaryID.get());
if (result.isValid) {
result = bankAccountNumberValidator.validate(model.secondaryID.get());
result = bankAccountNumberValidator.validate(delegate.secondaryID.get());
if (result.isValid) {
if (model.currency.get() == null)
if (delegate.currency.get() == null)
result = new InputValidator.ValidationResult(false,
"You have not selected a currency");
if (result.isValid) {
if (model.country.get() == null)
if (delegate.country.get() == null)
result = new InputValidator.ValidationResult(false,
"You have not selected a country of the payments account");
if (result.isValid) {
if (model.type.get() == null)
if (delegate.type.get() == null)
result = new InputValidator.ValidationResult(false,
"You have not selected a payments method");
}

View File

@ -22,7 +22,6 @@ import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.arbitrator.Reputation;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.gui.UIModel;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.CountryUtil;
import io.bitsquare.locale.CurrencyUtil;
@ -44,6 +43,9 @@ import java.util.Currency;
import java.util.List;
import java.util.Locale;
import viewfx.model.Activatable;
import viewfx.model.DataModel;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
@ -51,11 +53,7 @@ import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class IrcAccountModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(IrcAccountModel.class);
class IrcAccountDataModel implements Activatable, DataModel {
private final User user;
private final AccountSettings accountSettings;
@ -72,28 +70,13 @@ class IrcAccountModel extends UIModel {
final ObservableList<BankAccount> allBankAccounts = FXCollections.observableArrayList();
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
IrcAccountModel(User user, Persistence persistence, AccountSettings accountSettings,
MessageService messageService) {
public IrcAccountDataModel(User user, Persistence persistence, AccountSettings accountSettings,
MessageService messageService) {
this.persistence = persistence;
this.user = user;
this.accountSettings = accountSettings;
this.messageService = messageService;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize() {
super.initialize();
if (accountSettings.getAcceptedArbitrators().isEmpty())
addMockArbitrator();
@ -101,27 +84,14 @@ class IrcAccountModel extends UIModel {
@Override
public void activate() {
super.activate();
allBankAccounts.setAll(user.getBankAccounts());
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
// no-op
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public
///////////////////////////////////////////////////////////////////////////////////////////
void saveBankAccount() {
BankAccount bankAccount = new BankAccount(type.get(),
currency.get(),
@ -137,19 +107,11 @@ class IrcAccountModel extends UIModel {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
ObservableList<Country> getAllCountriesFor(Region selectedRegion) {
return FXCollections.observableArrayList(CountryUtil.getAllCountriesFor(selectedRegion));
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
void setType(BankAccountType type) {
this.type.set(type);
}
@ -159,10 +121,6 @@ class IrcAccountModel extends UIModel {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void reset() {
nickName.set(null);

View File

@ -24,7 +24,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.irc.IrcAccountViewCB" hgap="5.0"
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.irc.IrcAccountView" hgap="5.0"
vgap="5.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"

View File

@ -18,38 +18,31 @@
package io.bitsquare.gui.main.account.content.irc;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.components.InputTextField;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.main.account.MultiStepNavigation;
import io.bitsquare.gui.main.account.content.ContextAware;
import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.util.Utilities;
import java.net.URL;
import java.util.Currency;
import java.util.ResourceBundle;
import javax.inject.Inject;
import viewfx.view.FxmlView;
import viewfx.view.support.ActivatableViewAndModel;
import viewfx.view.Wizard;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.util.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*
Just temporary for giving the user a possibility to test the app via simulating the bank transfer in a IRC chat.
/**
* Just temporary for giving the user a possibility to test the app via simulating the bank transfer in a IRC chat.
*/
public class IrcAccountViewCB extends CachedViewCB<IrcAccountPm> implements ContextAware {
private static final Logger log = LoggerFactory.getLogger(IrcAccountViewCB.class);
@FxmlView
public class IrcAccountView extends ActivatableViewAndModel<GridPane, IrcAccountViewModel> implements Wizard.Step {
@FXML HBox buttonsHBox;
@FXML InputTextField ircNickNameTextField;
@ -57,27 +50,19 @@ public class IrcAccountViewCB extends CachedViewCB<IrcAccountPm> implements Cont
@FXML ComboBox<BankAccountType> typesComboBox;
@FXML ComboBox<Currency> currencyComboBox;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
private Wizard parent;
@Inject
IrcAccountViewCB(IrcAccountPm presentationModel) {
super(presentationModel);
public IrcAccountView(IrcAccountViewModel model) {
super(model);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
ircNickNameTextField.setValidator(presentationModel.getNickNameValidator());
public void doActivate() {
ircNickNameTextField.setValidator(model.getNickNameValidator());
typesComboBox.setItems(presentationModel.getAllTypes());
typesComboBox.setConverter(presentationModel.getTypesConverter());
typesComboBox.setItems(model.getAllTypes());
typesComboBox.setConverter(model.getTypesConverter());
// we use a custom cell for deactivating non IRC items, later we use the standard cell and the StringConverter
typesComboBox.setCellFactory(new Callback<ListView<BankAccountType>, ListCell<BankAccountType>>() {
@Override
@ -88,7 +73,7 @@ public class IrcAccountViewCB extends CachedViewCB<IrcAccountPm> implements Cont
protected void updateItem(BankAccountType item, boolean empty) {
super.updateItem(item, empty);
setText(presentationModel.getBankAccountType(item));
setText(model.getBankAccountType(item));
if (item == null || empty) {
setGraphic(null);
@ -103,8 +88,8 @@ public class IrcAccountViewCB extends CachedViewCB<IrcAccountPm> implements Cont
});
typesComboBox.getSelectionModel().select(0);
currencyComboBox.setItems(presentationModel.getAllCurrencies());
currencyComboBox.setConverter(presentationModel.getCurrencyConverter());
currencyComboBox.setItems(model.getAllCurrencies());
currencyComboBox.setConverter(model.getCurrencyConverter());
// we use a custom cell for deactivating non EUR items, later we use the standard cell and the StringConverter
currencyComboBox.setCellFactory(new Callback<ListView<Currency>, ListCell<Currency>>() {
@Override
@ -132,13 +117,6 @@ public class IrcAccountViewCB extends CachedViewCB<IrcAccountPm> implements Cont
});
currencyComboBox.getSelectionModel().select(0);
super.initialize(url, rb);
}
@Override
public void activate() {
super.activate();
setupListeners();
setupBindings();
@ -153,48 +131,29 @@ public class IrcAccountViewCB extends CachedViewCB<IrcAccountPm> implements Cont
"bank transfer."));
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
public void setParent(Wizard parent) {
this.parent = parent;
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
public void hideWizardNavigation() {
}
///////////////////////////////////////////////////////////////////////////////////////////
// ContextAware implementation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void useSettingsContext(boolean useSettingsContext) {
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
void onSelectType() {
presentationModel.setType(typesComboBox.getSelectionModel().getSelectedItem());
model.setType(typesComboBox.getSelectionModel().getSelectedItem());
}
@FXML
void onSelectCurrency() {
presentationModel.setCurrency(currencyComboBox.getSelectionModel().getSelectedItem());
model.setCurrency(currencyComboBox.getSelectionModel().getSelectedItem());
}
@FXML
void onSave() {
InputValidator.ValidationResult result = presentationModel.requestSaveBankAccount();
if (result.isValid && parent instanceof MultiStepNavigation)
((MultiStepNavigation) parent).nextStep(this);
if (model.requestSaveBankAccount().isValid)
parent.nextStep(this);
}
@FXML
@ -212,19 +171,16 @@ public class IrcAccountViewCB extends CachedViewCB<IrcAccountPm> implements Cont
"connection.");
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void setupListeners() {
presentationModel.type.addListener((ov, oldValue, newValue) -> {
model.type.addListener((ov, oldValue, newValue) -> {
if (newValue != null)
typesComboBox.getSelectionModel().select(typesComboBox.getItems().indexOf(newValue));
else
typesComboBox.getSelectionModel().clearSelection();
});
presentationModel.currency.addListener((ov, oldValue, newValue) -> {
model.currency.addListener((ov, oldValue, newValue) -> {
if (newValue != null)
currencyComboBox.getSelectionModel().select(currencyComboBox.getItems().indexOf(newValue));
else
@ -234,10 +190,8 @@ public class IrcAccountViewCB extends CachedViewCB<IrcAccountPm> implements Cont
private void setupBindings() {
// input
ircNickNameTextField.textProperty().bindBidirectional(presentationModel.ircNickName);
saveButton.disableProperty().bind(presentationModel.saveButtonDisable);
ircNickNameTextField.textProperty().bindBidirectional(model.ircNickName);
saveButton.disableProperty().bind(model.saveButtonDisable);
}
}

View File

@ -19,7 +19,6 @@ package io.bitsquare.gui.main.account.content.irc;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.util.validation.BankAccountNumberValidator;
import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.locale.BSResources;
@ -28,6 +27,9 @@ import com.google.inject.Inject;
import java.util.Currency;
import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
@ -37,11 +39,7 @@ import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList;
import javafx.util.StringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class IrcAccountPm extends PresentationModel<IrcAccountModel> {
private static final Logger log = LoggerFactory.getLogger(IrcAccountPm.class);
class IrcAccountViewModel extends ActivatableWithDelegate<IrcAccountDataModel> implements ViewModel {
private final InputValidator nickNameValidator;
@ -51,71 +49,32 @@ class IrcAccountPm extends PresentationModel<IrcAccountModel> {
final ObjectProperty<Currency> currency = new SimpleObjectProperty<>();
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
IrcAccountPm(IrcAccountModel model, BankAccountNumberValidator nickNameValidator) {
super(model);
public IrcAccountViewModel(IrcAccountDataModel delegate, BankAccountNumberValidator nickNameValidator) {
super(delegate);
this.nickNameValidator = nickNameValidator;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize() {
// input
ircNickName.bindBidirectional(model.nickName);
type.bindBidirectional(model.type);
currency.bindBidirectional(model.currency);
ircNickName.bindBidirectional(delegate.nickName);
type.bindBidirectional(delegate.type);
currency.bindBidirectional(delegate.currency);
model.nickName.addListener((ov, oldValue, newValue) -> validateInput());
super.initialize();
delegate.nickName.addListener((ov, oldValue, newValue) -> validateInput());
}
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public
///////////////////////////////////////////////////////////////////////////////////////////
InputValidator.ValidationResult requestSaveBankAccount() {
InputValidator.ValidationResult result = validateInput();
if (result.isValid) {
model.saveBankAccount();
delegate.saveBankAccount();
}
return result;
}
ObservableList<BankAccount> getAllBankAccounts() {
return model.allBankAccounts;
return delegate.allBankAccounts;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Converters
///////////////////////////////////////////////////////////////////////////////////////////
StringConverter<BankAccountType> getTypesConverter() {
return new StringConverter<BankAccountType>() {
@Override
@ -149,16 +108,12 @@ class IrcAccountPm extends PresentationModel<IrcAccountModel> {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
ObservableList<BankAccountType> getAllTypes() {
return model.allTypes;
return delegate.allTypes;
}
ObservableList<Currency> getAllCurrencies() {
return model.allCurrencies;
return delegate.allCurrencies;
}
InputValidator getNickNameValidator() {
@ -166,33 +121,25 @@ class IrcAccountPm extends PresentationModel<IrcAccountModel> {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
void setType(BankAccountType type) {
model.setType(type);
delegate.setType(type);
validateInput();
}
void setCurrency(Currency currency) {
model.setCurrency(currency);
delegate.setCurrency(currency);
validateInput();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private InputValidator.ValidationResult validateInput() {
InputValidator.ValidationResult result = nickNameValidator.validate(model.nickName.get());
if (model.currency.get() == null)
InputValidator.ValidationResult result = nickNameValidator.validate(delegate.nickName.get());
if (delegate.currency.get() == null)
result = new InputValidator.ValidationResult(false,
"You have not selected a currency");
if (result.isValid) {
if (model.type.get() == null)
if (delegate.type.get() == null)
result = new InputValidator.ValidationResult(false,
"You have not selected a payments method");
}

View File

@ -1,79 +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.main.account.content.password;
import io.bitsquare.gui.UIModel;
import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class PasswordModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(PasswordModel.class);
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private PasswordModel() {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize() {
super.initialize();
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
void savePassword(String password) {
//TODO Implement password encryption for wallet
}
}

View File

@ -22,7 +22,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.password.PasswordViewCB" hgap="5.0"
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.password.PasswordView" hgap="5.0"
vgap="5.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"

View File

@ -0,0 +1,83 @@
/*
* 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.main.account.content.password;
import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import javax.inject.Inject;
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;
@FXML Button saveButton, skipButton;
@FXML PasswordField oldPasswordField, passwordField, repeatedPasswordField;
private Wizard parent;
@Inject
private PasswordView(PasswordViewModel model) {
super(model);
}
@Override
public void initialize() {
passwordField.textProperty().bindBidirectional(model.passwordField);
repeatedPasswordField.textProperty().bindBidirectional(model.repeatedPasswordField);
saveButton.disableProperty().bind(model.saveButtonDisabled);
}
@Override
public void setParent(Wizard parent) {
this.parent = parent;
}
@Override
public void hideWizardNavigation() {
buttonsHBox.getChildren().remove(skipButton);
}
@FXML
private void onSaved() {
if (model.requestSavePassword())
parent.nextStep(this);
else
log.debug(model.getErrorMessage()); // TODO use validating passwordTF
}
@FXML
private void onSkipped() {
parent.nextStep(this);
}
@FXML
private void onOpenHelp() {
Help.openWindow(HelpId.SETUP_PASSWORD);
}
}

View File

@ -1,130 +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.main.account.content.password;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.main.account.MultiStepNavigation;
import io.bitsquare.gui.main.account.content.ContextAware;
import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PasswordViewCB extends CachedViewCB<PasswordPM> implements ContextAware {
private static final Logger log = LoggerFactory.getLogger(PasswordViewCB.class);
@FXML HBox buttonsHBox;
@FXML Button saveButton, skipButton;
@FXML PasswordField oldPasswordField, passwordField, repeatedPasswordField;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private PasswordViewCB(PasswordPM presentationModel) {
super(presentationModel);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
passwordField.textProperty().bindBidirectional(presentationModel.passwordField);
repeatedPasswordField.textProperty().bindBidirectional(presentationModel.repeatedPasswordField);
saveButton.disableProperty().bind(presentationModel.saveButtonDisabled);
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// ContextAware implementation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void useSettingsContext(boolean useSettingsContext) {
if (useSettingsContext)
buttonsHBox.getChildren().remove(skipButton);
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
private void onSaved() {
boolean result = presentationModel.requestSavePassword();
if (result) {
if (parent instanceof MultiStepNavigation)
((MultiStepNavigation) parent).nextStep(this);
}
else {
// TODO use validating passwordTF
log.debug(presentationModel.getErrorMessage());
}
}
@FXML
private void onSkipped() {
if (parent instanceof MultiStepNavigation)
((MultiStepNavigation) parent).nextStep(this);
}
@FXML
private void onOpenHelp() {
Help.openWindow(HelpId.SETUP_PASSWORD);
}
}

View File

@ -17,22 +17,19 @@
package io.bitsquare.gui.main.account.content.password;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.gui.util.validation.PasswordValidator;
import com.google.inject.Inject;
import viewfx.model.ViewModel;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class PasswordPM extends PresentationModel<PasswordModel> {
private static final Logger log = LoggerFactory.getLogger(PasswordPM.class);
class PasswordViewModel implements ViewModel {
private final PasswordValidator passwordValidator;
@ -43,13 +40,8 @@ class PasswordPM extends PresentationModel<PasswordModel> {
final BooleanProperty saveButtonDisabled = new SimpleBooleanProperty(true);
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private PasswordPM(PasswordModel model, PasswordValidator passwordValidator) {
super(model);
public PasswordViewModel(PasswordValidator passwordValidator) {
this.passwordValidator = passwordValidator;
passwordField.addListener((ov) -> saveButtonDisabled.set(!validate()));
@ -57,56 +49,23 @@ class PasswordPM extends PresentationModel<PasswordModel> {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize() {
super.initialize();
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public
///////////////////////////////////////////////////////////////////////////////////////////
boolean requestSavePassword() {
if (validate()) {
model.savePassword(passwordField.get());
savePassword(passwordField.get());
return true;
}
return false;
}
void savePassword(String password) {
//TODO Implement password encryption for wallet
}
String getErrorMessage() {
return errorMessage;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private boolean validate() {
InputValidator.ValidationResult result = passwordValidator.validate(passwordField.get());
if (result.isValid) {

View File

@ -21,7 +21,6 @@ import io.bitsquare.btc.AddressEntry;
import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.WalletService;
import io.bitsquare.btc.listeners.BalanceListener;
import io.bitsquare.gui.UIModel;
import io.bitsquare.persistence.Persistence;
import io.bitsquare.user.User;
@ -35,6 +34,8 @@ import com.google.inject.Inject;
import javax.annotation.Nullable;
import viewfx.model.DataModel;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
@ -45,8 +46,8 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class RegistrationModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(RegistrationModel.class);
class RegistrationDataModel implements DataModel {
private static final Logger log = LoggerFactory.getLogger(RegistrationDataModel.class);
private final WalletService walletService;
private final User user;
@ -60,26 +61,12 @@ class RegistrationModel extends UIModel {
final StringProperty payFeeErrorMessage = new SimpleStringProperty();
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private RegistrationModel(WalletService walletService, User user, Persistence persistence) {
public RegistrationDataModel(WalletService walletService, User user, Persistence persistence) {
this.walletService = walletService;
this.user = user;
this.persistence = persistence;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize() {
super.initialize();
if (walletService != null && walletService.getWallet() != null) {
addressEntry = walletService.getRegistrationAddressEntry();
@ -93,29 +80,6 @@ class RegistrationModel extends UIModel {
}
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Methods
///////////////////////////////////////////////////////////////////////////////////////////
void payFee() {
FutureCallback<Transaction> callback = new FutureCallback<Transaction>() {
@Override
@ -147,10 +111,6 @@ class RegistrationModel extends UIModel {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
WalletService getWalletService() {
return walletService;
}
@ -168,10 +128,6 @@ class RegistrationModel extends UIModel {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void updateBalance(@NotNull Coin balance) {
isWalletFunded.set(balance.compareTo(getFeeAsCoin()) >= 0);
}

View File

@ -24,7 +24,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.registration.RegistrationViewCB" hgap="5.0"
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.registration.RegistrationView" hgap="5.0"
vgap="5.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"

View File

@ -17,42 +17,34 @@
package io.bitsquare.gui.main.account.content.registration;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.OverlayManager;
import io.bitsquare.gui.components.AddressTextField;
import io.bitsquare.gui.components.BalanceTextField;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.main.account.MultiStepNavigation;
import io.bitsquare.gui.main.account.content.ContextAware;
import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import io.bitsquare.locale.BSResources;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javax.inject.Inject;
import viewfx.view.FxmlView;
import viewfx.view.Wizard;
import viewfx.view.support.InitializableView;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.controlsfx.control.action.AbstractAction;
import org.controlsfx.control.action.Action;
import org.controlsfx.dialog.Dialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RegistrationViewCB extends CachedViewCB<RegistrationPM> implements ContextAware {
private static final Logger log = LoggerFactory.getLogger(RegistrationViewCB.class);
private final OverlayManager overlayManager;
@FxmlView
public class RegistrationView extends InitializableView<GridPane, RegistrationViewModel> implements Wizard.Step {
@FXML TextField feeTextField;
@FXML AddressTextField addressTextField;
@ -61,40 +53,32 @@ public class RegistrationViewCB extends CachedViewCB<RegistrationPM> implements
@FXML Label paymentSpinnerInfoLabel;
@FXML ProgressIndicator paymentSpinner;
private Wizard parent;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
private final OverlayManager overlayManager;
@Inject
private RegistrationViewCB(RegistrationPM presentationModel, OverlayManager overlayManager) {
super(presentationModel);
private RegistrationView(RegistrationViewModel model, OverlayManager overlayManager) {
super(model);
this.overlayManager = overlayManager;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
feeTextField.setText(presentationModel.getFeeAsString());
addressTextField.setAmountAsCoin(presentationModel.getFeeAsCoin());
addressTextField.setPaymentLabel(presentationModel.getPaymentLabel());
addressTextField.setAddress(presentationModel.getAddressAsString());
public void initialize() {
feeTextField.setText(model.getFeeAsString());
addressTextField.setAmountAsCoin(model.getFeeAsCoin());
addressTextField.setPaymentLabel(model.getPaymentLabel());
addressTextField.setAddress(model.getAddressAsString());
// TODO find better solution
addressTextField.setOverlayManager(overlayManager);
balanceTextField.setup(presentationModel.getWalletService(), presentationModel.address.get(),
presentationModel.getFormatter());
balanceTextField.setup(model.getWalletService(), model.address.get(),
model.getFormatter());
payButton.disableProperty().bind(presentationModel.isPayButtonDisabled);
payButton.disableProperty().bind(model.isPayButtonDisabled);
presentationModel.requestPlaceOfferErrorMessage.addListener((o, oldValue, newValue) -> {
model.requestPlaceOfferErrorMessage.addListener((o, oldValue, newValue) -> {
if (newValue != null) {
Popups.openErrorPopup(BSResources.get("shared.error"),
BSResources.get("An error occurred when paying the registration fee"),
@ -102,14 +86,14 @@ public class RegistrationViewCB extends CachedViewCB<RegistrationPM> implements
}
});
paymentSpinnerInfoLabel.visibleProperty().bind(presentationModel.isPaymentSpinnerVisible);
paymentSpinnerInfoLabel.visibleProperty().bind(model.isPaymentSpinnerVisible);
presentationModel.isPaymentSpinnerVisible.addListener((ov, oldValue, newValue) -> {
model.isPaymentSpinnerVisible.addListener((ov, oldValue, newValue) -> {
paymentSpinner.setProgress(newValue ? -1 : 0);
paymentSpinner.setVisible(newValue);
});
presentationModel.showTransactionPublishedScreen.addListener((o, oldValue, newValue) -> {
model.showTransactionPublishedScreen.addListener((o, oldValue, newValue) -> {
if (newValue) {
overlayManager.blurContent();
@ -126,8 +110,7 @@ public class RegistrationViewCB extends CachedViewCB<RegistrationPM> implements
public void handle(ActionEvent actionEvent) {
getProperties().put("type", "CLOSE");
try {
if (parent instanceof MultiStepNavigation)
((MultiStepNavigation) parent).nextStep(RegistrationViewCB.this);
parent.nextStep(RegistrationView.this);
} catch (Exception e) {
e.printStackTrace();
}
@ -144,55 +127,23 @@ public class RegistrationViewCB extends CachedViewCB<RegistrationPM> implements
});
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
public void setParent(Wizard parent) {
this.parent = parent;
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
public void hideWizardNavigation() {
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// ContextAware implementation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void useSettingsContext(boolean useSettingsContext) {
if (useSettingsContext) {
// TODO not impl. yet
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
private void onPayFee() {
presentationModel.payFee();
model.payFee();
}
@FXML
private void onOpenHelp() {
Help.openWindow(HelpId.PAY_ACCOUNT_FEE);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
}

View File

@ -18,7 +18,6 @@
package io.bitsquare.gui.main.account.content.registration;
import io.bitsquare.btc.WalletService;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.BSResources;
@ -27,6 +26,9 @@ import org.bitcoinj.core.Coin;
import com.google.inject.Inject;
import viewfx.model.ViewModel;
import viewfx.model.support.WithDelegate;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
@ -34,12 +36,8 @@ import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class RegistrationPM extends PresentationModel<RegistrationModel> {
private static final Logger log = LoggerFactory.getLogger(RegistrationPM.class);
class RegistrationViewModel extends WithDelegate<RegistrationDataModel> implements ViewModel {
final BooleanProperty isPayButtonDisabled = new SimpleBooleanProperty(true);
final StringProperty requestPlaceOfferErrorMessage = new SimpleStringProperty();
@ -51,42 +49,28 @@ class RegistrationPM extends PresentationModel<RegistrationModel> {
private final BSFormatter formatter;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private RegistrationPM(RegistrationModel model, BSFormatter formatter) {
super(model);
public RegistrationViewModel(RegistrationDataModel delegate, BSFormatter formatter) {
super(delegate);
this.formatter = formatter;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize() {
super.initialize();
if (model.getAddressEntry() != null) {
address.set(model.getAddressEntry().getAddress());
if (delegate.getAddressEntry() != null) {
address.set(delegate.getAddressEntry().getAddress());
}
model.isWalletFunded.addListener((ov, oldValue, newValue) -> {
delegate.isWalletFunded.addListener((ov, oldValue, newValue) -> {
if (newValue)
validateInput();
});
validateInput();
model.payFeeSuccess.addListener((ov, oldValue, newValue) -> {
delegate.payFeeSuccess.addListener((ov, oldValue, newValue) -> {
isPayButtonDisabled.set(newValue);
showTransactionPublishedScreen.set(newValue);
isPaymentSpinnerVisible.set(false);
});
model.payFeeErrorMessage.addListener((ov, oldValue, newValue) -> {
delegate.payFeeErrorMessage.addListener((ov, oldValue, newValue) -> {
if (newValue != null) {
requestPlaceOfferErrorMessage.set(newValue);
isPaymentSpinnerVisible.set(false);
@ -94,46 +78,19 @@ class RegistrationPM extends PresentationModel<RegistrationModel> {
});
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI actions
///////////////////////////////////////////////////////////////////////////////////////////
void payFee() {
model.payFeeErrorMessage.set(null);
model.payFeeSuccess.set(false);
delegate.payFeeErrorMessage.set(null);
delegate.payFeeSuccess.set(false);
isPayButtonDisabled.set(true);
isPaymentSpinnerVisible.set(true);
model.payFee();
delegate.payFee();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
WalletService getWalletService() {
return model.getWalletService();
return delegate.getWalletService();
}
BSFormatter getFormatter() {
@ -141,11 +98,11 @@ class RegistrationPM extends PresentationModel<RegistrationModel> {
}
Coin getFeeAsCoin() {
return model.getFeeAsCoin();
return delegate.getFeeAsCoin();
}
String getAddressAsString() {
return model.getAddressEntry() != null ? model.getAddressEntry().getAddress().toString() : "";
return delegate.getAddressEntry() != null ? delegate.getAddressEntry().getAddress().toString() : "";
}
String getPaymentLabel() {
@ -153,20 +110,16 @@ class RegistrationPM extends PresentationModel<RegistrationModel> {
}
String getFeeAsString() {
return formatter.formatCoinWithCode(model.getFeeAsCoin());
return formatter.formatCoinWithCode(delegate.getFeeAsCoin());
}
String getTransactionId() {
return model.getTransactionId();
return delegate.getTransactionId();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void validateInput() {
isPayButtonDisabled.set(!(model.isWalletFunded.get()));
isPayButtonDisabled.set(!(delegate.isWalletFunded.get()));
}

View File

@ -20,7 +20,6 @@ package io.bitsquare.gui.main.account.content.restrictions;
import io.bitsquare.account.AccountSettings;
import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.arbitrator.Reputation;
import io.bitsquare.gui.UIModel;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.CountryUtil;
import io.bitsquare.locale.LanguageUtil;
@ -40,14 +39,13 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import viewfx.model.Activatable;
import viewfx.model.DataModel;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class RestrictionsModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(RestrictionsModel.class);
class RestrictionsDataModel implements Activatable, DataModel {
private final User user;
private final AccountSettings accountSettings;
@ -62,27 +60,13 @@ class RestrictionsModel extends UIModel {
final ObservableList<Region> allRegions = FXCollections.observableArrayList(CountryUtil.getAllRegions());
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private RestrictionsModel(User user, AccountSettings accountSettings, Persistence persistence,
MessageService messageService) {
public RestrictionsDataModel(User user, AccountSettings accountSettings, Persistence persistence,
MessageService messageService) {
this.user = user;
this.accountSettings = accountSettings;
this.persistence = persistence;
this.messageService = messageService;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize() {
super.initialize();
AccountSettings persistedAccountSettings = (AccountSettings) persistence.read(accountSettings);
if (persistedAccountSettings != null) {
@ -103,30 +87,16 @@ class RestrictionsModel extends UIModel {
@Override
public void activate() {
super.activate();
languageList.setAll(accountSettings.getAcceptedLanguageLocales());
countryList.setAll(accountSettings.getAcceptedCountries());
arbitratorList.setAll(accountSettings.getAcceptedArbitrators());
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
// no-op
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public
///////////////////////////////////////////////////////////////////////////////////////////
ObservableList<Country> getAllCountriesFor(Region selectedRegion) {
return FXCollections.observableArrayList(CountryUtil.getAllCountriesFor(selectedRegion));
}
@ -178,10 +148,6 @@ class RestrictionsModel extends UIModel {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void saveSettings() {
persistence.write(accountSettings);
}

View File

@ -1,157 +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.main.account.content.restrictions;
import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.Region;
import com.google.inject.Inject;
import java.util.Locale;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class RestrictionsPM extends PresentationModel<RestrictionsModel> {
private static final Logger log = LoggerFactory.getLogger(RestrictionsPM.class);
final BooleanProperty doneButtonDisable = new SimpleBooleanProperty(true);
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private RestrictionsPM(RestrictionsModel model) {
super(model);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize() {
super.initialize();
}
@Override
public void activate() {
super.activate();
updateDoneButtonDisableState();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public
///////////////////////////////////////////////////////////////////////////////////////////
void addLanguage(Locale locale) {
model.addLanguage(locale);
updateDoneButtonDisableState();
}
void removeLanguage(Locale locale) {
model.removeLanguage(locale);
updateDoneButtonDisableState();
}
void addCountry(Country country) {
model.addCountry(country);
updateDoneButtonDisableState();
}
void removeCountry(Country country) {
model.removeCountry(country);
updateDoneButtonDisableState();
}
void removeArbitrator(Arbitrator arbitrator) {
model.removeArbitrator(arbitrator);
updateDoneButtonDisableState();
}
void updateArbitratorList() {
model.updateArbitratorList();
updateDoneButtonDisableState();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
ObservableList<Country> getListWithAllEuroCountries() {
return model.getListWithAllEuroCountries();
}
ObservableList<Country> getAllCountriesFor(Region selectedRegion) {
return model.getAllCountriesFor(selectedRegion);
}
ObservableList<Locale> getLanguageList() {
return model.languageList;
}
ObservableList<Region> getAllRegions() {
return model.allRegions;
}
ObservableList<Locale> getAllLanguages() {
return model.allLanguages;
}
ObservableList<Country> getCountryList() {
return model.countryList;
}
ObservableList<Arbitrator> getArbitratorList() {
return model.arbitratorList;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
//TODO Revert size() > -1 to 0(2 later). For mock testing disabled arbitratorList test
private void updateDoneButtonDisableState() {
boolean isValid = model.languageList != null && model.languageList.size() > 0 &&
model.countryList != null && model.countryList.size() > 0 &&
model.arbitratorList != null && model.arbitratorList.size() > -1;
doneButtonDisable.set(!isValid);
}
}

View File

@ -22,13 +22,13 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.restrictions.RestrictionsViewCB" hgap="5.0"
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.restrictions.RestrictionsView" hgap="5.0"
vgap="5.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
xmlns:fx="http://javafx.com/fxml">
<!--
<!--
languages
-->
<TitledGroupBg text="Add languages" GridPane.rowSpan="3"/>
@ -47,7 +47,7 @@
<InfoDisplay gridPane="$root" onAction="#onOpenLanguagesHelp" rowIndex="2"
text="Trade with users who have at least 1 shared language."/>
<!--
<!--
countries
-->
<TitledGroupBg text="Add countries" GridPane.rowIndex="3" GridPane.rowSpan="3">
@ -84,7 +84,7 @@
text="Restrict trades with these payments account countries."/>
<!--
<!--
arbitrators
-->
<TitledGroupBg text="Add arbitrators" GridPane.rowIndex="6" GridPane.rowSpan="3">

View File

@ -18,26 +18,25 @@
package io.bitsquare.gui.main.account.content.restrictions;
import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.ViewLoader;
import io.bitsquare.gui.main.account.MultiStepNavigation;
import io.bitsquare.gui.main.account.content.ContextAware;
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;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.Region;
import java.net.URL;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.inject.Inject;
import viewfx.view.FxmlView;
import viewfx.view.View;
import viewfx.view.ViewLoader;
import viewfx.view.Wizard;
import viewfx.view.support.CachingViewLoader;
import viewfx.view.support.ActivatableViewAndModel;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.image.*;
@ -47,12 +46,8 @@ import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RestrictionsViewCB extends CachedViewCB<RestrictionsPM> implements ContextAware {
private static final Logger log = LoggerFactory.getLogger(RestrictionsViewCB.class);
@FxmlView
public class RestrictionsView extends ActivatableViewAndModel<GridPane, RestrictionsViewModel> implements Wizard.Step {
@FXML ListView<Locale> languagesListView;
@FXML ListView<Country> countriesListView;
@ -62,77 +57,47 @@ public class RestrictionsViewCB extends CachedViewCB<RestrictionsPM> implements
@FXML ComboBox<Country> countryComboBox;
@FXML Button completedButton, addAllEuroCountriesButton;
private Wizard parent;
private final ViewLoader viewLoader;
private final Stage primaryStage;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private RestrictionsViewCB(RestrictionsPM presentationModel, ViewLoader viewLoader, Stage primaryStage) {
super(presentationModel);
private RestrictionsView(RestrictionsViewModel model, CachingViewLoader viewLoader, Stage primaryStage) {
super(model);
this.viewLoader = viewLoader;
this.primaryStage = primaryStage;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
public void initialize() {
initLanguage();
initCountry();
initArbitrators();
completedButton.disableProperty().bind(presentationModel.doneButtonDisable);
completedButton.disableProperty().bind(model.doneButtonDisable);
}
@Override
public void activate() {
super.activate();
languagesListView.setItems(presentationModel.getLanguageList());
countriesListView.setItems(presentationModel.getCountryList());
arbitratorsListView.setItems(presentationModel.getArbitratorList());
public void doActivate() {
languagesListView.setItems(model.getLanguageList());
countriesListView.setItems(model.getCountryList());
arbitratorsListView.setItems(model.getArbitratorList());
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// ContextAware implementation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void useSettingsContext(boolean useSettingsContext) {
if (useSettingsContext)
((GridPane) root).getChildren().remove(completedButton);
public void setParent(Wizard parent) {
this.parent = parent;
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void hideWizardNavigation() {
root.getChildren().remove(completedButton);
}
@FXML
private void onAddLanguage() {
presentationModel.addLanguage(languageComboBox.getSelectionModel().getSelectedItem());
model.addLanguage(languageComboBox.getSelectionModel().getSelectedItem());
languageComboBox.getSelectionModel().clearSelection();
}
@ -140,32 +105,33 @@ public class RestrictionsViewCB extends CachedViewCB<RestrictionsPM> implements
private void onSelectRegion() {
countryComboBox.setVisible(true);
Region region = regionComboBox.getSelectionModel().getSelectedItem();
countryComboBox.setItems(presentationModel.getAllCountriesFor(region));
countryComboBox.setItems(model.getAllCountriesFor(region));
addAllEuroCountriesButton.setVisible(region.getCode().equals("EU"));
}
@FXML
private void onAddCountry() {
presentationModel.addCountry(countryComboBox.getSelectionModel().getSelectedItem());
model.addCountry(countryComboBox.getSelectionModel().getSelectedItem());
countryComboBox.getSelectionModel().clearSelection();
}
@FXML
private void onAddAllEuroCountries() {
countriesListView.setItems(presentationModel.getListWithAllEuroCountries());
countriesListView.setItems(model.getListWithAllEuroCountries());
}
@FXML
private void onOpenArbitratorScreen() {
loadView(Navigation.Item.ARBITRATOR_BROWSER);
private void onOpenArbitratorScreen(){
View view = viewLoader.load(ArbitratorBrowserView.class);
showStage(view);
}
@FXML
private void onCompleted() {
if (parent instanceof MultiStepNavigation)
((MultiStepNavigation) parent).nextStep(this);
if (parent instanceof Wizard)
((Wizard) parent).nextStep(this);
}
@FXML
@ -183,15 +149,7 @@ public class RestrictionsViewCB extends CachedViewCB<RestrictionsPM> implements
Help.openWindow(HelpId.SETUP_RESTRICTION_ARBITRATORS);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Navigation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected Initializable loadView(Navigation.Item navigationItem) {
ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl(), false);
private void showStage(View view) {
final Stage stage = new Stage();
stage.setTitle("Arbitrator selection");
stage.setMinWidth(800);
@ -202,25 +160,18 @@ public class RestrictionsViewCB extends CachedViewCB<RestrictionsPM> implements
stage.setY(primaryStage.getY() + 50);
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(primaryStage);
Scene scene = new Scene((Parent) loaded.view, 800, 600);
Scene scene = new Scene((Parent) view.getRoot(), 800, 600);
stage.setScene(scene);
stage.setOnHidden(windowEvent -> {
if (navigationItem == Navigation.Item.ARBITRATOR_BROWSER)
if (view instanceof ArbitratorBrowserView)
updateArbitratorList();
});
stage.show();
return loaded.controller;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
void updateArbitratorList() {
presentationModel.updateArbitratorList();
arbitratorsListView.setItems(presentationModel.getArbitratorList());
model.updateArbitratorList();
arbitratorsListView.setItems(model.getArbitratorList());
}
private void initLanguage() {
@ -255,7 +206,7 @@ public class RestrictionsViewCB extends CachedViewCB<RestrictionsPM> implements
}
});
languageComboBox.setItems(presentationModel.getAllLanguages());
languageComboBox.setItems(model.getAllLanguages());
languageComboBox.setConverter(new StringConverter<Locale>() {
@Override
public String toString(Locale locale) {
@ -270,7 +221,7 @@ public class RestrictionsViewCB extends CachedViewCB<RestrictionsPM> implements
}
private void initCountry() {
regionComboBox.setItems(presentationModel.getAllRegions());
regionComboBox.setItems(model.getAllRegions());
regionComboBox.setConverter(new StringConverter<io.bitsquare.locale.Region>() {
@Override
public String toString(io.bitsquare.locale.Region region) {
@ -361,33 +312,15 @@ public class RestrictionsViewCB extends CachedViewCB<RestrictionsPM> implements
}
private void removeLanguage(Locale locale) {
presentationModel.removeLanguage(locale);
model.removeLanguage(locale);
}
private void removeCountry(Country country) {
presentationModel.removeCountry(country);
model.removeCountry(country);
}
private void removeArbitrator(Arbitrator arbitrator) {
presentationModel.removeArbitrator(arbitrator);
model.removeArbitrator(arbitrator);
}
/* private void addCountry(Country country) {
if (!countryList.contains(country) && country != null) {
countryList.add(country);
settings.addAcceptedCountry(country);
saveSettings();
}
}*/
/* private void addLanguage(Locale locale) {
if (locale != null && !languageList.contains(locale)) {
languageList.add(locale);
settings.addAcceptedLanguageLocale(locale);
}
}*/
}

View File

@ -0,0 +1,119 @@
/*
* 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.main.account.content.restrictions;
import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.Region;
import com.google.inject.Inject;
import java.util.Locale;
import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ObservableList;
class RestrictionsViewModel extends ActivatableWithDelegate<RestrictionsDataModel> implements ViewModel {
final BooleanProperty doneButtonDisable = new SimpleBooleanProperty(true);
@Inject
public RestrictionsViewModel(RestrictionsDataModel delegate) {
super(delegate);
}
@Override
public void doActivate() {
updateDoneButtonDisableState();
}
void addLanguage(Locale locale) {
delegate.addLanguage(locale);
updateDoneButtonDisableState();
}
void removeLanguage(Locale locale) {
delegate.removeLanguage(locale);
updateDoneButtonDisableState();
}
void addCountry(Country country) {
delegate.addCountry(country);
updateDoneButtonDisableState();
}
void removeCountry(Country country) {
delegate.removeCountry(country);
updateDoneButtonDisableState();
}
void removeArbitrator(Arbitrator arbitrator) {
delegate.removeArbitrator(arbitrator);
updateDoneButtonDisableState();
}
void updateArbitratorList() {
delegate.updateArbitratorList();
updateDoneButtonDisableState();
}
ObservableList<Country> getListWithAllEuroCountries() {
return delegate.getListWithAllEuroCountries();
}
ObservableList<Country> getAllCountriesFor(Region selectedRegion) {
return delegate.getAllCountriesFor(selectedRegion);
}
ObservableList<Locale> getLanguageList() {
return delegate.languageList;
}
ObservableList<Region> getAllRegions() {
return delegate.allRegions;
}
ObservableList<Locale> getAllLanguages() {
return delegate.allLanguages;
}
ObservableList<Country> getCountryList() {
return delegate.countryList;
}
ObservableList<Arbitrator> getArbitratorList() {
return delegate.arbitratorList;
}
//TODO Revert size() > -1 to 0(2 later). For mock testing disabled arbitratorList test
private void updateDoneButtonDisableState() {
boolean isValid = delegate.languageList != null && delegate.languageList.size() > 0 &&
delegate.countryList != null && delegate.countryList.size() > 0 &&
delegate.arbitratorList != null && delegate.arbitratorList.size() > -1;
doneButtonDisable.set(!isValid);
}
}

View File

@ -1,83 +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.main.account.content.seedwords;
import io.bitsquare.btc.WalletService;
import io.bitsquare.gui.UIModel;
import com.google.inject.Inject;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class SeedWordsModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(SeedWordsModel.class);
private List<String> mnemonicCode;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private SeedWordsModel(WalletService walletService) {
if (walletService != null && walletService.getWallet() != null)
mnemonicCode = walletService.getWallet().getKeyChainSeed().getMnemonicCode();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize() {
super.initialize();
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter
///////////////////////////////////////////////////////////////////////////////////////////
List<String> getMnemonicCode() {
return mnemonicCode;
}
}

View File

@ -1,80 +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.main.account.content.seedwords;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.util.BSFormatter;
import com.google.inject.Inject;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class SeedWordsPM extends PresentationModel<SeedWordsModel> {
private static final Logger log = LoggerFactory.getLogger(SeedWordsPM.class);
final StringProperty seedWords = new SimpleStringProperty();
private final BSFormatter formatter;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private SeedWordsPM(SeedWordsModel model, BSFormatter formatter) {
super(model);
this.formatter = formatter;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize() {
super.initialize();
if (model.getMnemonicCode() != null)
seedWords.set(formatter.mnemonicCodeToString(model.getMnemonicCode()));
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
}

View File

@ -23,7 +23,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.seedwords.SeedWordsViewCB" hgap="5.0"
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.content.seedwords.SeedWordsView" hgap="5.0"
vgap="5.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"

View File

@ -0,0 +1,71 @@
/*
* 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.main.account.content.seedwords;
import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import javax.inject.Inject;
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;
@FXML TextArea seedWordsTextArea;
private Wizard parent;
@Inject
private SeedWordsView(SeedWordsViewModel model) {
super(model);
}
@Override
public void initialize() {
seedWordsTextArea.setText(model.seedWords.get());
}
@Override
public void setParent(Wizard parent) {
this.parent = parent;
}
@Override
public void hideWizardNavigation() {
root.getChildren().remove(completedButton);
}
@FXML
private void onCompleted() {
parent.nextStep(this);
}
@FXML
private void onOpenHelp() {
Help.openWindow(HelpId.SETUP_SEED_WORDS);
}
}

View File

@ -1,113 +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.main.account.content.seedwords;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.main.account.MultiStepNavigation;
import io.bitsquare.gui.main.account.content.ContextAware;
import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SeedWordsViewCB extends CachedViewCB<SeedWordsPM> implements ContextAware {
private static final Logger log = LoggerFactory.getLogger(SeedWordsViewCB.class);
@FXML Button completedButton;
@FXML TextArea seedWordsTextArea;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private SeedWordsViewCB(SeedWordsPM presentationModel) {
super(presentationModel);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
seedWordsTextArea.setText(presentationModel.seedWords.get());
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// ContextAware implementation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void useSettingsContext(boolean useSettingsContext) {
if (useSettingsContext)
((GridPane) root).getChildren().remove(completedButton);
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
private void onCompleted() {
if (parent instanceof MultiStepNavigation)
((MultiStepNavigation) parent).nextStep(this);
}
@FXML
private void onOpenHelp() {
Help.openWindow(HelpId.SETUP_SEED_WORDS);
}
}

View File

@ -0,0 +1,45 @@
/*
* 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.main.account.content.seedwords;
import io.bitsquare.btc.WalletService;
import io.bitsquare.gui.util.BSFormatter;
import com.google.inject.Inject;
import java.util.List;
import viewfx.model.ViewModel;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
class SeedWordsViewModel implements ViewModel {
final StringProperty seedWords = new SimpleStringProperty();
@Inject
public SeedWordsViewModel(WalletService walletService, BSFormatter formatter) {
if (walletService.getWallet() != null) {
List<String> mnemonicCode = walletService.getWallet().getKeyChainSeed().getMnemonicCode();
if (mnemonicCode != null) {
seedWords.set(formatter.mnemonicCodeToString(mnemonicCode));
}
}
}
}

View File

@ -19,7 +19,7 @@
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.settings.AccountSettingsViewCB"
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.settings.AccountSettingsView"
prefHeight="660.0" prefWidth="1000.0"
xmlns:fx="http://javafx.com/fxml">

View File

@ -0,0 +1,172 @@
/*
* 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.main.account.settings;
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.irc.IrcAccountView;
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;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon;
@FxmlView
public class AccountSettingsView extends ActivatableViewAndModel {
private final ViewLoader viewLoader;
private final Navigation navigation;
private MenuItem seedWords, password, restrictions, ircAccount, registration;
private Navigation.Listener listener;
@FXML private VBox leftVBox;
@FXML private AnchorPane content;
@Inject
private AccountSettingsView(ViewLoader viewLoader, Navigation navigation) {
this.viewLoader = viewLoader;
this.navigation = navigation;
}
@Override
public void initialize() {
listener = viewPath -> {
if (viewPath.size() != 4 || viewPath.indexOf(AccountSettingsView.class) != 2)
return;
loadView(viewPath.tip());
};
ToggleGroup toggleGroup = new 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);
ircAccount = new MenuItem(navigation, toggleGroup, "Payments account(s)", IrcAccountView.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, ircAccount, registration);
}
@Override
public void doActivate() {
navigation.addListener(listener);
ViewPath viewPath = navigation.getCurrentPath();
if (viewPath.size() == 3 && viewPath.indexOf(AccountSettingsView.class) == 2) {
navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, IrcAccountView.class);
}
else if (viewPath.size() == 4 && viewPath.indexOf(AccountSettingsView.class) == 2) {
loadView(viewPath.get(3));
}
}
@Override
public void doDeactivate() {
navigation.removeListener(listener);
}
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();
if (view instanceof SeedWordsView) seedWords.setSelected(true);
else if (view instanceof ChangePasswordView) password.setSelected(true);
else if (view instanceof RestrictionsView) restrictions.setSelected(true);
else if (view instanceof IrcAccountView) ircAccount.setSelected(true);
else if (view instanceof RegistrationView) registration.setSelected(true);
else throw new BitsquareException("Selecting main menu button for view " + view + " is not supported");
}
}
class MenuItem extends ToggleButton {
MenuItem(Navigation navigation, ToggleGroup toggleGroup, String title, Class<? extends View> viewClass) {
setToggleGroup(toggleGroup);
setText(title);
setId("account-settings-item-background-active");
setPrefHeight(40);
setPrefWidth(200);
setAlignment(Pos.CENTER_LEFT);
Label icon = new Label();
icon.setTextFill(Paint.valueOf("#999"));
if (viewClass == SeedWordsView.class)
AwesomeDude.setIcon(icon, AwesomeIcon.INFO_SIGN);
else if (viewClass == RegistrationView.class)
AwesomeDude.setIcon(icon, AwesomeIcon.BRIEFCASE);
else
AwesomeDude.setIcon(icon, AwesomeIcon.EDIT_SIGN);
setGraphic(icon);
setOnAction((event) ->
navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, viewClass));
selectedProperty().addListener((ov, oldValue, newValue) -> {
if (newValue) {
setId("account-settings-item-background-selected");
icon.setTextFill(Colors.BLUE);
}
else {
setId("account-settings-item-background-active");
icon.setTextFill(Paint.valueOf("#999"));
}
});
disableProperty().addListener((ov, oldValue, newValue) -> {
if (newValue) {
setId("account-settings-item-background-disabled");
icon.setTextFill(Paint.valueOf("#ccc"));
}
else {
setId("account-settings-item-background-active");
icon.setTextFill(Paint.valueOf("#999"));
}
});
}
}

View File

@ -1,238 +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.main.account.settings;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.ViewCB;
import io.bitsquare.gui.ViewLoader;
import io.bitsquare.gui.main.account.content.ContextAware;
import io.bitsquare.gui.util.Colors;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AccountSettingsViewCB extends CachedViewCB {
private static final Logger log = LoggerFactory.getLogger(AccountSettingsViewCB.class);
private final ViewLoader viewLoader;
private final Navigation navigation;
private MenuItem seedWords, password, restrictions, fiatAccount, registration;
private Navigation.Listener listener;
@FXML private VBox leftVBox;
@FXML private AnchorPane content;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private AccountSettingsViewCB(ViewLoader viewLoader, Navigation navigation) {
super();
this.viewLoader = viewLoader;
this.navigation = navigation;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
listener = navigationItems -> {
if (navigationItems != null &&
navigationItems.length == 4 &&
navigationItems[2] == Navigation.Item.ACCOUNT_SETTINGS) {
loadView(navigationItems[3]);
selectMainMenuButton(navigationItems[3]);
}
};
ToggleGroup toggleGroup = new ToggleGroup();
seedWords = new MenuItem(navigation, "Wallet seed",
Navigation.Item.SEED_WORDS, toggleGroup);
password = new MenuItem(navigation, "Wallet password",
Navigation.Item.CHANGE_PASSWORD, toggleGroup);
restrictions = new MenuItem(navigation, "Arbitrator selection",
Navigation.Item.RESTRICTIONS, toggleGroup);
fiatAccount = new MenuItem(navigation, "Payments account(s)",
Navigation.Item.FIAT_ACCOUNT, toggleGroup);
registration = new MenuItem(navigation, "Renew your account",
Navigation.Item.REGISTRATION, toggleGroup);
seedWords.setDisable(true);
password.setDisable(true);
restrictions.setDisable(true);
registration.setDisable(true);
leftVBox.getChildren().addAll(seedWords, password,
restrictions, fiatAccount, registration);
super.initialize(url, rb);
}
@Override
public void activate() {
super.activate();
navigation.addListener(listener);
Navigation.Item[] items = navigation.getCurrentItems();
if (items.length == 3 &&
items[2] == Navigation.Item.ACCOUNT_SETTINGS) {
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ACCOUNT,
Navigation.Item.ACCOUNT_SETTINGS, Navigation.Item.FIAT_ACCOUNT);
}
else {
if (items.length == 4 &&
items[2] == Navigation.Item.ACCOUNT_SETTINGS) {
loadView(items[3]);
selectMainMenuButton(items[3]);
}
}
}
@Override
public void deactivate() {
super.deactivate();
navigation.removeListener(listener);
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public Methods
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected Initializable loadView(Navigation.Item navigationItem) {
ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl());
content.getChildren().setAll(loaded.view);
childController = loaded.controller;
((ViewCB<? extends PresentationModel>) childController).setParent(this);
((ContextAware) childController).useSettingsContext(true);
return childController;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void selectMainMenuButton(Navigation.Item 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.getFxmlUrl() + " is invalid");
break;
}
}
}
class MenuItem extends ToggleButton {
private static final Logger log = LoggerFactory.getLogger(MenuItem.class);
MenuItem(Navigation navigation, String title, Navigation.Item navigationItem,
ToggleGroup toggleGroup) {
setToggleGroup(toggleGroup);
setText(title);
setId("account-settings-item-background-active");
setPrefHeight(40);
setPrefWidth(200);
setAlignment(Pos.CENTER_LEFT);
Label icon = new Label();
icon.setTextFill(Paint.valueOf("#999"));
if (navigationItem.equals(Navigation.Item.SEED_WORDS))
AwesomeDude.setIcon(icon, AwesomeIcon.INFO_SIGN);
else if (navigationItem.equals(Navigation.Item.REGISTRATION))
AwesomeDude.setIcon(icon, AwesomeIcon.BRIEFCASE);
else
AwesomeDude.setIcon(icon, AwesomeIcon.EDIT_SIGN);
setGraphic(icon);
setOnAction((event) -> navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ACCOUNT,
Navigation.Item.ACCOUNT_SETTINGS, navigationItem));
selectedProperty().addListener((ov, oldValue, newValue) -> {
if (newValue) {
setId("account-settings-item-background-selected");
icon.setTextFill(Colors.BLUE);
}
else {
setId("account-settings-item-background-active");
icon.setTextFill(Paint.valueOf("#999"));
}
});
disableProperty().addListener((ov, oldValue, newValue) -> {
if (newValue) {
setId("account-settings-item-background-disabled");
icon.setTextFill(Paint.valueOf("#ccc"));
}
else {
setId("account-settings-item-background-active");
icon.setTextFill(Paint.valueOf("#999"));
}
});
}
}

View File

@ -1,272 +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.main.account.setup;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.ViewCB;
import io.bitsquare.gui.ViewLoader;
import io.bitsquare.gui.main.account.MultiStepNavigation;
import io.bitsquare.gui.main.account.content.ContextAware;
import io.bitsquare.gui.main.account.content.irc.IrcAccountViewCB;
import io.bitsquare.gui.main.account.content.password.PasswordViewCB;
import io.bitsquare.gui.main.account.content.registration.RegistrationViewCB;
import io.bitsquare.gui.main.account.content.restrictions.RestrictionsViewCB;
import io.bitsquare.gui.main.account.content.seedwords.SeedWordsViewCB;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This UI is not cached as it is normally only needed once.
*/
public class AccountSetupViewCB extends ViewCB implements MultiStepNavigation {
private static final Logger log = LoggerFactory.getLogger(AccountSetupViewCB.class);
private WizardItem seedWords, password, fiatAccount, restrictions, registration;
private Navigation.Listener listener;
@FXML VBox leftVBox;
@FXML AnchorPane content;
private final ViewLoader viewLoader;
private final Navigation navigation;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private AccountSetupViewCB(ViewLoader viewLoader, Navigation navigation) {
super();
this.viewLoader = viewLoader;
this.navigation = navigation;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
listener = navigationItems -> {
if (navigationItems != null &&
navigationItems.length == 4 &&
navigationItems[2] == Navigation.Item.ACCOUNT_SETUP) {
switch (navigationItems[3]) {
case SEED_WORDS:
childController = seedWords.show();
break;
case ADD_PASSWORD:
seedWords.onCompleted();
childController = password.show();
break;
case RESTRICTIONS:
seedWords.onCompleted();
password.onCompleted();
childController = restrictions.show();
break;
case FIAT_ACCOUNT:
seedWords.onCompleted();
password.onCompleted();
restrictions.onCompleted();
childController = fiatAccount.show();
break;
case REGISTRATION:
seedWords.onCompleted();
password.onCompleted();
restrictions.onCompleted();
fiatAccount.onCompleted();
childController = registration.show();
break;
}
}
};
seedWords = new WizardItem(this, "Backup wallet seed", "Write down the seed word for your wallet",
Navigation.Item.SEED_WORDS);
password = new WizardItem(this, "Setup password", "Protect your wallet with a password",
Navigation.Item.ADD_PASSWORD);
restrictions = new WizardItem(this, "Select arbitrators",
"Select which arbitrators you want to use for trading",
Navigation.Item.RESTRICTIONS);
fiatAccount = new WizardItem(this, " Setup Payments account(s)",
"You need to setup at least one payment account",
Navigation.Item.FIAT_ACCOUNT);
registration = new WizardItem(this, "Register your account",
"The registration in the Blockchain requires a payment of 0.0002 BTC",
Navigation.Item.REGISTRATION);
leftVBox.getChildren().addAll(seedWords, password, restrictions, fiatAccount, registration);
seedWords.setDisable(true);
password.setDisable(true);
restrictions.setDisable(true);
registration.setDisable(true);
super.initialize(url, rb);
navigation.addListener(listener);
childController = fiatAccount.show();
}
@Override
public void terminate() {
super.terminate();
navigation.removeListener(listener);
}
///////////////////////////////////////////////////////////////////////////////////////////
// MultiStepNavigation implementation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void nextStep(ViewCB<? extends PresentationModel> childView) {
if (childView instanceof SeedWordsViewCB) {
seedWords.onCompleted();
childController = password.show();
}
else if (childView instanceof PasswordViewCB) {
password.onCompleted();
childController = restrictions.show();
}
else if (childView instanceof RestrictionsViewCB) {
restrictions.onCompleted();
childController = fiatAccount.show();
}
else if (childView instanceof IrcAccountViewCB) {
fiatAccount.onCompleted();
childController = registration.show();
}
else if (childView instanceof RegistrationViewCB) {
registration.onCompleted();
childController = null;
if (navigation.getItemsForReturning() != null)
navigation.navigationTo(navigation.getItemsForReturning());
else
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.BUY);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public Methods
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected Initializable loadView(Navigation.Item navigationItem) {
ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl());
content.getChildren().setAll(loaded.view);
childController = loaded.controller;
((ViewCB<? extends PresentationModel>) childController).setParent(this);
((ContextAware) childController).useSettingsContext(false);
return childController;
}
}
class WizardItem extends HBox {
private static final Logger log = LoggerFactory.getLogger(WizardItem.class);
private ViewCB<? extends PresentationModel> childController;
private final ImageView imageView;
private final Label titleLabel;
private final Label subTitleLabel;
private final AccountSetupViewCB host;
private final Navigation.Item navigationItem;
WizardItem(AccountSetupViewCB host, String title, String subTitle,
Navigation.Item navigationItem) {
this.host = host;
this.navigationItem = navigationItem;
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));
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);
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);
}
ViewCB<? extends PresentationModel> show() {
host.loadView(navigationItem);
/* navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ACCOUNT, Navigation
.Item.ACCOUNT_SETUP,
navigationItem);*/
setId("wizard-item-background-active");
imageView.setId("image-arrow-blue");
titleLabel.setId("wizard-title-active");
subTitleLabel.setId("wizard-sub-title-active");
return childController;
}
void onCompleted() {
setId("wizard-item-background-completed");
imageView.setId("image-tick");
titleLabel.setId("wizard-title-completed");
subTitleLabel.setId("wizard-sub-title-completed");
}
}

View File

@ -19,7 +19,7 @@
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.setup.AccountSetupViewCB"
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.account.setup.AccountSetupWizard"
xmlns:fx="http://javafx.com/fxml">
<VBox fx:id="leftVBox" spacing="5" prefWidth="300" AnchorPane.bottomAnchor="20" AnchorPane.leftAnchor="15"

View File

@ -0,0 +1,223 @@
/*
* 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.main.account.setup;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.main.MainView;
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;
import viewfx.view.support.ActivatableView;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
@FxmlView
public class AccountSetupWizard extends ActivatableView implements Wizard {
@FXML VBox leftVBox;
@FXML AnchorPane content;
private WizardItem seedWords, password, ircAccount, restrictions, registration;
private Navigation.Listener listener;
private final ViewLoader viewLoader;
private final Navigation navigation;
@Inject
private AccountSetupWizard(ViewLoader viewLoader, Navigation navigation) {
this.viewLoader = viewLoader;
this.navigation = navigation;
}
@Override
public void initialize() {
listener = viewPath -> {
if (viewPath.size() != 4 || !viewPath.contains(this.getClass()))
return;
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 == IrcAccountView.class) {
seedWords.onCompleted();
password.onCompleted();
restrictions.onCompleted();
ircAccount.show();
}
else if (viewClass == RegistrationView.class) {
seedWords.onCompleted();
password.onCompleted();
restrictions.onCompleted();
ircAccount.onCompleted();
registration.show();
}
};
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");
ircAccount = new WizardItem(IrcAccountView.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, ircAccount, registration);
seedWords.setDisable(true);
password.setDisable(true);
restrictions.setDisable(true);
registration.setDisable(true);
}
@Override
public void activate() {
navigation.addListener(listener);
ircAccount.show();
}
@Override
public void deactivate() {
navigation.removeListener(listener);
}
@Override
public void nextStep(Step currentStep) {
if (currentStep instanceof SeedWordsView) {
seedWords.onCompleted();
password.show();
}
else if (currentStep instanceof PasswordView) {
password.onCompleted();
restrictions.show();
}
else if (currentStep instanceof RestrictionsView) {
restrictions.onCompleted();
ircAccount.show();
}
else if (currentStep instanceof IrcAccountView) {
ircAccount.onCompleted();
registration.show();
}
else if (currentStep instanceof RegistrationView) {
registration.onCompleted();
if (navigation.getReturnPath() != null)
navigation.navigateTo(navigation.getReturnPath());
else
navigation.navigateTo(MainView.class, BuyView.class);
}
}
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);
}
private class WizardItem extends HBox {
private final ImageView imageView;
private final Label titleLabel;
private final Label subTitleLabel;
private final Class<? extends View> viewClass;
WizardItem(Class<? extends View> viewClass, String title, String subTitle) {
this.viewClass = viewClass;
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));
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);
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);
}
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");
}
void onCompleted() {
setId("wizard-item-background-completed");
imageView.setId("image-tick");
titleLabel.setId("wizard-title-completed");
subTitleLabel.setId("wizard-sub-title-completed");
}
}
}

View File

@ -18,7 +18,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.main.funds.FundsViewCB"
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.main.funds.FundsView"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0"
xmlns:fx="http://javafx.com/fxml">

View File

@ -0,0 +1,101 @@
/*
* 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.main.funds;
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;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.scene.control.*;
@FxmlView
public class FundsView extends ActivatableViewAndModel<TabPane, Activatable> {
@FXML Tab withdrawalTab, transactionsTab;
private Navigation.Listener navigationListener;
private ChangeListener<Tab> tabChangeListener;
private Tab currentTab;
private final ViewLoader viewLoader;
private final Navigation navigation;
@Inject
public FundsView(ViewLoader viewLoader, Navigation navigation) {
this.viewLoader = viewLoader;
this.navigation = navigation;
}
@Override
public void initialize() {
navigationListener = viewPath -> {
if (viewPath.size() == 3 && viewPath.indexOf(FundsView.class) == 1)
loadView(viewPath.tip());
};
tabChangeListener = (ov, oldValue, newValue) -> {
if (newValue == withdrawalTab)
navigation.navigateTo(MainView.class, FundsView.class, WithdrawalView.class);
else if (newValue == transactionsTab)
navigation.navigateTo(MainView.class, FundsView.class, TransactionsView.class);
};
}
@Override
public void doActivate() {
root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener);
navigation.addListener(navigationListener);
if (root.getSelectionModel().getSelectedItem() == transactionsTab)
navigation.navigateTo(MainView.class, FundsView.class, TransactionsView.class);
else
navigation.navigateTo(MainView.class, FundsView.class, WithdrawalView.class);
}
@Override
public void doDeactivate() {
root.getSelectionModel().selectedItemProperty().removeListener(tabChangeListener);
navigation.removeListener(navigationListener);
}
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(viewClass);
if (view instanceof WithdrawalView) currentTab = withdrawalTab;
else if (view instanceof TransactionsView) currentTab = transactionsTab;
currentTab.setContent(view.getRoot());
root.getSelectionModel().select(currentTab);
}
}

View File

@ -1,135 +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.main.funds;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.ViewCB;
import io.bitsquare.gui.ViewLoader;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.*;
import javafx.scene.control.*;
public class FundsViewCB extends CachedViewCB {
private Navigation.Listener navigationListener;
private ChangeListener<Tab> tabChangeListener;
private Tab currentTab;
@FXML Tab withdrawalTab, transactionsTab;
private final ViewLoader viewLoader;
private final Navigation navigation;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
FundsViewCB(ViewLoader viewLoader, Navigation navigation) {
super();
this.viewLoader = viewLoader;
this.navigation = navigation;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
navigationListener = navigationItems -> {
if (navigationItems != null && navigationItems.length == 3
&& navigationItems[1] == Navigation.Item.FUNDS)
loadView(navigationItems[2]);
};
tabChangeListener = (ov, oldValue, newValue) -> {
if (newValue == withdrawalTab)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.FUNDS, Navigation.Item.WITHDRAWAL);
else if (newValue == transactionsTab)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.FUNDS, Navigation.Item.TRANSACTIONS);
};
super.initialize(url, rb);
}
@Override
public void activate() {
super.activate();
((TabPane) root).getSelectionModel().selectedItemProperty().addListener(tabChangeListener);
navigation.addListener(navigationListener);
if (((TabPane) root).getSelectionModel().getSelectedItem() == transactionsTab)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.FUNDS, Navigation.Item.TRANSACTIONS);
else
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.FUNDS, Navigation.Item.WITHDRAWAL);
}
@Override
public void deactivate() {
super.deactivate();
((TabPane) root).getSelectionModel().selectedItemProperty().removeListener(tabChangeListener);
navigation.removeListener(navigationListener);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Navigation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected Initializable loadView(Navigation.Item navigationItem) {
super.loadView(navigationItem);
// we want to get activate/deactivate called, so we remove the old view on tab change
if (currentTab != null)
currentTab.setContent(null);
ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl());
switch (navigationItem) {
case WITHDRAWAL:
currentTab = withdrawalTab;
break;
case TRANSACTIONS:
currentTab = transactionsTab;
break;
}
currentTab.setContent(loaded.view);
((TabPane) root).getSelectionModel().select(currentTab);
Initializable childController = loaded.controller;
((ViewCB) childController).setParent(this);
return childController;
}
}

View File

@ -32,11 +32,8 @@ import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.control.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TransactionsListItem {
private static final Logger log = LoggerFactory.getLogger(TransactionsListItem.class);
private final StringProperty date = new SimpleStringProperty();
private final StringProperty amount = new SimpleStringProperty();
private final StringProperty type = new SimpleStringProperty();

View File

@ -21,7 +21,7 @@
<?import javafx.scene.control.cell.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.funds.transactions.TransactionsViewCB"
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.funds.transactions.TransactionsView"
spacing="10" xmlns:fx="http://javafx.com/fxml">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>

View File

@ -18,20 +18,19 @@
package io.bitsquare.gui.main.funds.transactions;
import io.bitsquare.btc.WalletService;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.util.BSFormatter;
import org.bitcoinj.core.Transaction;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javax.inject.Inject;
import viewfx.view.FxmlView;
import viewfx.view.support.ActivatableViewAndModel;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@ -39,40 +38,26 @@ import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.util.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TransactionsViewCB extends CachedViewCB {
private static final Logger log = LoggerFactory.getLogger(TransactionsViewCB.class);
private final WalletService walletService;
private final BSFormatter formatter;
private ObservableList<TransactionsListItem> transactionsListItems;
@FxmlView
public class TransactionsView extends ActivatableViewAndModel {
@FXML TableView<TransactionsListItem> table;
@FXML TableColumn<TransactionsListItem, TransactionsListItem> dateColumn, addressColumn, amountColumn, typeColumn,
confidenceColumn;
private ObservableList<TransactionsListItem> transactionsListItems;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
private final WalletService walletService;
private final BSFormatter formatter;
@Inject
private TransactionsViewCB(WalletService walletService, BSFormatter formatter) {
private TransactionsView(WalletService walletService, BSFormatter formatter) {
this.walletService = walletService;
this.formatter = formatter;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
public void initialize() {
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
table.setPlaceholder(new Label("No transactions available"));
@ -81,9 +66,7 @@ public class TransactionsViewCB extends CachedViewCB {
}
@Override
public void activate() {
super.activate();
public void doActivate() {
List<Transaction> transactions = walletService.getWallet().getRecentTransactions(10000, true);
transactionsListItems = FXCollections.observableArrayList();
transactionsListItems.addAll(transactions.stream().map(transaction ->
@ -93,23 +76,11 @@ public class TransactionsViewCB extends CachedViewCB {
}
@Override
public void deactivate() {
super.deactivate();
public void doDeactivate() {
for (TransactionsListItem transactionsListItem : transactionsListItems)
transactionsListItem.cleanup();
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void openTxDetails(TransactionsListItem item) {
// TODO Open popup with details view
log.debug("openTxDetails " + item);
@ -118,11 +89,6 @@ public class TransactionsViewCB extends CachedViewCB {
"This will open a details popup but that is not implemented yet.");
}
///////////////////////////////////////////////////////////////////////////////////////////
// Cell factories
///////////////////////////////////////////////////////////////////////////////////////////
private void setAddressColumnCellFactory() {
addressColumn.setCellValueFactory((addressListItem) -> new ReadOnlyObjectWrapper<>(addressListItem.getValue()));
addressColumn.setCellFactory(
@ -182,6 +148,5 @@ public class TransactionsViewCB extends CachedViewCB {
}
});
}
}

View File

@ -21,7 +21,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.*?>
<?import javafx.scene.layout.*?>
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.funds.withdrawal.WithdrawalViewCB"
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.funds.withdrawal.WithdrawalView"
spacing="10" xmlns:fx="http://javafx.com/fxml">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>

View File

@ -22,7 +22,6 @@ import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.Restrictions;
import io.bitsquare.btc.WalletService;
import io.bitsquare.btc.listeners.BalanceListener;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.util.Utilities;
@ -34,14 +33,14 @@ import org.bitcoinj.core.Transaction;
import com.google.common.util.concurrent.FutureCallback;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javax.inject.Inject;
import viewfx.view.FxmlView;
import viewfx.view.support.ActivatableViewAndModel;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@ -56,40 +55,28 @@ import org.controlsfx.control.action.Action;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class WithdrawalViewCB extends CachedViewCB {
private static final Logger log = LoggerFactory.getLogger(WithdrawalViewCB.class);
@FxmlView
public class WithdrawalView extends ActivatableViewAndModel {
@FXML TableView<WithdrawalListItem> table;
@FXML Button addNewAddressButton;
@FXML TextField withdrawFromTextField, withdrawToTextField, amountTextField;
@FXML TableColumn<WithdrawalListItem, WithdrawalListItem> labelColumn, addressColumn, balanceColumn, copyColumn,
confidenceColumn;
private final WalletService walletService;
private final BSFormatter formatter;
private final ObservableList<WithdrawalListItem> addressList = FXCollections.observableArrayList();
@FXML TableView<WithdrawalListItem> table;
@FXML TableColumn<WithdrawalListItem, WithdrawalListItem> labelColumn, addressColumn, balanceColumn, copyColumn,
confidenceColumn;
@FXML Button addNewAddressButton;
@FXML TextField withdrawFromTextField, withdrawToTextField, amountTextField;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private WithdrawalViewCB(WalletService walletService, BSFormatter formatter) {
private WithdrawalView(WalletService walletService, BSFormatter formatter) {
this.walletService = walletService;
this.formatter = formatter;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
public void initialize() {
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
table.setPlaceholder(new Label("No funded wallets for withdrawal available"));
@ -97,14 +84,10 @@ public class WithdrawalViewCB extends CachedViewCB {
setBalanceColumnCellFactory();
setCopyColumnCellFactory();
setConfidenceColumnCellFactory();
super.initialize(url, rb);
}
@Override
public void activate() {
super.activate();
public void doActivate() {
table.getSelectionModel().selectedItemProperty().addListener((observableValue, oldValue, newValue) -> {
if (newValue != null) {
@ -133,24 +116,11 @@ public class WithdrawalViewCB extends CachedViewCB {
}
@Override
public void deactivate() {
super.deactivate();
public void doDeactivate() {
for (WithdrawalListItem item : addressList)
item.cleanup();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
public void onWithdraw() {
Coin amount = formatter.parseToCoin(amountTextField.getText());
@ -207,11 +177,6 @@ public class WithdrawalViewCB extends CachedViewCB {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void fillList() {
addressList.clear();
List<AddressEntry> addressEntryList = walletService.getAddressEntryList();
@ -221,10 +186,6 @@ public class WithdrawalViewCB extends CachedViewCB {
.collect(Collectors.toList()));
}
///////////////////////////////////////////////////////////////////////////////////////////
// Cell factories
///////////////////////////////////////////////////////////////////////////////////////////
private void setLabelColumnCellFactory() {
labelColumn.setCellValueFactory((addressListItem) -> new ReadOnlyObjectWrapper<>(addressListItem.getValue()));
labelColumn.setCellFactory(new Callback<TableColumn<WithdrawalListItem, WithdrawalListItem>,

View File

@ -20,7 +20,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.main.home.HomeViewCB"
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.main.home.HomeView"
AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0"
AnchorPane.rightAnchor="0" AnchorPane.topAnchor="0"
xmlns:fx="http://javafx.com/fxml">

View File

@ -0,0 +1,27 @@
/*
* 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.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
@FxmlView
public class HomeView extends AbstractView {
}

View File

@ -1,64 +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.main.home;
import io.bitsquare.gui.CachedViewCB;
import java.net.URL;
import java.util.ResourceBundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// 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
public class HomeViewCB extends CachedViewCB {
private static final Logger log = LoggerFactory.getLogger(HomeViewCB.class);
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
}

View File

@ -20,7 +20,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.main.msg.MsgViewCB"
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.main.msg.MsgView"
AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0"
AnchorPane.rightAnchor="0" AnchorPane.topAnchor="0"
xmlns:fx="http://javafx.com/fxml">

View File

@ -15,15 +15,13 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.main.trade;
package io.bitsquare.gui.main.msg;
import io.bitsquare.offer.Offer;
import viewfx.view.FxmlView;
import viewfx.view.support.AbstractView;
import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.Fiat;
public interface TradeNavigator {
void createOffer(Coin amount, Fiat price);
void takeOffer(Coin amount, Fiat price, Offer offer);
// will be probably only used for arbitration communication, will be renamed and the icon changed
@FxmlView
public class MsgView extends AbstractView {
}

View File

@ -1,99 +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.main.msg;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.Navigation;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.Initializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// will be probably only used for arbitration communication, will be renamed and the icon changed
public class MsgViewCB extends CachedViewCB {
private static final Logger log = LoggerFactory.getLogger(MsgViewCB.class);
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private MsgViewCB() {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Navigation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected Initializable loadView(Navigation.Item navigationItem) {
return super.loadView(navigationItem);
}
///////////////////////////////////////////////////////////////////////////////////////////
// GUI Event handlers
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private Methods
///////////////////////////////////////////////////////////////////////////////////////////
}

View File

@ -19,7 +19,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.main.portfolio.PortfolioViewCB"
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.main.portfolio.PortfolioView"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" tabClosingPolicy="UNAVAILABLE"
xmlns:fx="http://javafx.com/fxml">

View File

@ -0,0 +1,109 @@
/*
* 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.main.portfolio;
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;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.scene.control.*;
@FxmlView
public class PortfolioView extends ActivatableViewAndModel<TabPane, Activatable> {
@FXML Tab offersTab, openTradesTab, closedTradesTab;
private Tab currentTab;
private Navigation.Listener navigationListener;
private ChangeListener<Tab> tabChangeListener;
private final ViewLoader viewLoader;
private final Navigation navigation;
private final TradeManager tradeManager;
@Inject
public PortfolioView(ViewLoader viewLoader, Navigation navigation, TradeManager tradeManager) {
this.viewLoader = viewLoader;
this.navigation = navigation;
this.tradeManager = tradeManager;
}
@Override
public void initialize() {
navigationListener = viewPath -> {
if (viewPath.size() == 3 && viewPath.indexOf(PortfolioView.class) == 1)
loadView(viewPath.tip());
};
tabChangeListener = (ov, oldValue, newValue) -> {
if (newValue == offersTab)
navigation.navigateTo(MainView.class, PortfolioView.class, OffersView.class);
else if (newValue == openTradesTab)
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);
else if (newValue == closedTradesTab)
navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class);
};
}
@Override
public void doActivate() {
root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener);
navigation.addListener(navigationListener);
if (tradeManager.getPendingTrades().size() == 0)
navigation.navigateTo(MainView.class, PortfolioView.class, OffersView.class);
else
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);
}
@Override
public void doDeactivate() {
root.getSelectionModel().selectedItemProperty().removeListener(tabChangeListener);
navigation.removeListener(navigationListener);
currentTab = null;
}
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(viewClass);
if (view instanceof OffersView) currentTab = offersTab;
else if (view instanceof PendingTradesView) currentTab = openTradesTab;
else if (view instanceof ClosedTradesView) currentTab = closedTradesTab;
currentTab.setContent(view.getRoot());
root.getSelectionModel().select(currentTab);
}
}

View File

@ -1,150 +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.main.portfolio;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.ViewCB;
import io.bitsquare.gui.ViewLoader;
import io.bitsquare.trade.TradeManager;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.*;
import javafx.scene.control.*;
public class PortfolioViewCB extends CachedViewCB {
private Tab currentTab;
private Navigation.Listener navigationListener;
private ChangeListener<Tab> tabChangeListener;
@FXML Tab offersTab, openTradesTab, closedTradesTab;
private final ViewLoader viewLoader;
private final Navigation navigation;
private final TradeManager tradeManager;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
PortfolioViewCB(ViewLoader viewLoader, Navigation navigation, TradeManager tradeManager) {
super();
this.viewLoader = viewLoader;
this.navigation = navigation;
this.tradeManager = tradeManager;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
navigationListener = navigationItems -> {
if (navigationItems != null && navigationItems.length == 3
&& navigationItems[1] == Navigation.Item.PORTFOLIO)
loadView(navigationItems[2]);
};
tabChangeListener = (ov, oldValue, newValue) -> {
if (newValue == offersTab)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.PORTFOLIO, Navigation.Item.OFFERS);
else if (newValue == openTradesTab)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.PORTFOLIO,
Navigation.Item.PENDING_TRADES);
else if (newValue == closedTradesTab)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.PORTFOLIO, Navigation.Item.CLOSED_TRADES);
};
super.initialize(url, rb);
}
@Override
public void activate() {
super.activate();
((TabPane) root).getSelectionModel().selectedItemProperty().addListener(tabChangeListener);
navigation.addListener(navigationListener);
if (tradeManager.getPendingTrades().size() == 0)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.PORTFOLIO, Navigation.Item.OFFERS);
else
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.PORTFOLIO, Navigation.Item.PENDING_TRADES);
}
@Override
public void deactivate() {
super.deactivate();
((TabPane) root).getSelectionModel().selectedItemProperty().removeListener(tabChangeListener);
navigation.removeListener(navigationListener);
currentTab = null;
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Navigation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected Initializable loadView(Navigation.Item navigationItem) {
super.loadView(navigationItem);
// we want to get activate/deactivate called, so we remove the old view on tab change
if (currentTab != null)
currentTab.setContent(null);
ViewLoader.Item loaded = viewLoader.load(navigationItem.getFxmlUrl());
switch (navigationItem) {
case OFFERS:
currentTab = offersTab;
break;
case PENDING_TRADES:
currentTab = openTradesTab;
break;
case CLOSED_TRADES:
currentTab = closedTradesTab;
break;
}
currentTab.setContent(loaded.view);
((TabPane) root).getSelectionModel().select(currentTab);
Initializable childController = loaded.controller;
((ViewCB) childController).setParent(this);
return childController;
}
}

View File

@ -17,7 +17,6 @@
package io.bitsquare.gui.main.portfolio.closed;
import io.bitsquare.gui.UIModel;
import io.bitsquare.offer.Direction;
import io.bitsquare.offer.Offer;
import io.bitsquare.trade.Trade;
@ -26,54 +25,37 @@ import io.bitsquare.user.User;
import com.google.inject.Inject;
import viewfx.model.Activatable;
import viewfx.model.DataModel;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class ClosedTradesModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(ClosedTradesModel.class);
class ClosedTradesDataModel implements Activatable, DataModel {
private final TradeManager tradeManager;
private final User user;
private final ObservableList<ClosedTradesListItem> list = FXCollections.observableArrayList();
private MapChangeListener<String, Trade> mapChangeListener;
private final MapChangeListener<String, Trade> mapChangeListener;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public ClosedTradesModel(TradeManager tradeManager, User user) {
public ClosedTradesDataModel(TradeManager tradeManager, User user) {
this.tradeManager = tradeManager;
this.user = user;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize() {
mapChangeListener = change -> {
this.mapChangeListener = change -> {
if (change.wasAdded())
list.add(new ClosedTradesListItem(change.getValueAdded()));
else if (change.wasRemoved())
list.removeIf(e -> e.getTrade().getId().equals(change.getValueRemoved().getId()));
};
super.initialize();
}
@Override
public void activate() {
super.activate();
list.clear();
tradeManager.getClosedTrades().values().stream()
.forEach(e -> list.add(new ClosedTradesListItem(e)));
@ -85,22 +67,9 @@ class ClosedTradesModel extends UIModel {
@Override
public void deactivate() {
super.deactivate();
tradeManager.getClosedTrades().removeListener(mapChangeListener);
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
public ObservableList<ClosedTradesListItem> getList() {
return list;
}

View File

@ -19,14 +19,10 @@ package io.bitsquare.gui.main.portfolio.closed;
import io.bitsquare.trade.Trade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* We could remove that wrapper if it is not needed for additional UI only fields.
*/
class ClosedTradesListItem {
private static final Logger log = LoggerFactory.getLogger(ClosedTradesListItem.class);
private final Trade trade;

View File

@ -21,7 +21,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.portfolio.closed.ClosedTradesViewCB"
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.portfolio.closed.ClosedTradesView"
hgap="5.0" vgap="5"
xmlns:fx="http://javafx.com/fxml">
<padding>

Some files were not shown because too many files have changed in this diff Show More