Add account settings screens

This commit is contained in:
Manfred Karrer 2014-09-08 18:35:48 +02:00
parent efc2100b26
commit 05525e3558
71 changed files with 1688 additions and 1040 deletions

View file

@ -19,7 +19,6 @@ package io.bitsquare;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.NavigationItem;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.util.Profiler;
@ -28,6 +27,7 @@ import io.bitsquare.persistence.Persistence;
import io.bitsquare.settings.Settings;
import io.bitsquare.user.User;
import io.bitsquare.util.AWTSystemTray;
import io.bitsquare.util.BSFXMLLoader;
import com.google.common.base.Throwables;
@ -111,10 +111,10 @@ public class BitSquare extends Application {
primaryStage.setTitle("BitSquare (" + APP_NAME + ")");
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
final GuiceFXMLLoader loader =
new GuiceFXMLLoader(getClass().getResource(NavigationItem.MAIN.getFxmlUrl()), false);
final BSFXMLLoader loader =
new BSFXMLLoader(getClass().getResource(NavigationItem.MAIN.getFxmlUrl()), false);
try {
final Parent view = loader.load();

View file

@ -128,13 +128,17 @@ public class AddressBasedCoinSelector extends DefaultCoinSelector {
if (addressEntry != null && addressOutput.equals(addressEntry.getAddress())) {
return true;
}
log.warn("No match found at matchesRequiredAddress addressOutput/addressEntry " + addressOutput.toString
() + "/" + addressEntry.getAddress().toString());
}
return false;
}
@Override
public CoinSelection select(Coin target, List<TransactionOutput> candidates) {
log.debug("candidates.size: " + candidates.size());
long targetAsLong = target.longValue();
log.debug("value needed: " + targetAsLong);
HashSet<TransactionOutput> selected = new HashSet<>();
// Sort the inputs by age*value so we get the highest "coindays" spent.
// TODO: Consider changing the wallets internal format to track just outputs and keep them ordered.
@ -159,6 +163,8 @@ public class AddressBasedCoinSelector extends DefaultCoinSelector {
selected.add(output);
total += output.getValue().longValue();
log.debug("adding up outputs: output/total: " + output.getValue().longValue() + "/" + total);
}
// Total may be lower than target here, if the given candidates were insufficient to create to requested
// transaction.

View file

@ -30,13 +30,22 @@ import org.slf4j.LoggerFactory;
public class FeePolicy {
public static final Coin TX_FEE = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
public static final Coin ACCOUNT_REGISTRATION_FEE = Coin.CENT; // 0.01
// The min. REGISTRATION_FEE calculated with Transaction.MIN_NONDUST_OUTPUT would be 0.00015460 which might lead
// to problems for the spending wallet.
// Some web wallets don't allow more then 4 decimal places (need more investigation)
// So we use 0.0002 as that fits also to our 4 decimal places restriction for BTC values.
// The remaining 0.0000454 BTC is given to miners at the moment as it is lower then dust.
public static final Coin REGISTRATION_FEE = TX_FEE.add(TX_FEE);
public static final Coin CREATE_OFFER_FEE = Coin.MILLICOIN; // 0.001
public static final Coin TAKE_OFFER_FEE = CREATE_OFFER_FEE;
private static final Logger log = LoggerFactory.getLogger(FeePolicy.class);
// those are just dummy yet. trading fees will go probably to arbiters
private static final String registrationFeeAddress = "mvkDXt4QmN4Nq9dRUsRigBCaovde9nLkZR";
// Not used at the moment
// private static final String registrationFeeAddress = "mvkDXt4QmN4Nq9dRUsRigBCaovde9nLkZR";
private static final String createOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg";
private static final String takeOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg";
@ -48,15 +57,16 @@ public class FeePolicy {
}
//TODO who is receiver? other users or dev address? use donation option list?
// Not used at the moment
// (dev, other users, wikileaks, tor, sub projects (bitcoinj, tomp2p,...)...)
public Address getAddressForRegistrationFee() {
/* public Address getAddressForRegistrationFee() {
try {
return new Address(params, registrationFeeAddress);
} catch (AddressFormatException e) {
e.printStackTrace();
return null;
}
}
}*/
//TODO get address form arbitrator list
public Address getAddressForCreateOfferFee() {

View file

@ -234,6 +234,7 @@ public class WalletFacade {
registrationAddressEntry = addressEntryList.get(0);
}
else {
// First time
lock.lock();
DeterministicKey registrationKey = wallet.currentReceiveKey();
registrationAddressEntry = new AddressEntry(registrationKey, params,
@ -479,7 +480,7 @@ public class WalletFacade {
}
public boolean isRegistrationFeeBalanceSufficient() {
return getRegistrationBalance().compareTo(FeePolicy.ACCOUNT_REGISTRATION_FEE) >= 0;
return getRegistrationBalance().compareTo(FeePolicy.REGISTRATION_FEE) >= 0;
}
//TODO
@ -505,18 +506,22 @@ public class WalletFacade {
getRegistrationAddressEntry().getKey(), stringifiedBankAccounts);
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT, new ScriptBuilder().op(OP_RETURN).data(data).build());
Coin fee = FeePolicy.ACCOUNT_REGISTRATION_FEE
// We don't take a fee at the moment
// 0.0000454 BTC will get extra to miners as it is lower then durst
/* Coin fee = FeePolicy.REGISTRATION_FEE
.subtract(Transaction.MIN_NONDUST_OUTPUT)
.subtract(FeePolicy.TX_FEE);
log.trace("fee: " + fee.toFriendlyString());
tx.addOutput(fee, feePolicy.getAddressForRegistrationFee());
tx.addOutput(fee, feePolicy.getAddressForRegistrationFee());*/
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
sendRequest.shuffleOutputs = false;
// we don't allow spending of unconfirmed tx as with fake registrations we would open up doors for spam and
// market manipulation with fake offers
// so set includePending to false
sendRequest.coinSelector = new AddressBasedCoinSelector(params, getRegistrationAddressEntry(), false);
// We accept at the moment registration fee payment with 0 confirmations.
// The verification will be done at the end of the trade process again, and then a double spend would be
// detected and lead to arbitration.
// The last param (boolean includePending) is used for indicating that we accept 0 conf tx.
sendRequest.coinSelector = new AddressBasedCoinSelector(params, getRegistrationAddressEntry(), true);
sendRequest.changeAddress = getRegistrationAddressEntry().getAddress();
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
Futures.addCallback(sendResult.broadcastComplete, callback);

View file

@ -81,7 +81,7 @@ public class CodeBehind<T extends PresentationModel> implements Initializable {
* @param navigationItem NavigationItem to be loaded.
* @return The ViewController of the loaded view.
*/
public Initializable loadViewAndGetChildController(NavigationItem navigationItem) {
public Initializable loadView(NavigationItem navigationItem) {
log.trace("Lifecycle: loadViewAndGetChildController " + this.getClass().getSimpleName() + " / navigationItem " +
"= " + navigationItem);
return null;

View file

@ -20,7 +20,6 @@ package io.bitsquare.gui;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.btc.listeners.BalanceListener;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.components.NetworkSyncPane;
import io.bitsquare.gui.orders.OrdersController;
import io.bitsquare.gui.util.BSFormatter;
@ -33,6 +32,7 @@ import io.bitsquare.persistence.Persistence;
import io.bitsquare.trade.TradeManager;
import io.bitsquare.user.User;
import io.bitsquare.util.AWTSystemTray;
import io.bitsquare.util.BSFXMLLoader;
import com.google.bitcoin.core.Coin;
@ -85,6 +85,7 @@ public class MainController extends ViewController {
private Pane ordersButtonButtonHolder;
private boolean messageFacadeInited;
private boolean walletFacadeInited;
private NavigationItem previousNavigationItem;
///////////////////////////////////////////////////////////////////////////////////////////
@ -321,7 +322,7 @@ public class MainController extends ViewController {
///////////////////////////////////////////////////////////////////////////////////////////
private void loadView(NavigationItem navigationItem) {
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
final BSFXMLLoader loader = new BSFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
try {
final Node view = loader.load();
viewBuilder.contentPane.getChildren().setAll(view);
@ -336,9 +337,7 @@ public class MainController extends ViewController {
persistence.write(this, "selectedNavigationItem", navigationItem);
} catch (IOException e) {
log.error("Loading view failed. FxmlUrl = " + navigationItem.getFxmlUrl());
log.error(e.getCause().toString());
log.error(e.getMessage());
log.error(e.getStackTrace().toString());
e.getStackTrace();
}
}
@ -448,6 +447,14 @@ public class MainController extends ViewController {
vBox.getChildren().setAll(comboBox, titleLabel);
parent.getChildren().add(vBox);
}
public void setPreviousNavigationItem(NavigationItem previousNavigationItem) {
this.previousNavigationItem = previousNavigationItem;
}
public NavigationItem getPreviousNavigationItem() {
return previousNavigationItem;
}
}

View file

@ -29,7 +29,6 @@ public enum NavigationItem {
MSG("/io/bitsquare/gui/msg/MsgView.fxml", ImageUtil.MSG, ImageUtil.MSG_ACTIVE),
SETTINGS("/io/bitsquare/gui/settings/SettingsView.fxml", ImageUtil.SETTINGS, ImageUtil.SETTINGS_ACTIVE),
ACCOUNT("/io/bitsquare/gui/account/AccountView.fxml", ImageUtil.ACCOUNT, ImageUtil.ACCOUNT_ACTIVE),
SETUP("/io/bitsquare/gui/account/setup/SetupView.fxml"),
ORDER_BOOK("/io/bitsquare/gui/trade/orderbook/OrderBookView.fxml"),
CREATE_OFFER("/io/bitsquare/gui/trade/createoffer/CreateOfferView.fxml"),
@ -44,8 +43,11 @@ public enum NavigationItem {
WITHDRAWAL("/io/bitsquare/gui/funds/withdrawal/WithdrawalView.fxml"),
TRANSACTIONS("/io/bitsquare/gui/funds/transactions/TransactionsView.fxml"),
ACCOUNT_SETUP("/io/bitsquare/gui/account/setup/SetupView.fxml"),
ACCOUNT_SETTINGS("/io/bitsquare/gui/account/settings/AccountSettingsView.fxml"),
SEED_WORDS("/io/bitsquare/gui/account/seedwords/SeedWordsView.fxml"),
PASSWORD("/io/bitsquare/gui/account/password/PasswordView.fxml"),
ADD_PASSWORD("/io/bitsquare/gui/account/addpassword/PasswordView.fxml"),
CHANGE_PASSWORD("/io/bitsquare/gui/account/changepassword/PasswordView.fxml"),
RESTRICTIONS("/io/bitsquare/gui/account/restrictions/RestrictionsView.fxml"),
REGISTRATION("/io/bitsquare/gui/account/registration/RegistrationView.fxml"),
FIAT_ACCOUNT("/io/bitsquare/gui/account/fiataccount/FiatAccountView.fxml"),

View file

@ -17,12 +17,11 @@
package io.bitsquare.gui.account;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.CachedCodeBehind;
import io.bitsquare.gui.CodeBehind;
import io.bitsquare.gui.MainController;
import io.bitsquare.gui.NavigationItem;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.account.setup.SetupPM;
import io.bitsquare.util.BSFXMLLoader;
import java.io.IOException;
@ -32,26 +31,25 @@ import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AccountCB extends CachedCodeBehind<SetupPM> {
public class AccountCB extends CachedCodeBehind<AccountPM> {
private static final Logger log = LoggerFactory.getLogger(AccountCB.class);
public Button registrationButton;
public Label headLineLabel;
public Label titleLabel;
public Tab setupTab;
public Tab tab;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public AccountCB(SetupPM presentationModel) {
public AccountCB(AccountPM presentationModel) {
super(presentationModel);
}
@ -63,13 +61,22 @@ public class AccountCB extends CachedCodeBehind<SetupPM> {
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
loadViewAndGetChildController(NavigationItem.SETUP);
}
@Override
public void activate() {
super.activate();
if (childController == null) {
if (presentationModel.getNeedRegistration()) {
childController = loadView(NavigationItem.ACCOUNT_SETUP);
tab.setText("Account setup");
}
else {
childController = loadView(NavigationItem.ACCOUNT_SETTINGS);
tab.setText("Account settings");
}
}
}
@Override
@ -82,46 +89,42 @@ public class AccountCB extends CachedCodeBehind<SetupPM> {
super.terminate();
}
public void onRegister() {
loadViewAndGetChildController(NavigationItem.SETUP);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public Methods
// Navigation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public CodeBehind<? extends PresentationModel> loadViewAndGetChildController(NavigationItem navigationItem) {
super.loadViewAndGetChildController(navigationItem);
public Initializable loadView(NavigationItem navigationItem) {
super.loadView(navigationItem);
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
final BSFXMLLoader loader = new BSFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
try {
Pane setupView = loader.load();
setupTab.setContent(setupView);
childController = loader.getController();
Pane view = loader.load();
tab.setContent(view);
Initializable childController = loader.getController();
((CodeBehind) childController).setParentController(this);
} catch (IOException e) {
log.error("Loading view failed. FxmlUrl = " + NavigationItem.ACCOUNT.getFxmlUrl());
log.error(e.getCause().toString());
log.error(e.getMessage());
log.error(e.getStackTrace().toString());
log.error("Loading view failed. FxmlUrl = " + NavigationItem.ACCOUNT_SETUP.getFxmlUrl());
e.getStackTrace();
}
return (CodeBehind) childController;
return childController;
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
public void removeSetup() {
childController = null;
NavigationItem previousItem = MainController.GET_INSTANCE().getPreviousNavigationItem();
if (previousItem == null)
previousItem = NavigationItem.HOME;
MainController.GET_INSTANCE().loadViewAndGetChildController(previousItem);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
}

View file

@ -18,6 +18,7 @@
package io.bitsquare.gui.account;
import io.bitsquare.gui.UIModel;
import io.bitsquare.user.User;
import com.google.inject.Inject;
@ -26,14 +27,16 @@ import org.slf4j.LoggerFactory;
public class AccountModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(AccountModel.class);
private User user;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public AccountModel() {
public AccountModel(User user) {
this.user = user;
}
@ -51,7 +54,10 @@ public class AccountModel extends UIModel {
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
boolean getNeedRegistration() {
return user.getAccountId() == null;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -51,6 +51,9 @@ public class AccountPM extends PresentationModel<AccountModel> {
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
boolean getNeedRegistration() {
return model.getNeedRegistration();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters

View file

@ -19,33 +19,14 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.account.AccountCB"
prefHeight="630.0" prefWidth="1000.0"
AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0"
AnchorPane.rightAnchor="0" AnchorPane.topAnchor="0"
xmlns:fx="http://javafx.com/fxml">
<tabs>
<Tab fx:id="setupTab" text="Setup" closable="false">
<content>
<AnchorPane fx:id="contentPane">
<children>
<Label fx:id="headLineLabel" layoutX="-111.308349609375" layoutY="-70.0"
text="You need to register to use the exchange." AnchorPane.leftAnchor="20.0"
AnchorPane.topAnchor="50.0"/>
<Label fx:id="titleLabel" layoutX="113.353271484375" layoutY="28.0" text="Account overview"
AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="20.0">
<font>
<Font name="System Bold" size="18.0"/>
</font>
</Label>
<Button fx:id="registrationButton" layoutX="100.0" layoutY="76.0" mnemonicParsing="false"
onAction="#onRegister" defaultButton="true"
text="Registration" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="80.0"/>
<Tab fx:id="tab" closable="false">
</children>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>

View file

@ -0,0 +1,132 @@
/*
* 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.account.addpassword;
import io.bitsquare.gui.CachedCodeBehind;
import io.bitsquare.gui.account.settings.AccountSettingsCB;
import io.bitsquare.gui.account.setup.SetupCB;
import io.bitsquare.gui.help.Help;
import io.bitsquare.gui.help.HelpId;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PasswordCB extends CachedCodeBehind<PasswordPM> {
private static final Logger log = LoggerFactory.getLogger(PasswordCB.class);
@FXML private HBox buttonsHBox;
@FXML private Button saveButton, skipButton;
@FXML private PasswordField oldPasswordField, passwordField, repeatedPasswordField;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public PasswordCB(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);
}
@Override
public void activate() {
super.activate();
}
@Override
public void deactivate() {
super.deactivate();
}
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Override from CodeBehind
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setParentController(Initializable parentController) {
super.setParentController(parentController);
if (parentController instanceof AccountSettingsCB) {
buttonsHBox.getChildren().remove(skipButton);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
private void onSaved() {
boolean result = presentationModel.savePassword();
if (result) {
if (parentController instanceof SetupCB)
((SetupCB) parentController).onCompleted(this);
}
else {
log.debug(presentationModel.errorMessage); // TODO use validating TF
}
}
@FXML
private void onOpenHelp() {
Help.openWindow(HelpId.SETUP_PASSWORD);
}
public void onSkipped() {
if (parentController instanceof SetupCB)
((SetupCB) parentController).onCompleted(this);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
}

View file

@ -15,7 +15,7 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.account.password;
package io.bitsquare.gui.account.addpassword;
import io.bitsquare.gui.UIModel;

View file

@ -15,7 +15,7 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.account.password;
package io.bitsquare.gui.account.addpassword;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.util.validation.InputValidator;
@ -34,12 +34,12 @@ import org.slf4j.LoggerFactory;
public class PasswordPM extends PresentationModel<PasswordModel> {
private static final Logger log = LoggerFactory.getLogger(PasswordPM.class);
private PasswordValidator passwordValidator = new PasswordValidator();
private final PasswordValidator passwordValidator = new PasswordValidator();
String errorMessage;
StringProperty passwordField = new SimpleStringProperty();
StringProperty repeatedPasswordField = new SimpleStringProperty();
BooleanProperty saveButtonDisabled = new SimpleBooleanProperty(true);
final StringProperty passwordField = new SimpleStringProperty();
final StringProperty repeatedPasswordField = new SimpleStringProperty();
final BooleanProperty saveButtonDisabled = new SimpleBooleanProperty(true);
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor

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.account.password.PasswordCB" hgap="5.0" vgap="5.0"
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.account.addpassword.PasswordCB" 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">
@ -56,7 +56,7 @@
<PasswordField fx:id="repeatedPasswordField" promptText="Repeat password" GridPane.columnIndex="1"
GridPane.rowIndex="1"/>
<HBox spacing="10" GridPane.columnIndex="1" GridPane.rowIndex="2">
<HBox fx:id="buttonsHBox" spacing="10" GridPane.columnIndex="1" GridPane.rowIndex="2">
<Button fx:id="saveButton" text="Save password" onAction="#onSaved" disable="true" defaultButton="true"/>
<Button fx:id="skipButton" text="I will not use a password" onAction="#onSkipped"/>
<GridPane.margin>

View file

@ -15,9 +15,10 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.account.password;
package io.bitsquare.gui.account.changepassword;
import io.bitsquare.gui.CachedCodeBehind;
import io.bitsquare.gui.account.settings.AccountSettingsCB;
import io.bitsquare.gui.account.setup.SetupCB;
import io.bitsquare.gui.help.Help;
import io.bitsquare.gui.help.HelpId;
@ -29,7 +30,9 @@ import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -38,7 +41,8 @@ public class PasswordCB extends CachedCodeBehind<PasswordPM> {
private static final Logger log = LoggerFactory.getLogger(PasswordCB.class);
@FXML private Button saveButton;
@FXML private HBox buttonsHBox;
@FXML private Button saveButton, skipButton;
@FXML private PasswordField passwordField, repeatedPasswordField;
@ -81,6 +85,17 @@ public class PasswordCB extends CachedCodeBehind<PasswordPM> {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Override from CodeBehind
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setParentController(Initializable parentController) {
super.setParentController(parentController);
if (parentController instanceof AccountSettingsCB) {
buttonsHBox.getChildren().remove(skipButton);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
@ -89,10 +104,13 @@ public class PasswordCB extends CachedCodeBehind<PasswordPM> {
@FXML
private void onSaved() {
boolean result = presentationModel.savePassword();
if (result)
((SetupCB) parentController).onCompleted(this);
else
if (result) {
if (parentController instanceof SetupCB)
((SetupCB) parentController).onCompleted(this);
}
else {
log.debug(presentationModel.errorMessage); // TODO use validating TF
}
}
@FXML
@ -101,7 +119,8 @@ public class PasswordCB extends CachedCodeBehind<PasswordPM> {
}
public void onSkipped() {
((SetupCB) parentController).onCompleted(this);
if (parentController instanceof SetupCB)
((SetupCB) parentController).onCompleted(this);
}
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -0,0 +1,70 @@
/*
* 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.account.changepassword;
import io.bitsquare.gui.UIModel;
import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PasswordModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(PasswordModel.class);
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public PasswordModel() {
}
void savePassword(String password) {
//TODO Implement password encryption for wallet
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: Initializable
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
}

View file

@ -0,0 +1,93 @@
/*
* 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.account.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 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;
public class PasswordPM extends PresentationModel<PasswordModel> {
private static final Logger log = LoggerFactory.getLogger(PasswordPM.class);
private final PasswordValidator passwordValidator = new PasswordValidator();
String errorMessage;
final StringProperty passwordField = new SimpleStringProperty();
final StringProperty repeatedPasswordField = new SimpleStringProperty();
final BooleanProperty saveButtonDisabled = new SimpleBooleanProperty(true);
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public PasswordPM(PasswordModel model) {
super(model);
passwordField.addListener((ov) -> saveButtonDisabled.set(!validate()));
repeatedPasswordField.addListener((ov) -> saveButtonDisabled.set(!validate()));
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialized() {
super.initialized();
}
boolean savePassword() {
if (validate()) {
model.savePassword(passwordField.get());
return true;
}
return false;
}
boolean validate() {
InputValidator.ValidationResult result = passwordValidator.validate(passwordField.get());
if (result.isValid) {
result = passwordValidator.validate(repeatedPasswordField.get());
if (result.isValid) {
if (passwordField.get().equals(repeatedPasswordField.get()))
return true;
else
errorMessage = "The 2 passwords does not match.";
}
else {
errorMessage = result.errorMessage;
}
}
else {
errorMessage = result.errorMessage;
}
return false;
}
}

View file

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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/>.
-->
<?import io.bitsquare.gui.components.InfoDisplay?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.account.addpassword.PasswordCB" 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">
<children>
<Pane id="form-group-background-active" GridPane.columnSpan="2" GridPane.rowSpan="5">
<GridPane.margin>
<Insets bottom="-10.0" left="-10.0" right="-10.0" top="-10.0"/>
</GridPane.margin>
<children>
<Label id="form-group-title-active" text="Change password" layoutX="8" layoutY="-8">
<padding>
<Insets left="5" right="7"/>
</padding>
</Label>
</children>
</Pane>
<Label text="Enter old password:">
<GridPane.margin>
<Insets top="10.0"/>
</GridPane.margin>
</Label>
<PasswordField fx:id="oldPasswordField" promptText="Enter your old password" GridPane.columnIndex="1">
<GridPane.margin>
<Insets top="10.0"/>
</GridPane.margin>
</PasswordField>
<Label text="Enter new password:" GridPane.rowIndex="1"/>
<PasswordField fx:id="passwordField" promptText="Min. 8 characters" GridPane.columnIndex="1"
GridPane.rowIndex="1"/>
<Label text="Repeat password:" GridPane.rowIndex="2"/>
<PasswordField fx:id="repeatedPasswordField" promptText="Repeat password" GridPane.columnIndex="1"
GridPane.rowIndex="2"/>
<HBox fx:id="buttonsHBox" spacing="10" GridPane.columnIndex="1" GridPane.rowIndex="3">
<Button fx:id="saveButton" text="Save password" onAction="#onSaved" disable="true" defaultButton="true"/>
<Button fx:id="skipButton" text="I will not use a password" onAction="#onSkipped"/>
<GridPane.margin>
<Insets bottom="5"/>
</GridPane.margin>
</HBox>
<InfoDisplay gridPane="$root" onAction="#onOpenHelp" rowIndex="4"
text="Protect your wallet with a strong password. You need to enter the password any time you withdraw Bitcoins from your trading wallets. You can change the password later in the settings. Open the help menu for more information."/>
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" halignment="RIGHT" minWidth="140.0"/>
<ColumnConstraints hgrow="ALWAYS" minWidth="300.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
</rowConstraints>
</GridPane>

View file

@ -20,6 +20,7 @@ package io.bitsquare.gui.account.fiataccount;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.gui.CachedCodeBehind;
import io.bitsquare.gui.account.settings.AccountSettingsCB;
import io.bitsquare.gui.account.setup.SetupCB;
import io.bitsquare.gui.components.InputTextField;
import io.bitsquare.gui.components.Popups;
@ -40,7 +41,9 @@ import javax.inject.Inject;
import javafx.collections.ListChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.controlsfx.control.action.Action;
import org.controlsfx.dialog.Dialog;
@ -54,10 +57,11 @@ public class FiatAccountCB extends CachedCodeBehind<FiatAccountPm> {
private static final Logger log = LoggerFactory.getLogger(FiatAccountCB.class);
@FXML private HBox buttonsHBox;
@FXML private ComboBox<Region> regionComboBox;
@FXML private ComboBox<Country> countryComboBox;
@FXML private InputTextField titleTextField, holderNameTextField, primaryIDTextField, secondaryIDTextField;
@FXML private Button saveButton, doneButton, removeBankAccountButton;
@FXML private Button saveButton, completedButton, removeBankAccountButton;
@FXML private ComboBox<BankAccount> selectionComboBox;
@FXML private ComboBox<BankAccountType> typesComboBox;
@FXML private ComboBox<Currency> currencyComboBox;
@ -117,6 +121,19 @@ public class FiatAccountCB extends CachedCodeBehind<FiatAccountPm> {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Override from CodeBehind
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setParentController(Initializable parentController) {
super.setParentController(parentController);
if (parentController instanceof AccountSettingsCB) {
buttonsHBox.getChildren().remove(completedButton);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@ -160,7 +177,7 @@ public class FiatAccountCB extends CachedCodeBehind<FiatAccountPm> {
}
@FXML
private void onDone() {
private void onCompleted() {
if (parentController != null)
((SetupCB) parentController).onCompleted(this);
}
@ -230,7 +247,8 @@ public class FiatAccountCB extends CachedCodeBehind<FiatAccountPm> {
});
presentationModel.getAllBankAccounts().addListener((ListChangeListener<BankAccount>) change ->
doneButton.setDisable(change.getList().isEmpty()));
completedButton.setDisable(presentationModel.getAllBankAccounts().isEmpty()));
completedButton.setDisable(presentationModel.getAllBankAccounts().isEmpty());
}
private void setupBindings() {

View file

@ -87,9 +87,9 @@
<InfoDisplay gridPane="$root" onAction="#onOpenSetupHelp" rowIndex="7"
text="The payments account data will be saved in a encrypted form to the Bitcoin block chain and will be used in the trade process for account verification."/>
<HBox GridPane.columnIndex="1" GridPane.rowIndex="8" spacing="10">
<HBox fx:id="buttonsHBox" GridPane.columnIndex="1" GridPane.rowIndex="8" spacing="10">
<Button fx:id="saveButton" text="Save" onAction="#onSave" defaultButton="true" disable="true"/>
<Button fx:id="doneButton" text="Continue to the next step" onAction="#onDone" disable="true"/>
<Button fx:id="completedButton" text="Continue to the next step" onAction="#onCompleted" disable="true"/>
<GridPane.margin>
<Insets top="15.0" bottom="5.0"/>
</GridPane.margin>

View file

@ -18,17 +18,33 @@
package io.bitsquare.gui.account.registration;
import io.bitsquare.gui.CachedCodeBehind;
import io.bitsquare.gui.MainController;
import io.bitsquare.gui.account.settings.AccountSettingsCB;
import io.bitsquare.gui.account.setup.SetupCB;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.components.btc.AddressTextField;
import io.bitsquare.gui.components.btc.BalanceTextField;
import io.bitsquare.gui.help.Help;
import io.bitsquare.gui.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 javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.input.*;
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;
@ -37,6 +53,13 @@ public class RegistrationCB extends CachedCodeBehind<RegistrationPM> {
private static final Logger log = LoggerFactory.getLogger(RegistrationCB.class);
@FXML private TextField feeTextField;
@FXML private AddressTextField addressTextField;
@FXML private BalanceTextField balanceTextField;
@FXML private Button payButton;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@ -55,6 +78,57 @@ public class RegistrationCB extends CachedCodeBehind<RegistrationPM> {
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());
balanceTextField.setup(presentationModel.getWalletFacade(), presentationModel.address.get());
payButton.disableProperty().bind(presentationModel.isPayButtonDisabled);
presentationModel.requestPlaceOfferErrorMessage.addListener((o, oldValue, newValue) -> {
if (newValue != null) {
Popups.openErrorPopup(BSResources.get("shared.error"),
BSResources.get("createOffer.amountPriceBox.error.message",
presentationModel.requestPlaceOfferErrorMessage.get()));
}
});
presentationModel.showTransactionPublishedScreen.addListener((o, oldValue, newValue) -> {
if (newValue) {
MainController.GET_INSTANCE().blurContentScreen();
List<Action> actions = new ArrayList<>();
actions.add(new AbstractAction(BSResources.get("shared.copyTxId")) {
@Override
public void handle(ActionEvent actionEvent) {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(presentationModel.getTransactionId());
clipboard.setContent(content);
}
});
actions.add(new AbstractAction(BSResources.get("shared.close")) {
@Override
public void handle(ActionEvent actionEvent) {
try {
if (parentController instanceof SetupCB)
((SetupCB) parentController).onCompleted(RegistrationCB.this);
} catch (Exception e) {
e.printStackTrace();
}
Dialog.Actions.CLOSE.handle(actionEvent);
MainController.GET_INSTANCE().removeContentScreenBlur();
}
});
Popups.openInfo(BSResources.get("The Transaction ID for the offer payment is:\n" +
presentationModel.getTransactionId() +
"\n\n You can now start trading."),
BSResources.get("You have been successfully registered."),
actions);
}
});
}
@Override
@ -75,22 +149,29 @@ public class RegistrationCB extends CachedCodeBehind<RegistrationPM> {
///////////////////////////////////////////////////////////////////////////////////////////
// Public Methods
// Override from CodeBehind
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setParentController(Initializable parentController) {
super.setParentController(parentController);
if (parentController instanceof AccountSettingsCB) {
// ((GridPane) root).getChildren().remove(completedButton);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
private void onDone() {
((SetupCB) parentController).onCompleted(this);
private void onPayFee() {
presentationModel.payFee();
}
@FXML
private void onOpenHelp() {
Help.openWindow(HelpId.SETUP_REGISTRATION);
Help.openWindow(HelpId.PAY_ACCOUNT_FEE);
}
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -17,49 +17,154 @@
package io.bitsquare.gui.account.registration;
import io.bitsquare.btc.AddressEntry;
import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.btc.listeners.BalanceListener;
import io.bitsquare.gui.UIModel;
import io.bitsquare.persistence.Persistence;
import io.bitsquare.user.User;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.InsufficientMoneyException;
import com.google.bitcoin.core.Transaction;
import com.google.common.util.concurrent.FutureCallback;
import com.google.inject.Inject;
import javax.annotation.Nullable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RegistrationModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(RegistrationModel.class);
private WalletFacade walletFacade;
private User user;
private Persistence persistence;
AddressEntry addressEntry;
final BooleanProperty isWalletFunded = new SimpleBooleanProperty();
final BooleanProperty payFeeSuccess = new SimpleBooleanProperty();
String transactionId;
final StringProperty payFeeErrorMessage = new SimpleStringProperty();
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public RegistrationModel() {
public RegistrationModel(WalletFacade walletFacade, User user, Persistence persistence) {
this.walletFacade = walletFacade;
this.user = user;
this.persistence = persistence;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialized() {
super.initialized();
if (walletFacade != null && walletFacade.getWallet() != null) {
addressEntry = walletFacade.getRegistrationAddressEntry();
walletFacade.addBalanceListener(new BalanceListener(addressEntry.getAddress()) {
@Override
public void onBalanceChanged(@NotNull Coin balance) {
updateBalance(balance);
}
});
updateBalance(walletFacade.getBalanceForAddress(addressEntry.getAddress()));
}
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: Initializable
// Methods
///////////////////////////////////////////////////////////////////////////////////////////
void payFee() {
FutureCallback<Transaction> callback = new FutureCallback<Transaction>() {
@Override
public void onSuccess(@Nullable Transaction transaction) {
log.debug("payRegistrationFee onSuccess");
if (transaction != null) {
transactionId = transaction.getHashAsString();
log.info("payRegistrationFee onSuccess tx id:" + transaction.getHashAsString());
if (addressEntry != null)
user.setAccountID(addressEntry.toString());
persistence.write(user.getClass().getName(), user);
payFeeSuccess.set(true);
}
}
@Override
public void onFailure(@NotNull Throwable t) {
log.debug("payRegistrationFee onFailure");
payFeeErrorMessage.set("Fee payment failed with error: " + t.getMessage());
}
};
try {
walletFacade.payRegistrationFee(user.getStringifiedBankAccounts(), callback);
} catch (InsufficientMoneyException e) {
payFeeErrorMessage.set("Fee payment failed with error: " + e.getMessage());
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
WalletFacade getWalletFacade() {
return walletFacade;
}
Coin getFeeAsCoin() {
return FeePolicy.REGISTRATION_FEE;
}
String getTransactionId() {
return transactionId;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
// Private
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void updateBalance(@NotNull Coin balance) {
isWalletFunded.set(balance.compareTo(getFeeAsCoin()) >= 0);
}
}

View file

@ -17,16 +17,37 @@
package io.bitsquare.gui.account.registration;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.locale.BSResources;
import com.google.bitcoin.core.Address;
import com.google.bitcoin.core.Coin;
import com.google.inject.Inject;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.gui.util.BSFormatter.formatCoinWithCode;
public class RegistrationPM extends PresentationModel<RegistrationModel> {
private static final Logger log = LoggerFactory.getLogger(RegistrationPM.class);
// Those are needed for the addressTextField
final ObjectProperty<Address> address = new SimpleObjectProperty<>();
final BooleanProperty isPayButtonDisabled = new SimpleBooleanProperty(true);
final StringProperty requestPlaceOfferErrorMessage = new SimpleStringProperty();
final BooleanProperty showTransactionPublishedScreen = new SimpleBooleanProperty();
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@ -38,28 +59,96 @@ public class RegistrationPM extends PresentationModel<RegistrationModel> {
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialized() {
super.initialized();
if (model.addressEntry != null) {
address.set(model.addressEntry.getAddress());
}
model.isWalletFunded.addListener((ov, oldValue, newValue) -> {
if (newValue)
validateInput();
});
validateInput();
model.payFeeSuccess.addListener((ov, oldValue, newValue) -> isPayButtonDisabled.set(newValue));
requestPlaceOfferErrorMessage.bind(model.payFeeErrorMessage);
showTransactionPublishedScreen.bind(model.payFeeSuccess);
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: Initializable
// UI actions (called by CB)
///////////////////////////////////////////////////////////////////////////////////////////
void payFee() {
model.payFeeErrorMessage.set(null);
model.payFeeSuccess.set(false);
isPayButtonDisabled.set(true);
model.payFee();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
// Getters (called by CB)
///////////////////////////////////////////////////////////////////////////////////////////
WalletFacade getWalletFacade() {
return model.getWalletFacade();
}
Coin getFeeAsCoin() {
return model.getFeeAsCoin();
}
String getAddressAsString() {
return model.addressEntry != null ? model.addressEntry.getAddress().toString() : "";
}
String getPaymentLabel() {
return BSResources.get("Bitsquare account registration fee");
}
String getFeeAsString() {
return formatCoinWithCode(model.getFeeAsCoin());
}
String getTransactionId() {
return model.getTransactionId();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void validateInput() {
isPayButtonDisabled.set(!(model.isWalletFunded.get()));
}
}

View file

@ -17,6 +17,10 @@
~ along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
-->
<?import io.bitsquare.gui.components.btc.AddressTextField?>
<?import io.bitsquare.gui.components.btc.BalanceTextField?>
<?import io.bitsquare.gui.components.InfoDisplay?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.account.registration.RegistrationCB" hgap="5.0" vgap="5.0"
@ -24,19 +28,73 @@
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
xmlns:fx="http://javafx.com/fxml">
<children>
<Label text="REG"/>
<Pane id="form-group-background-active" GridPane.columnSpan="2" GridPane.rowSpan="4">
<GridPane.margin>
<Insets bottom="-10.0" left="-10.0" right="-10.0" top="-10.0"/>
</GridPane.margin>
<children>
<Label id="form-group-title-active" text="Fund the registration fee"
layoutX="8" layoutY="-8">
<padding>
<Insets left="5" right="7"/>
</padding>
</Label>
</children>
</Pane>
<Label text="Registration fee:" GridPane.rowIndex="0">
<GridPane.margin>
<Insets top="10.0"/>
</GridPane.margin>
</Label>
<TextField fx:id="feeTextField"
GridPane.columnIndex="1"
GridPane.rowIndex="0"
editable="false" focusTraversable="false">
<GridPane.margin>
<Insets top="10.0"/>
</GridPane.margin>
</TextField>
<Label text="Registration wallet address:" GridPane.rowIndex="1"/>
<AddressTextField fx:id="addressTextField" GridPane.columnIndex="1" GridPane.rowIndex="1"
focusTraversable="true"/>
<Label text="Registration wallet balance:" GridPane.rowIndex="2">
<GridPane.margin>
<Insets bottom="5.0"/>
</GridPane.margin>
</Label>
<BalanceTextField fx:id="balanceTextField" GridPane.columnIndex="1" GridPane.rowIndex="2"
focusTraversable="false">
<GridPane.margin>
<Insets bottom="5.0"/>
</GridPane.margin>
</BalanceTextField>
<InfoDisplay gridPane="$root" onAction="#onOpenHelp" rowIndex="3"
text="You need to pay a tiny registration fee which is needed for storing your encrypted account data in the blockchain. That will be used in the trade process for account verification."/>
<Button fx:id="payButton" text="Pay registration fee" onAction="#onPayFee" GridPane.columnIndex="1"
GridPane.rowIndex="4"
defaultButton="true">
<GridPane.margin>
<Insets top="15.0"/>
</GridPane.margin>
</Button>
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" halignment="RIGHT" minWidth="140.0"/>
<ColumnConstraints hgrow="SOMETIMES" halignment="RIGHT" minWidth="200.0"/>
<ColumnConstraints hgrow="ALWAYS" minWidth="300.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
</rowConstraints>
</GridPane>

View file

@ -19,15 +19,16 @@ package io.bitsquare.gui.account.restrictions;
import io.bitsquare.BitSquare;
import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.CachedCodeBehind;
import io.bitsquare.gui.NavigationItem;
import io.bitsquare.gui.account.settings.AccountSettingsCB;
import io.bitsquare.gui.account.setup.SetupCB;
import io.bitsquare.gui.help.Help;
import io.bitsquare.gui.help.HelpId;
import io.bitsquare.gui.util.ImageUtil;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.Region;
import io.bitsquare.util.BSFXMLLoader;
import java.io.IOException;
@ -60,7 +61,7 @@ public class RestrictionsCB extends CachedCodeBehind<RestrictionsPM> {
@FXML private ComboBox<Locale> languageComboBox;
@FXML private ComboBox<Region> regionComboBox;
@FXML private ComboBox<Country> countryComboBox;
@FXML private Button doneButton, addAllEuroCountriesButton;
@FXML private Button completedButton, addAllEuroCountriesButton;
///////////////////////////////////////////////////////////////////////////////////////////
@ -85,7 +86,7 @@ public class RestrictionsCB extends CachedCodeBehind<RestrictionsPM> {
initCountry();
initArbitrators();
doneButton.disableProperty().bind(presentationModel.doneButtonDisabled);
completedButton.disableProperty().bind(presentationModel.doneButtonDisabled);
}
@Override
@ -108,6 +109,19 @@ public class RestrictionsCB extends CachedCodeBehind<RestrictionsPM> {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Override from CodeBehind
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setParentController(Initializable parentController) {
super.setParentController(parentController);
if (parentController instanceof AccountSettingsCB) {
((GridPane) root).getChildren().remove(completedButton);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@ -140,13 +154,14 @@ public class RestrictionsCB extends CachedCodeBehind<RestrictionsPM> {
@FXML
private void onOpenArbitratorScreen() {
loadViewAndGetChildController(NavigationItem.ARBITRATOR_BROWSER);
loadView(NavigationItem.ARBITRATOR_BROWSER);
}
@FXML
private void onDone() {
((SetupCB) parentController).onCompleted(this);
private void onCompleted() {
if (parentController instanceof SetupCB)
((SetupCB) parentController).onCompleted(this);
}
@FXML
@ -170,9 +185,9 @@ public class RestrictionsCB extends CachedCodeBehind<RestrictionsPM> {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public Initializable loadViewAndGetChildController(NavigationItem navigationItem) {
public Initializable loadView(NavigationItem navigationItem) {
// TODO caching causes exception
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), false);
final BSFXMLLoader loader = new BSFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), false);
try {
final Node view = loader.load();
//TODO Resolve type problem...

View file

@ -37,7 +37,7 @@ public class RestrictionsPM extends PresentationModel<RestrictionsModel> {
private static final Logger log = LoggerFactory.getLogger(RestrictionsPM.class);
public BooleanProperty doneButtonDisabled = new SimpleBooleanProperty(true);
public final BooleanProperty doneButtonDisabled = new SimpleBooleanProperty(true);
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -137,7 +137,7 @@
<InfoDisplay gridPane="$root" onAction="#onOpenArbitratorsHelp" rowIndex="8"
text="You need to choose at least 3 arbitrators."/>
<Button fx:id="doneButton" text="Completed" onAction="#onDone" disable="true" GridPane.columnIndex="1"
<Button fx:id="completedButton" text="Completed" onAction="#onCompleted" disable="true" GridPane.columnIndex="1"
GridPane.rowIndex="9"
defaultButton="true">
<GridPane.margin>

View file

@ -18,6 +18,7 @@
package io.bitsquare.gui.account.seedwords;
import io.bitsquare.gui.CachedCodeBehind;
import io.bitsquare.gui.account.settings.AccountSettingsCB;
import io.bitsquare.gui.account.setup.SetupCB;
import io.bitsquare.gui.help.Help;
import io.bitsquare.gui.help.HelpId;
@ -29,7 +30,9 @@ import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -38,8 +41,10 @@ public class SeedWordsCB extends CachedCodeBehind<SeedWordsPM> {
private static final Logger log = LoggerFactory.getLogger(SeedWordsCB.class);
@FXML private Button completedButton;
@FXML private TextArea seedWordsTextArea;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@ -77,13 +82,28 @@ public class SeedWordsCB extends CachedCodeBehind<SeedWordsPM> {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Override from CodeBehind
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setParentController(Initializable parentController) {
super.setParentController(parentController);
if (parentController instanceof AccountSettingsCB) {
((GridPane) root).getChildren().remove(completedButton);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
private void onDone() {
((SetupCB) parentController).onCompleted(this);
private void onCompleted() {
if (parentController instanceof SetupCB)
if (parentController instanceof SetupCB)
((SetupCB) parentController).onCompleted(this);
}
@FXML

View file

@ -31,7 +31,7 @@ import org.slf4j.LoggerFactory;
public class SeedWordsPM extends PresentationModel<SeedWordsModel> {
private static final Logger log = LoggerFactory.getLogger(SeedWordsPM.class);
StringProperty seedWords = new SimpleStringProperty();
final StringProperty seedWords = new SimpleStringProperty();
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -52,7 +52,8 @@
<Font size="16.0"/>
</font>
</TextArea>
<Button text="I have made my backup" onAction="#onDone" GridPane.columnIndex="1" GridPane.rowIndex="2"
<Button fx:id="completedButton" text="I have made my backup" onAction="#onCompleted"
GridPane.columnIndex="1" GridPane.rowIndex="2"
defaultButton="true">
<GridPane.margin>
<Insets bottom="5"/>

View file

@ -0,0 +1,199 @@
/*
* 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.account.settings;
import io.bitsquare.gui.CachedCodeBehind;
import io.bitsquare.gui.CodeBehind;
import io.bitsquare.gui.NavigationItem;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.util.BSFXMLLoader;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.geometry.Pos;
import javafx.scene.*;
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 AccountSettingsCB extends CachedCodeBehind<AccountSettingsPM> {
private static final Logger log = LoggerFactory.getLogger(AccountSettingsCB.class);
public VBox leftVBox;
public AnchorPane content;
private MenuItem seedWords, password, fiatAccount, restrictions, registration;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public AccountSettingsCB(AccountSettingsPM presentationModel) {
super(presentationModel);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
ToggleGroup toggleGroup = new ToggleGroup();
seedWords = new MenuItem(this, content, "Wallet seed",
NavigationItem.SEED_WORDS, toggleGroup);
password = new MenuItem(this, content, "Wallet password",
NavigationItem.CHANGE_PASSWORD, toggleGroup);
restrictions = new MenuItem(this, content, "Trading restrictions",
NavigationItem.RESTRICTIONS, toggleGroup);
fiatAccount = new MenuItem(this, content, "Payments account(s)",
NavigationItem.FIAT_ACCOUNT, toggleGroup);
registration = new MenuItem(this, content, "Renew your account",
NavigationItem.REGISTRATION, toggleGroup);
// registration.setDisable(true);
leftVBox.getChildren().addAll(seedWords, password,
restrictions, fiatAccount, registration);
seedWords.fire();
}
@Override
public void activate() {
super.activate();
}
@Override
public void deactivate() {
super.deactivate();
}
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Public Methods
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
}
class MenuItem extends ToggleButton {
private static final Logger log = LoggerFactory.getLogger(MenuItem.class);
private CodeBehind<? extends PresentationModel> childController;
private final AccountSettingsCB parentCB;
private final Parent content;
private final NavigationItem navigationItem;
MenuItem(AccountSettingsCB parentCB, Parent content, String title, NavigationItem navigationItem,
ToggleGroup toggleGroup) {
this.parentCB = parentCB;
this.content = content;
this.navigationItem = navigationItem;
setPrefHeight(40);
setPrefWidth(200);
setAlignment(Pos.CENTER_LEFT);
setToggleGroup(toggleGroup);
setText(title);
setId("account-settings-item-background-active");
Label icon = new Label();
icon.setTextFill(Paint.valueOf("#999"));
AwesomeDude.setIcon(icon, AwesomeIcon.EDIT_SIGN);
setGraphic(icon);
setOnAction((event) -> show());
selectedProperty().addListener((ov, oldValue, newValue) -> {
if (newValue) {
setId("account-settings-item-background-selected");
icon.setTextFill(Paint.valueOf("#0096c9"));
}
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"));
}
});
}
void show() {
final BSFXMLLoader loader = new BSFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
try {
final Pane view = loader.load();
((AnchorPane) content).getChildren().setAll(view);
childController = loader.getController();
childController.setParentController(parentCB);
} catch (IOException e) {
log.error("Loading view failed. FxmlUrl = " + navigationItem.getFxmlUrl());
e.getStackTrace();
}
}
CodeBehind<? extends PresentationModel> getChildController() {
return childController;
}
}

View file

@ -0,0 +1,65 @@
/*
* 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.account.settings;
import io.bitsquare.gui.UIModel;
import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AccountSettingsModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(AccountSettingsModel.class);
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public AccountSettingsModel() {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: Initializable
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
}

View file

@ -0,0 +1,65 @@
/*
* 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.account.settings;
import io.bitsquare.gui.PresentationModel;
import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AccountSettingsPM extends PresentationModel<AccountSettingsModel> {
private static final Logger log = LoggerFactory.getLogger(AccountSettingsPM.class);
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public AccountSettingsPM(AccountSettingsModel model) {
super(model);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: Initializable
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
}

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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/>.
-->
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.account.settings.AccountSettingsCB"
prefHeight="660.0" prefWidth="1000.0"
xmlns:fx="http://javafx.com/fxml">
<VBox fx:id="leftVBox" spacing="5" prefWidth="200" AnchorPane.bottomAnchor="20" AnchorPane.leftAnchor="20"
AnchorPane.topAnchor="20"/>
<AnchorPane fx:id="content" AnchorPane.bottomAnchor="10" AnchorPane.rightAnchor="30" AnchorPane.leftAnchor="250"
AnchorPane.topAnchor="30" prefWidth="720"/>
</AnchorPane>

View file

@ -17,17 +17,18 @@
package io.bitsquare.gui.account.setup;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.CachedCodeBehind;
import io.bitsquare.gui.CodeBehind;
import io.bitsquare.gui.NavigationItem;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.account.AccountCB;
import io.bitsquare.gui.account.addpassword.PasswordCB;
import io.bitsquare.gui.account.fiataccount.FiatAccountCB;
import io.bitsquare.gui.account.password.PasswordCB;
import io.bitsquare.gui.account.registration.RegistrationCB;
import io.bitsquare.gui.account.restrictions.RestrictionsCB;
import io.bitsquare.gui.account.seedwords.SeedWordsCB;
import io.bitsquare.gui.util.ImageUtil;
import io.bitsquare.util.BSFXMLLoader;
import java.io.IOException;
@ -74,14 +75,14 @@ public class SetupCB extends CachedCodeBehind<SetupPM> {
seedWords = new WizardItem(this, content, "Backup wallet seed", "Write down the seed word for your wallet",
NavigationItem.SEED_WORDS);
password = new WizardItem(this, content, "Setup password", "Protect your wallet with a password",
NavigationItem.PASSWORD);
NavigationItem.ADD_PASSWORD);
restrictions = new WizardItem(this, content, "Setup your preferences",
"Define your preferences with whom you want to trade",
NavigationItem.RESTRICTIONS);
fiatAccount = new WizardItem(this, content, " Setup Payments account(s)",
"You need to add a payments account to your trading account",
NavigationItem.FIAT_ACCOUNT);
registration = new WizardItem(this, root, "Register your account",
registration = new WizardItem(this, content, "Register your account",
"Pay in the registration fee of 0.0002 BTC and store your account in the BTC block chain",
NavigationItem.REGISTRATION);
@ -110,11 +111,10 @@ public class SetupCB extends CachedCodeBehind<SetupPM> {
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
public void onCompleted(CodeBehind<? extends PresentationModel> childView) {
if (childView instanceof SeedWordsCB) {
seedWords.onCompleted();
childController = password.show(NavigationItem.PASSWORD);
childController = password.show(NavigationItem.ADD_PASSWORD);
}
else if (childView instanceof PasswordCB) {
password.onCompleted();
@ -131,6 +131,8 @@ public class SetupCB extends CachedCodeBehind<SetupPM> {
else if (childView instanceof RegistrationCB) {
registration.onCompleted();
childController = null;
((AccountCB) parentController).removeSetup();
}
}
@ -233,7 +235,7 @@ class WizardItem extends HBox {
}
private void loadView(NavigationItem navigationItem) {
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
final BSFXMLLoader loader = new BSFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
try {
final Pane view = loader.load();
((AnchorPane) content).getChildren().setAll(view);
@ -241,9 +243,7 @@ class WizardItem extends HBox {
childController.setParentController(parentCB);
} catch (IOException e) {
log.error("Loading view failed. FxmlUrl = " + navigationItem.getFxmlUrl());
// log.error(e.getCause().toString());
log.error(e.getMessage());
log.error(e.getStackTrace().toString());
e.getStackTrace();
}
}

View file

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

View file

@ -18,7 +18,6 @@
package io.bitsquare.gui.arbitrators.browser;
import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.CachedViewController;
import io.bitsquare.gui.NavigationItem;
import io.bitsquare.gui.ViewController;
@ -28,6 +27,7 @@ import io.bitsquare.msg.MessageFacade;
import io.bitsquare.msg.listeners.ArbitratorListener;
import io.bitsquare.persistence.Persistence;
import io.bitsquare.settings.Settings;
import io.bitsquare.util.BSFXMLLoader;
import java.io.IOException;
@ -123,7 +123,7 @@ public class ArbitratorBrowserController extends CachedViewController implements
@Override
public Initializable loadViewAndGetChildController(NavigationItem navigationItem) {
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
final BSFXMLLoader loader = new BSFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
try {
final Node view = loader.load();
arbitratorProfileController = loader.getController();

View file

@ -8,15 +8,29 @@ dark grey: #333333
main bg grey: dddddd
content bg grey: f4f4f4
tab pane upper bg gradient color mid dark grey to bright grey: cfcfcf -> dddddd
upper border on tab: cfcfcf
lower border on tab: b5b5b5
upper gradient color on tab: d3d3d3
lower gradient color on tab: dddddd
*/
/* Account */
#content-pane-top {
-fx-background-color: linear-gradient(to bottom, #cfcfcf, #dddddd);
-fx-background-color:
#cfcfcf,
linear-gradient(#cfcfcf 0%, #b5b5b5 100%),
linear-gradient(#d3d3d3 0%, #dddddd 100%);
-fx-background-insets: 0 0 0 0,0,1;
}
#content-pane-label {
-fx-font-size: 14;
-fx-text-fill: #000;
}
#info-icon-label {
-fx-font-size:16;
-fx-text-fill: #333000;
@ -58,7 +72,7 @@ tab pane upper bg gradient color mid dark grey to bright grey: cfcfcf -> dddddd
}
/* Registration */
/* Account setup */
#wizard-title-deactivated {
-fx-font-weight: bold;
-fx-font-size: 16;
@ -119,6 +133,57 @@ tab pane upper bg gradient color mid dark grey to bright grey: cfcfcf -> dddddd
/* Account settings */
#wizard-title-disabled {
-fx-font-weight: bold;
-fx-font-size: 16;
-fx-text-fill: #ccc;
}
#wizard-title-active {
-fx-font-weight: bold;
-fx-font-size: 16;
-fx-text-fill: #000;
}
#wizard-title-selected {
-fx-font-weight: bold;
-fx-font-size: 16;
-fx-text-fill: #0096c9;
}
#account-settings-item-background-disabled {
-fx-body-color: linear-gradient(to bottom, #f4f4f4, #F0F0F0);
-fx-outer-border: linear-gradient(to bottom, #ddd, #ccc);
-fx-background-color: -fx-shadow-highlight-color,
-fx-outer-border,
-fx-inner-border,
-fx-body-color;
-fx-background-insets: 0 0 -1 0, 0, 1, 2;
-fx-background-radius: 3px, 3px, 2px, 1px;
}
#account-settings-item-background-active {
-fx-body-color: linear-gradient(to bottom, #f4f4f4, #F0F0F0);
-fx-outer-border: linear-gradient(to bottom, #ddd, #ccc);
-fx-background-color: -fx-shadow-highlight-color,
-fx-outer-border,
-fx-inner-border,
-fx-body-color;
-fx-background-insets: 0 0 -1 0, 0, 1, 2;
-fx-background-radius: 3px, 3px, 2px, 1px;
}
#account-settings-item-background-selected {
-fx-body-color: linear-gradient(to bottom, #f1f6f7, #e7f5f9);
-fx-outer-border: linear-gradient(to bottom, #b5e1ef, #6aa4b6);
-fx-background-color: -fx-shadow-highlight-color,
-fx-outer-border,
-fx-inner-border,
-fx-body-color;
-fx-background-insets: 0 0 -1 0, 0, 1, 2;
-fx-background-radius: 3px, 3px, 2px, 1px;
}
/* Splash */
#splash {
-fx-background-color: #ffffff;

View file

@ -17,9 +17,9 @@
package io.bitsquare.gui.components;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.ViewController;
import io.bitsquare.persistence.Persistence;
import io.bitsquare.util.BSFXMLLoader;
import java.io.IOException;
@ -96,7 +96,7 @@ public class CachingTabPane extends TabPane {
selectedTabIndex = getSelectionModel().getSelectedIndex();
TabInfo selectedTabInfo = tabInfoList.get(selectedTabIndex);
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(selectedTabInfo.url));
final BSFXMLLoader loader = new BSFXMLLoader(getClass().getResource(selectedTabInfo.url));
try {
Node view = loader.load();
selectedTabInfo.controller = loader.getController();

View file

@ -42,6 +42,9 @@ import org.slf4j.LoggerFactory;
/**
* Collection of controlsfx Popups
* <p>
* TODO Replace it with custom views as they are graphically more flexible and the Dialogs are a bit limited from the
* API
*/
public class Popups {
private static final Logger log = LoggerFactory.getLogger(Popups.class);

View file

@ -17,6 +17,7 @@
package io.bitsquare.gui.components.btc;
import io.bitsquare.gui.MainController;
import io.bitsquare.gui.components.Popups;
import com.google.bitcoin.core.Coin;
@ -123,11 +124,13 @@ public class AddressTextField extends AnchorPane {
PopOver popOver = new PopOver(pane);
popOver.setDetachedTitle("Scan QR code for this address");
popOver.setDetached(true);
popOver.setOnHiding(windowEvent -> MainController.GET_INSTANCE().removeContentScreenBlur());
Window window = getScene().getWindow();
double x = Math.round(window.getX() + (window.getWidth() - 320) / 2);
double y = Math.round(window.getY() + (window.getHeight() - 240) / 2);
popOver.show(getScene().getWindow(), x, y);
MainController.GET_INSTANCE().blurContentScreen();
}
});

View file

@ -28,7 +28,8 @@ public enum HelpId {
SETUP_RESTRICTION_ARBITRATORS,
SETUP_REGISTRATION,
SETUP_FIAT_ACCOUNT,
MANAGE_FIAT_ACCOUNT
MANAGE_FIAT_ACCOUNT,
PAY_ACCOUNT_FEE
}

View file

@ -18,10 +18,10 @@
package io.bitsquare.gui.home;
import io.bitsquare.BitSquare;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.CachedViewController;
import io.bitsquare.gui.NavigationItem;
import io.bitsquare.gui.arbitrators.registration.ArbitratorRegistrationController;
import io.bitsquare.util.BSFXMLLoader;
import java.io.IOException;
@ -72,7 +72,7 @@ public class HomeController extends CachedViewController {
@Override
public Initializable loadViewAndGetChildController(NavigationItem navigationItem) {
// don't use caching here, cause exc. -> need to investigate and is rarely called so no caching is better
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), false);
final BSFXMLLoader loader = new BSFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), false);
try {
final Parent view = loader.load();
arbitratorRegistrationController = loader.getController();

View file

@ -17,94 +17,22 @@
package io.bitsquare.gui.settings;
import io.bitsquare.BitSquare;
import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.arbitrator.Reputation;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.CachedViewController;
import io.bitsquare.gui.NavigationItem;
import io.bitsquare.gui.ViewController;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.util.BitSquareValidator;
import io.bitsquare.gui.util.ImageUtil;
import io.bitsquare.locale.BSResources;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.CountryUtil;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.locale.LanguageUtil;
import io.bitsquare.locale.Region;
import io.bitsquare.msg.MessageFacade;
import io.bitsquare.persistence.Persistence;
import io.bitsquare.settings.Settings;
import io.bitsquare.user.User;
import io.bitsquare.util.DSAKeyUtil;
import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.Utils;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Currency;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;
import org.controlsfx.control.action.Action;
import org.controlsfx.dialog.Dialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// TODO separate in 2 view/controllers
// TODO: change ui to dispaly a menu on the left and the content on the right
// there will be more screens
public class SettingsController extends CachedViewController {
private static final Logger log = LoggerFactory.getLogger(SettingsController.class);
private final User user;
private final Settings settings;
private final Persistence persistence;
private final MessageFacade messageFacade;
private final ObservableList<Locale> languageList;
private final ObservableList<Country> countryList;
private ViewController childController;
private ObservableList<Arbitrator> arbitratorList;
@FXML private ListView<Locale> languagesListView;
@FXML private ListView<Country> countriesListView;
@FXML private ListView<Arbitrator> arbitratorsListView;
@FXML private ComboBox<Locale> languageComboBox;
@FXML private ComboBox<Region> regionComboBox, bankAccountRegionComboBox;
@FXML private ComboBox<Country> countryComboBox, bankAccountCountryComboBox;
@FXML private TextField bankAccountTitleTextField, bankAccountHolderNameTextField, bankAccountPrimaryIDTextField,
bankAccountSecondaryIDTextField;
@FXML private Button saveBankAccountButton, addBankAccountButton;
@FXML private ComboBox<BankAccount> bankAccountComboBox;
@FXML private ComboBox<BankAccountType> bankAccountTypesComboBox;
@FXML private ComboBox<Currency> bankAccountCurrencyComboBox;
///////////////////////////////////////////////////////////////////////////////////////////
@ -112,32 +40,7 @@ public class SettingsController extends CachedViewController {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public SettingsController(User user, Settings settings, Persistence persistence, MessageFacade messageFacade) {
this.user = user;
this.settings = settings;
this.persistence = persistence;
this.messageFacade = messageFacade;
Settings persistedSettings = (Settings) persistence.read(settings);
if (persistedSettings != null) {
settings.applyPersistedSettings(persistedSettings);
languageList = FXCollections.observableArrayList(settings.getAcceptedLanguageLocales());
countryList = FXCollections.observableArrayList(settings.getAcceptedCountries());
arbitratorList = FXCollections.observableArrayList(settings.getAcceptedArbitrators());
}
else {
languageList = FXCollections.observableArrayList(new ArrayList<>());
countryList = FXCollections.observableArrayList(new ArrayList<>());
arbitratorList = FXCollections.observableArrayList(new ArrayList<>());
if (Locale.getDefault() != null) {
addLanguage(LanguageUtil.getDefaultLanguageLocale());
addCountry(CountryUtil.getDefaultCountry());
}
// Add english as default as well
addLanguage(LanguageUtil.getEnglishLanguageLocale());
}
public SettingsController() {
}
///////////////////////////////////////////////////////////////////////////////////////////
@ -147,10 +50,6 @@ public class SettingsController extends CachedViewController {
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
setupGeneralSettingsScreen();
initBankAccountScreen();
addMockArbitrator();
}
@Override
@ -170,37 +69,7 @@ public class SettingsController extends CachedViewController {
@Override
public Initializable loadViewAndGetChildController(NavigationItem navigationItem) {
// TODO caching causes exception
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), false);
try {
final Node view = loader.load();
childController = loader.getController();
childController.setParentController(this);
final Stage rootStage = BitSquare.getPrimaryStage();
final Stage stage = new Stage();
stage.setTitle("Arbitrator selection");
stage.setMinWidth(800);
stage.setMinHeight(500);
stage.setWidth(800);
stage.setHeight(600);
stage.setX(rootStage.getX() + 50);
stage.setY(rootStage.getY() + 50);
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(rootStage);
Scene scene = new Scene((Parent) view, 800, 600);
stage.setScene(scene);
stage.setOnHidden(windowEvent -> {
if (navigationItem == NavigationItem.ARBITRATOR_BROWSER)
updateArbitrators();
});
stage.show();
return childController;
} catch (IOException e) {
e.printStackTrace();
}
return null;
return super.loadViewAndGetChildController(navigationItem);
}
@ -208,582 +77,16 @@ public class SettingsController extends CachedViewController {
// Public Methods
///////////////////////////////////////////////////////////////////////////////////////////
void updateArbitrators() {
arbitratorList = FXCollections.observableArrayList(settings.getAcceptedArbitrators());
initArbitrators();
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
// General Settings
@FXML
public void onAddLanguage() {
addLanguage(languageComboBox.getSelectionModel().getSelectedItem());
languageComboBox.getSelectionModel().clearSelection();
}
@FXML
public void onSelectRegion() {
countryComboBox.setVisible(true);
Region selectedRegion = regionComboBox.getSelectionModel().getSelectedItem();
countryComboBox.setItems(FXCollections.observableArrayList(CountryUtil.getAllCountriesFor(selectedRegion)));
}
@FXML
public void onAddCountry() {
addCountry(countryComboBox.getSelectionModel().getSelectedItem());
countryComboBox.getSelectionModel().clearSelection();
}
@FXML
public void onOpenArbitratorScreen() {
loadViewAndGetChildController(NavigationItem.ARBITRATOR_BROWSER);
}
// Bank Account Settings
@FXML
public void selectBankAccount() {
BankAccount bankAccount = bankAccountComboBox.getSelectionModel().getSelectedItem();
if (bankAccount != null && bankAccount != user.getCurrentBankAccount()) {
user.setCurrentBankAccount(bankAccount);
persistence.write(user);
fillWithCurrentBankAccount();
}
}
@FXML
public void selectBankAccountType() {
BankAccountType bankAccountType = bankAccountTypesComboBox.getSelectionModel().getSelectedItem();
if (bankAccountType != null) {
bankAccountTitleTextField.setText("");
bankAccountPrimaryIDTextField.setText("");
bankAccountPrimaryIDTextField.setPromptText(bankAccountType.getPrimaryId());
bankAccountSecondaryIDTextField.setText("");
bankAccountSecondaryIDTextField.setPromptText(bankAccountType.getSecondaryId());
}
}
@FXML
public void onSelectBankAccountRegion() {
bankAccountCountryComboBox.setVisible(true);
Region selectedBankAccountRegion = bankAccountRegionComboBox.getSelectionModel().getSelectedItem();
bankAccountCountryComboBox.setItems(
FXCollections.observableArrayList(CountryUtil.getAllCountriesFor(selectedBankAccountRegion)));
}
@FXML
public void onAddBankAccount() {
saveBankAccount();
resetBankAccountInput();
}
@FXML
public void onRemoveBankAccount() {
removeBankAccount();
}
@FXML
void onSaveBankAccount() {
saveBankAccount();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
// General Settings
private void setupGeneralSettingsScreen() {
initLanguage();
initCountry();
initArbitrators();
}
private void initLanguage() {
languagesListView.setCellFactory(new Callback<ListView<Locale>, ListCell<Locale>>() {
@Override
public ListCell<Locale> call(ListView<Locale> list) {
return new ListCell<Locale>() {
final HBox hBox = new HBox();
final Label label = new Label();
final Button removeButton = new Button();
final ImageView icon = ImageUtil.getIconImageView(ImageUtil.REMOVE);
{
label.setPrefWidth(565);
icon.setMouseTransparent(true);
removeButton.setGraphic(icon);
removeButton.setId("icon-button");
hBox.setSpacing(3);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.getChildren().addAll(label, removeButton);
}
@Override
public void updateItem(final Locale item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
label.setText(item.getDisplayName());
removeButton.setOnAction(actionEvent -> removeLanguage(item));
setGraphic(hBox);
}
else {
setGraphic(null);
}
}
};
}
});
languagesListView.setItems(languageList);
languageComboBox.setItems(FXCollections.observableArrayList(LanguageUtil.getAllLanguageLocales()));
languageComboBox.setConverter(new StringConverter<Locale>() {
@Override
public String toString(Locale locale) {
return locale.getDisplayLanguage();
}
@Override
public Locale fromString(String s) {
return null;
}
});
}
private void initCountry() {
regionComboBox.setItems(FXCollections.observableArrayList(CountryUtil.getAllRegions()));
regionComboBox.setConverter(new StringConverter<Region>() {
@Override
public String toString(Region region) {
return region.getName();
}
@Override
public Region fromString(String s) {
return null;
}
});
countriesListView.setCellFactory(new Callback<ListView<Country>, ListCell<Country>>() {
@Override
public ListCell<Country> call(ListView<Country> list) {
return new ListCell<Country>() {
final HBox hBox = new HBox();
final Label label = new Label();
final Button removeButton = new Button();
final ImageView icon = ImageUtil.getIconImageView(ImageUtil.REMOVE);
{
label.setPrefWidth(565);
icon.setMouseTransparent(true);
removeButton.setGraphic(icon);
removeButton.setId("icon-button");
hBox.setSpacing(3);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.getChildren().addAll(label, removeButton);
}
@Override
public void updateItem(final Country item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
label.setText(item.getName());
removeButton.setOnAction(actionEvent -> removeCountry(item));
setGraphic(hBox);
}
else {
setGraphic(null);
}
}
};
}
});
countriesListView.setItems(countryList);
countryComboBox.setConverter(new StringConverter<Country>() {
@Override
public String toString(Country country) {
return country.getName();
}
@Override
public Country fromString(String s) {
return null;
}
});
}
private void initArbitrators() {
arbitratorsListView.setCellFactory(new Callback<ListView<Arbitrator>, ListCell<Arbitrator>>() {
@Override
public ListCell<Arbitrator> call(ListView<Arbitrator> list) {
return new ListCell<Arbitrator>() {
final HBox hBox = new HBox();
final Label label = new Label();
final Button removeButton = new Button();
final ImageView icon = ImageUtil.getIconImageView(ImageUtil.REMOVE);
{
label.setPrefWidth(565);
icon.setMouseTransparent(true);
removeButton.setGraphic(icon);
removeButton.setId("icon-button");
hBox.setSpacing(3);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.getChildren().addAll(label, removeButton);
}
@Override
public void updateItem(final Arbitrator item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
label.setText(item.getName());
removeButton.setOnAction(actionEvent -> removeArbitrator(item));
setGraphic(hBox);
}
else {
setGraphic(null);
}
}
};
}
});
arbitratorsListView.setItems(arbitratorList);
}
private void addLanguage(Locale locale) {
if (locale != null && !languageList.contains(locale)) {
languageList.add(locale);
settings.addAcceptedLanguageLocale(locale);
}
}
private void removeLanguage(Locale locale) {
languageList.remove(locale);
settings.removeAcceptedLanguageLocale(locale);
saveSettings();
}
private void addCountry(Country country) {
if (!countryList.contains(country) && country != null) {
countryList.add(country);
settings.addAcceptedCountry(country);
saveSettings();
}
}
private void removeCountry(Country country) {
countryList.remove(country);
settings.removeAcceptedCountry(country);
saveSettings();
}
private void removeArbitrator(Arbitrator arbitrator) {
arbitratorList.remove(arbitrator);
settings.removeAcceptedArbitrator(arbitrator);
saveSettings();
}
private void saveSettings() {
persistence.write(settings);
}
private void saveUser() {
persistence.write(user);
}
// Bank Account Settings
private void fillWithCurrentBankAccount() {
BankAccount currentBankAccount = user.getCurrentBankAccount();
if (currentBankAccount != null) {
bankAccountTitleTextField.setText(currentBankAccount.getAccountTitle());
bankAccountHolderNameTextField.setText(currentBankAccount.getAccountHolderName());
bankAccountPrimaryIDTextField.setText(currentBankAccount.getAccountPrimaryID());
bankAccountPrimaryIDTextField.setPromptText(currentBankAccount.getBankAccountType().getPrimaryId());
bankAccountSecondaryIDTextField.setText(currentBankAccount.getAccountSecondaryID());
bankAccountSecondaryIDTextField.setPromptText(currentBankAccount.getBankAccountType().getSecondaryId());
}
else {
resetBankAccountInput();
}
}
private void initBankAccountScreen() {
initBankAccountComboBox();
initBankAccountTypesComboBox();
initBankAccountCurrencyComboBox();
initBankAccountCountryComboBox();
fillWithCurrentBankAccount();
//TODO
if (BitSquare.fillFormsWithDummyData) {
bankAccountTypesComboBox.getSelectionModel().selectFirst();
bankAccountCurrencyComboBox.getSelectionModel().selectFirst();
bankAccountRegionComboBox.getSelectionModel().select(3);
Optional<Country> country = bankAccountCountryComboBox.getItems().stream().filter(e ->
e.getCode().equals(CountryUtil.getDefaultCountry().getCode())).findFirst();
if (country.isPresent())
bankAccountCountryComboBox.getSelectionModel().select(country.get());
bankAccountTitleTextField.setText("dummy title");
bankAccountHolderNameTextField.setText("dummy name");
bankAccountPrimaryIDTextField.setText("dummy primary ID");
bankAccountSecondaryIDTextField.setText("dummy secondary ID");
if (user.getCurrentBankAccount() == null)
onSaveBankAccount();
}
}
private void resetBankAccountInput() {
bankAccountTitleTextField.setText("");
bankAccountHolderNameTextField.setText("");
bankAccountPrimaryIDTextField.setText("");
bankAccountPrimaryIDTextField.setPromptText("");
bankAccountSecondaryIDTextField.setText("");
bankAccountSecondaryIDTextField.setPromptText("");
bankAccountTypesComboBox.getSelectionModel().clearSelection();
bankAccountCurrencyComboBox.getSelectionModel().clearSelection();
}
private void initBankAccountComboBox() {
if (user.getBankAccounts().isEmpty()) {
bankAccountComboBox.setPromptText("No bank account available");
bankAccountComboBox.setDisable(true);
}
else {
bankAccountComboBox.setPromptText("Select bank account");
bankAccountComboBox.setDisable(false);
bankAccountComboBox.setItems(FXCollections.observableArrayList(user.getBankAccounts()));
bankAccountComboBox.setConverter(new StringConverter<BankAccount>() {
@Override
public String toString(BankAccount bankAccount) {
return bankAccount.getAccountTitle();
}
@Override
public BankAccount fromString(String s) {
return null;
}
});
BankAccount currentBankAccount = user.getCurrentBankAccount();
if (currentBankAccount != null) {
int index = bankAccountComboBox.getItems().indexOf(currentBankAccount);
bankAccountComboBox.getSelectionModel().select(index);
}
}
}
private void initBankAccountTypesComboBox() {
bankAccountTypesComboBox.setItems(FXCollections.observableArrayList(BankAccountType.getAllBankAccountTypes()));
bankAccountTypesComboBox.setConverter(new StringConverter<BankAccountType>() {
@Override
public String toString(BankAccountType bankAccountTypeInfo) {
return BSResources.get(bankAccountTypeInfo.toString());
}
@Override
public BankAccountType fromString(String s) {
return null;
}
});
BankAccount currentBankAccount = user.getCurrentBankAccount();
if (currentBankAccount != null) {
int index = bankAccountTypesComboBox.getItems().indexOf(currentBankAccount.getBankAccountType());
bankAccountTypesComboBox.getSelectionModel().select(index);
}
}
private void initBankAccountCurrencyComboBox() {
bankAccountCurrencyComboBox.setItems(FXCollections.observableArrayList(CurrencyUtil.getAllCurrencies()));
bankAccountCurrencyComboBox.setConverter(new StringConverter<Currency>() {
@Override
public String toString(Currency currency) {
return currency.getCurrencyCode() + " (" + currency.getDisplayName() + ")";
}
@Override
public Currency fromString(String s) {
return null;
}
});
BankAccount currentBankAccount = user.getCurrentBankAccount();
if (currentBankAccount != null) {
Currency currentCurrency = currentBankAccount.getCurrency();
int index = bankAccountCurrencyComboBox.getItems().indexOf(currentCurrency);
bankAccountCurrencyComboBox.getSelectionModel().select(index);
}
}
private void initBankAccountCountryComboBox() {
bankAccountRegionComboBox.setItems(FXCollections.observableArrayList(CountryUtil.getAllRegions()));
bankAccountRegionComboBox.setConverter(new StringConverter<Region>() {
@Override
public String toString(Region region) {
return region.getName();
}
@Override
public Region fromString(String s) {
return null;
}
});
bankAccountCountryComboBox.setConverter(new StringConverter<Country>() {
@Override
public String toString(Country country) {
return country.getName();
}
@Override
public Country fromString(String s) {
return null;
}
});
BankAccount currentBankAccount = user.getCurrentBankAccount();
if (currentBankAccount != null) {
Country currentCountry = currentBankAccount.getCountry();
Region currentRegion = currentCountry.getRegion();
int regionIndex = bankAccountRegionComboBox.getItems().indexOf(currentRegion);
bankAccountRegionComboBox.getSelectionModel().select(regionIndex);
bankAccountCountryComboBox.setVisible(true);
int countryIndex = bankAccountCountryComboBox.getItems().indexOf(currentCountry);
bankAccountCountryComboBox.getSelectionModel().select(countryIndex);
}
}
private void saveBankAccount() {
if (verifyBankAccountData()) {
BankAccount bankAccount = new BankAccount(bankAccountTypesComboBox.getSelectionModel().getSelectedItem(),
bankAccountCurrencyComboBox.getSelectionModel().getSelectedItem(),
bankAccountCountryComboBox.getSelectionModel().getSelectedItem(),
bankAccountTitleTextField.getText(),
bankAccountHolderNameTextField.getText(),
bankAccountPrimaryIDTextField.getText(),
bankAccountSecondaryIDTextField.getText());
user.setBankAccount(bankAccount);
saveUser();
if (!settings.getAcceptedCountries().contains(bankAccount.getCountry())) {
List<Action> actions = new ArrayList<>();
actions.add(Dialog.Actions.YES);
actions.add(Dialog.Actions.NO);
Action response = Popups.openConfirmPopup("Warning",
"The country of your bank account is not included in the accepted countries in the general " +
"settings.\n\nDo you want to add it automatically?",
null,
actions);
if (response == Dialog.Actions.YES)
addCountry(bankAccount.getCountry());
}
}
}
private void removeBankAccount() {
user.removeCurrentBankAccount();
saveUser();
saveSettings();
fillWithCurrentBankAccount();
}
private boolean verifyBankAccountData() {
try {
BitSquareValidator.textFieldsNotEmptyWithReset(
bankAccountTitleTextField, bankAccountHolderNameTextField,
bankAccountPrimaryIDTextField, bankAccountSecondaryIDTextField);
BankAccountType bankAccountTypeInfo = bankAccountTypesComboBox.getSelectionModel().getSelectedItem();
BitSquareValidator.textFieldBankAccountPrimaryIDIsValid(bankAccountPrimaryIDTextField, bankAccountTypeInfo);
BitSquareValidator.textFieldBankAccountSecondaryIDIsValid(bankAccountSecondaryIDTextField,
bankAccountTypeInfo);
return bankAccountTypesComboBox.getSelectionModel().getSelectedItem() != null &&
bankAccountCountryComboBox.getSelectionModel().getSelectedItem() != null &&
bankAccountCurrencyComboBox.getSelectionModel().getSelectedItem() != null;
} catch (BitSquareValidator.ValidationException e) {
return false;
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Arbitrators
///////////////////////////////////////////////////////////////////////////////////////////
private void addMockArbitrator() {
if (settings.getAcceptedArbitrators().isEmpty()) {
String pubKeyAsHex = Utils.HEX.encode(new ECKey().getPubKey());
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getMessagePublicKey());
List<Locale> languages = new ArrayList<>();
languages.add(LanguageUtil.getDefaultLanguageLocale());
List<Arbitrator.METHOD> arbitrationMethods = new ArrayList<>();
arbitrationMethods.add(Arbitrator.METHOD.TLS_NOTARY);
List<Arbitrator.ID_VERIFICATION> idVerifications = new ArrayList<>();
idVerifications.add(Arbitrator.ID_VERIFICATION.PASSPORT);
idVerifications.add(Arbitrator.ID_VERIFICATION.GOV_ID);
Arbitrator arbitrator = new Arbitrator(pubKeyAsHex,
messagePubKeyAsHex,
"Manfred Karrer",
Arbitrator.ID_TYPE.REAL_LIFE_ID,
languages,
new Reputation(),
1,
0.01,
0.001,
10,
0.1,
arbitrationMethods,
idVerifications,
"http://bitsquare.io/",
"Bla bla...");
arbitratorList.add(arbitrator);
settings.addAcceptedArbitrator(arbitrator);
persistence.write(settings);
messageFacade.addArbitrator(arbitrator);
}
}
}

View file

@ -17,118 +17,14 @@
~ along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
-->
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.settings.SettingsController"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0"
AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0"
AnchorPane.rightAnchor="0" AnchorPane.topAnchor="0"
xmlns:fx="http://javafx.com/fxml">
<Tab text="General" closable="false">
<GridPane hgap="5.0" vgap="5.0">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</padding>
<Label text="Accepted languages:"/>
<ListView fx:id="languagesListView" prefHeight="300.0" prefWidth="400.0" GridPane.columnIndex="1"/>
<Label text="Accepted countries:" GridPane.rowIndex="2"/>
<Label text="Accepted arbitrators:" GridPane.rowIndex="4"/>
<ListView fx:id="countriesListView" prefHeight="300.0" prefWidth="400.0" GridPane.columnIndex="1"
GridPane.rowIndex="2"/>
<ListView fx:id="arbitratorsListView" prefHeight="300.0" prefWidth="400.0" GridPane.columnIndex="1"
GridPane.rowIndex="4"/>
<ComboBox fx:id="languageComboBox" onAction="#onAddLanguage" prefWidth="150.0" promptText="Add language"
GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<HBox spacing="10" GridPane.columnIndex="1" GridPane.rowIndex="3">
<ComboBox fx:id="regionComboBox" onAction="#onSelectRegion" prefWidth="150.0"
promptText="Select region"/>
<ComboBox fx:id="countryComboBox" onAction="#onAddCountry" visible="false" prefWidth="150.0"
promptText="Add country"/>
</HBox>
<Button onAction="#onOpenArbitratorScreen" text="Add arbitrator" GridPane.columnIndex="1"
GridPane.rowIndex="5"/>
<columnConstraints>
<ColumnConstraints/>
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="ALWAYS"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="ALWAYS"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="ALWAYS"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
</rowConstraints>
</GridPane>
</Tab>
<Tab text="Bank accounts" closable="false">
<GridPane hgap="5.0" vgap="5.0">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</padding>
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES"/>
<ColumnConstraints hgrow="ALWAYS"/>
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
</rowConstraints>
<Label text="Bank account:"/>
<ComboBox fx:id="bankAccountComboBox" onAction="#selectBankAccount" GridPane.columnIndex="1"/>
<Label text="Bank account type:" GridPane.rowIndex="1"/>
<ComboBox fx:id="bankAccountTypesComboBox" promptText="Select bank account type"
onAction="#selectBankAccountType" GridPane.rowIndex="1" GridPane.columnIndex="1"/>
<Label text="Bank account title:" GridPane.rowIndex="2"/>
<TextField fx:id="bankAccountTitleTextField" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
<Label text="Bank account holder name" GridPane.rowIndex="3"/>
<TextField fx:id="bankAccountHolderNameTextField" GridPane.columnIndex="1" GridPane.rowIndex="3"/>
<Label text="Bank account primary ID" GridPane.rowIndex="4"/>
<TextField fx:id="bankAccountPrimaryIDTextField" GridPane.columnIndex="1" GridPane.rowIndex="4"/>
<Label text="Bank account secondary ID" GridPane.rowIndex="5"/>
<TextField fx:id="bankAccountSecondaryIDTextField" GridPane.columnIndex="1" GridPane.rowIndex="5"/>
<Label text="Currency used for bank account:" GridPane.rowIndex="6"/>
<ComboBox fx:id="bankAccountCurrencyComboBox" promptText="Select currency" GridPane.columnIndex="1"
GridPane.rowIndex="6"/>
<Label text="Country of bank account" GridPane.rowIndex="7"/>
<HBox spacing="10" GridPane.columnIndex="1" GridPane.rowIndex="7">
<ComboBox fx:id="bankAccountRegionComboBox" onAction="#onSelectBankAccountRegion" prefWidth="150.0"
promptText="Select region"/>
<ComboBox fx:id="bankAccountCountryComboBox" visible="false" prefWidth="150.0"
promptText="Select country"/>
</HBox>
<HBox spacing="10" GridPane.columnIndex="1" GridPane.rowIndex="8">
<Button fx:id="saveBankAccountButton" defaultButton="true" onAction="#onSaveBankAccount"
text="Save bank account"/>
<Button fx:id="addBankAccountButton" onAction="#onAddBankAccount" text="Add new bank account"/>
<Button onAction="#onRemoveBankAccount" text="Remove bank account"/>
</HBox>
</GridPane>
<Tab text="TODO" closable="false">
</Tab>

View file

@ -17,7 +17,6 @@
package io.bitsquare.gui.trade;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.CachedViewController;
import io.bitsquare.gui.NavigationItem;
import io.bitsquare.gui.components.InputTextField;
@ -25,6 +24,7 @@ import io.bitsquare.gui.trade.createoffer.CreateOfferCB;
import io.bitsquare.gui.trade.orderbook.OrderBookController;
import io.bitsquare.gui.trade.takeoffer.TakeOfferController;
import io.bitsquare.trade.Direction;
import io.bitsquare.util.BSFXMLLoader;
import java.io.IOException;
@ -49,7 +49,7 @@ public class TradeController extends CachedViewController {
protected OrderBookController orderBookController;
protected CreateOfferCB createOfferCodeBehind;
protected TakeOfferController takeOfferController;
protected GuiceFXMLLoader orderBookLoader;
protected BSFXMLLoader orderBookLoader;
private Node createOfferView;
@ -111,7 +111,7 @@ public class TradeController extends CachedViewController {
checkArgument(orderBookLoader == null);
// Orderbook must not be cached by GuiceFXMLLoader as we use 2 instances for sell and buy screens.
orderBookLoader =
new GuiceFXMLLoader(getClass().getResource(NavigationItem.ORDER_BOOK.getFxmlUrl()), false);
new BSFXMLLoader(getClass().getResource(NavigationItem.ORDER_BOOK.getFxmlUrl()), false);
try {
final Parent view = orderBookLoader.load();
final Tab tab = new Tab("Orderbook");
@ -130,7 +130,7 @@ public class TradeController extends CachedViewController {
// CreateOffer and TakeOffer must not be cached by GuiceFXMLLoader as we cannot use a view multiple times
// in different graphs
GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), false);
BSFXMLLoader loader = new BSFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), false);
try {
createOfferView = loader.load();
createOfferCodeBehind = loader.getController();
@ -150,7 +150,7 @@ public class TradeController extends CachedViewController {
// CreateOffer and TakeOffer must not be cached by GuiceFXMLLoader as we cannot use a view multiple times
// in different graphs
GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), false);
BSFXMLLoader loader = new BSFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), false);
try {
final Parent view = loader.load();
takeOfferController = loader.getController();

View file

@ -301,7 +301,7 @@ public class CreateOfferCB extends CachedCodeBehind<CreateOfferPM> {
// Dialogs are a bit limited. There is no callback for the InformationDialog button click, so we added
// our own actions.
List<Action> actions = new ArrayList<>();
actions.add(new AbstractAction(BSResources.get("createOffer.success.copyTxId")) {
actions.add(new AbstractAction(BSResources.get("shared.copyTxId")) {
@Override
public void handle(ActionEvent actionEvent) {
Clipboard clipboard = Clipboard.getSystemClipboard();

View file

@ -84,7 +84,7 @@ class CreateOfferModel extends UIModel {
final StringProperty bankAccountType = new SimpleStringProperty();
final StringProperty fiatCode = new SimpleStringProperty();
final StringProperty btcCode = new SimpleStringProperty();
final LongProperty collateralAsLong = new SimpleLongProperty();
final BooleanProperty requestPlaceOfferSuccess = new SimpleBooleanProperty();
@ -287,7 +287,7 @@ class CreateOfferModel extends UIModel {
this.direction = direction;
}
public WalletFacade getWalletFacade() {
WalletFacade getWalletFacade() {
return walletFacade;
}

View file

@ -178,7 +178,6 @@ class CreateOfferPM extends PresentationModel<CreateOfferModel> {
model.requestPlaceOfferSuccess.set(false);
isPlaceOfferButtonDisabled.set(true);
// isPlaceOfferButtonVisible.set(true);
model.placeOffer();
}

View file

@ -240,7 +240,7 @@ public class OrderBookController extends CachedViewController {
nextController = ((ViewController) parentController).loadViewAndGetChildController(NavigationItem
.CREATE_OFFER);
else if (parentController instanceof CodeBehind)
nextController = ((CodeBehind) parentController).loadViewAndGetChildController(NavigationItem
nextController = ((CodeBehind) parentController).loadView(NavigationItem
.CREATE_OFFER);
}
@ -279,6 +279,9 @@ public class OrderBookController extends CachedViewController {
MainController.GET_INSTANCE().removeContentScreenBlur();
MainController.GET_INSTANCE().loadViewAndGetChildController(NavigationItem.ACCOUNT);
MainController.GET_INSTANCE()
.setPreviousNavigationItem((orderBookFilter.getDirection() == Direction.BUY) ?
NavigationItem.BUY : NavigationItem.SELL);
}
});
Popups.openInfo("You need to setup your trading account before you can trade.",
@ -324,7 +327,7 @@ public class OrderBookController extends CachedViewController {
.TAKE_OFFER);
else if (parentController instanceof CodeBehind)
takeOfferController = (TakeOfferController) ((CodeBehind) parentController)
.loadViewAndGetChildController(NavigationItem
.loadView(NavigationItem
.TAKE_OFFER);
}

View file

@ -49,7 +49,7 @@ public class BSResources {
return BSResources.getResourceBundle().getString(key);
} catch (MissingResourceException e) {
log.error("MissingResourceException for key: " + key);
return key + " is missing";
return "# " + key;
}
}

View file

@ -15,7 +15,7 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.di;
package io.bitsquare.util;
import io.bitsquare.locale.BSResources;
@ -36,8 +36,8 @@ import org.slf4j.LoggerFactory;
* Guice support for fxml controllers
* Support caching to speed up switches between UI screens.
*/
public class GuiceFXMLLoader {
private static final Logger log = LoggerFactory.getLogger(GuiceFXMLLoader.class);
public class BSFXMLLoader {
private static final Logger log = LoggerFactory.getLogger(BSFXMLLoader.class);
private static Injector injector = null;
private FXMLLoader loader;
private final boolean isCached;
@ -45,25 +45,25 @@ public class GuiceFXMLLoader {
private Item item;
public static void setInjector(Injector injector) {
GuiceFXMLLoader.injector = injector;
BSFXMLLoader.injector = injector;
}
// TODO maybe add more sophisticated caching strategy with removal of rarely accessed items
private static final Map<URL, Item> cachedGUIItems = new HashMap<>();
public GuiceFXMLLoader(URL url) {
public BSFXMLLoader(URL url) {
this(url, true);
}
public GuiceFXMLLoader(URL url, boolean useCaching) {
public BSFXMLLoader(URL url, boolean useCaching) {
this.url = url;
isCached = useCaching && cachedGUIItems.containsKey(url);
if (!isCached) {
loader = new FXMLLoader(url, BSResources.getResourceBundle());
if (GuiceFXMLLoader.injector != null)
loader.setControllerFactory(new GuiceControllerFactory(GuiceFXMLLoader.injector));
if (BSFXMLLoader.injector != null)
loader.setControllerFactory(new GuiceControllerFactory(BSFXMLLoader.injector));
}
}

View file

@ -9,7 +9,7 @@ shared.ok=OK
shared.openSettings=Open settings for editing
shared.buy=Buy Bitcoin
shared.sell=Sell Bitcoin
shared.copyTxId=Copy transaction ID
# validation
validation.empty=Empty input is not allowed.
@ -67,13 +67,11 @@ createOffer.advancedBox.county=Payments account country:
createOffer.advancedBox.info=Your trading partners must fulfill your offer restrictions. You can edit the accepted countries, languages and arbitrators in the settings. The payments account details are used from your current selected payments account (if you have multiple payments accounts).
createOffer.success.headline=Your offer has been successfully published to the distributed orderbook.
createOffer.success.info=The Bitcoin network transaction ID for the offer payment is: {0}
createOffer.success.copyTxId=Copy transaction ID
createOffer.success.info=The Transaction ID for the offer payment is: {0}
createOffer.error.message=An error occurred when placing the offer.\n{0}
# TODO Update the following string when doing the UI (old stuff...)
# generic
OTHER=Other

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.account;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* For testing single isolated UI screens
*/
public class AccountSettingsUITestRunner extends Application {
private static final Logger log = LoggerFactory.getLogger(AccountSettingsUITestRunner.class);
private Scene scene;
private Pane view;
private Pane pane;
private boolean devTest = true;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 630);
scene.getAccelerators().put(KeyCombination.valueOf("Shortcut+S"), this::loadMainWindow);
loadMainWindow();
primaryStage.setScene(scene);
primaryStage.show();
}
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/account/settings/AccountSettingsView.fxml"), false);
try {
view = loader.load();
pane.getChildren().setAll(view);
refreshStylesheets();
} catch (IOException e) {
e.printStackTrace();
log.error(e.getStackTrace().toString());
}
}
private void refreshStylesheets() {
scene.getStylesheets().clear();
scene.getStylesheets().setAll(getUrl("/io/bitsquare/gui/bitsquare.css").toExternalForm());
}
private URL getUrl(String subPath) {
if (devTest) {
try {
// load from file system location to make a reload possible. makes dev process easier with hot reload
return new URL("file:///Users/mk/Documents/_intellij/bitsquare/src/main/java" + subPath);
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}
else {
return getClass().getResource(subPath);
}
}
}

View file

@ -18,7 +18,7 @@
package io.bitsquare.gui.account;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -54,7 +54,7 @@ public class AccountUITestRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 630);
@ -67,7 +67,7 @@ public class AccountUITestRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/account/AccountView.fxml"), false);
try {
view = loader.load();

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.account;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* For testing single isolated UI screens
*/
public class RegistrationUITestRunner extends Application {
private static final Logger log = LoggerFactory.getLogger(RegistrationUITestRunner.class);
private Scene scene;
private Node view;
private StackPane pane;
private boolean devTest = true;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 630);
scene.getAccelerators().put(KeyCombination.valueOf("Shortcut+S"), this::loadMainWindow);
loadMainWindow();
primaryStage.setScene(scene);
primaryStage.show();
}
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/account/registration/RegistrationView.fxml"), false);
try {
view = loader.load();
pane.getChildren().setAll(view);
refreshStylesheets();
} catch (IOException e) {
e.printStackTrace();
log.error(e.getStackTrace().toString());
}
}
private void refreshStylesheets() {
scene.getStylesheets().clear();
scene.getStylesheets().setAll(getUrl("/io/bitsquare/gui/bitsquare.css").toExternalForm());
}
private URL getUrl(String subPath) {
if (devTest) {
try {
// load from file system location to make a reload possible. makes dev process easier with hot reload
return new URL("file:///Users/mk/Documents/_intellij/bitsquare/src/main/java" + subPath);
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}
else {
return getClass().getResource(subPath);
}
}
}

View file

@ -18,7 +18,7 @@
package io.bitsquare.gui.account;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -54,7 +54,7 @@ public class SetupUITestRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 630);
@ -67,7 +67,7 @@ public class SetupUITestRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/account/setup/SetupView.fxml"), false);
try {
view = loader.load();

View file

@ -1,7 +1,7 @@
package io.bitsquare.gui.account.registration.uimock;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -37,10 +37,10 @@ public class FundRegistrationWalletUIMockRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 1200);
scene = new Scene(pane, 1000, 650);
scene.getAccelerators().put(KeyCombination.valueOf("Shortcut+S"), this::loadMainWindow);
loadMainWindow();
primaryStage.setScene(scene);
@ -50,8 +50,8 @@ public class FundRegistrationWalletUIMockRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
getUrl("/io/bitsquare/gui/registration/uimock/FundRegistrationWalletViewUIMock.fxml"), false);
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/account/registration/uimock/FundRegistrationWalletViewUIMock.fxml"), false);
try {
view = loader.load();

View file

@ -1,7 +1,7 @@
package io.bitsquare.gui.account.registration.uimock;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -37,7 +37,7 @@ public class RegistrationUIMockRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 660);
@ -50,7 +50,7 @@ public class RegistrationUIMockRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/account/registration/uimock/RegistrationViewUIMock.fxml"), false);
try {

View file

@ -18,7 +18,7 @@
package io.bitsquare.gui.settings;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -54,7 +54,7 @@ public class FiatAccountUITestRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 630);
@ -67,7 +67,7 @@ public class FiatAccountUITestRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/account/fiataccount/FiatAccountView.fxml"), false);
try {
view = loader.load();

View file

@ -18,7 +18,7 @@
package io.bitsquare.gui.settings;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -54,7 +54,7 @@ public class PasswordUITestRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 630);
@ -67,8 +67,8 @@ public class PasswordUITestRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
getUrl("/io/bitsquare/gui/account/password/PasswordView.fxml"), false);
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/account/addpassword/PasswordView.fxml"), false);
try {
view = loader.load();
pane.getChildren().setAll(view);

View file

@ -18,7 +18,7 @@
package io.bitsquare.gui.settings;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -54,7 +54,7 @@ public class RegistrationUITestRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 530);
@ -67,7 +67,7 @@ public class RegistrationUITestRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/account/registration/RegistrationView.fxml"), false);
try {
view = loader.load();

View file

@ -18,7 +18,7 @@
package io.bitsquare.gui.settings;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -54,7 +54,7 @@ public class RestrictionsUITestRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 530);
@ -67,7 +67,7 @@ public class RestrictionsUITestRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/account/restrictions/RestrictionsView.fxml"), false);
try {
view = loader.load();

View file

@ -18,7 +18,7 @@
package io.bitsquare.gui.settings;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -54,7 +54,7 @@ public class SeedWordsUITestRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 630);
@ -67,7 +67,7 @@ public class SeedWordsUITestRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/account/seedwords/SeedWordsView.fxml"), false);
try {
view = loader.load();

View file

@ -18,7 +18,7 @@
package io.bitsquare.gui.settings.uimock;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -54,7 +54,7 @@ public class BankAccountSettingsUIMockRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 1200);
@ -67,7 +67,7 @@ public class BankAccountSettingsUIMockRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/settings/uimock/BankAccountSettingsViewUIMock.fxml"), false);
try {

View file

@ -18,7 +18,7 @@
package io.bitsquare.gui.settings.uimock;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -54,7 +54,7 @@ public class RestrictionSettingsUIMockRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 1200);
@ -67,7 +67,7 @@ public class RestrictionSettingsUIMockRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/settings/uimock/RestrictionSettingsViewUIMock.fxml"), false);
try {

View file

@ -1,7 +1,7 @@
package io.bitsquare.gui.settings.uimock;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -37,7 +37,7 @@ public class SeedWordsUIMockRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 1200);
@ -50,7 +50,7 @@ public class SeedWordsUIMockRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/settings/uimock/SeedWordsViewUIMock.fxml"), false);
try {

View file

@ -1,7 +1,7 @@
package io.bitsquare.gui.settings.uimock;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -37,7 +37,7 @@ public class SetPasswordUIMockRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 1200);
@ -50,7 +50,7 @@ public class SetPasswordUIMockRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/settings/uimock/SetPasswordViewUIMock.fxml"), false);
try {

View file

@ -18,7 +18,7 @@
package io.bitsquare.gui.trade.createoffer;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -54,7 +54,7 @@ public class CreateOfferUITestRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 630);
@ -67,7 +67,7 @@ public class CreateOfferUITestRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/trade/createoffer/CreateOfferView.fxml"), false);
try {
view = loader.load();

View file

@ -18,7 +18,7 @@
package io.bitsquare.gui.trade.createoffer.uimock;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.util.BSFXMLLoader;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -54,7 +54,7 @@ public class CreateOfferUIMockRunner extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new BitSquareModule());
GuiceFXMLLoader.setInjector(injector);
BSFXMLLoader.setInjector(injector);
pane = new StackPane();
scene = new Scene(pane, 1000, 630);
@ -67,7 +67,7 @@ public class CreateOfferUIMockRunner extends Application {
public void loadMainWindow() {
log.debug("re load");
pane.getChildren().removeAll();
GuiceFXMLLoader loader = new GuiceFXMLLoader(
BSFXMLLoader loader = new BSFXMLLoader(
getUrl("/io/bitsquare/gui/trade/createoffer/uimock/CreateOfferViewUIMock.fxml"), false);
try {