diff --git a/README.md b/README.md index 7db28c8c33..b2ba8d868a 100644 --- a/README.md +++ b/README.md @@ -12,15 +12,15 @@ We use bitcoinj library as a submodule. To get the project with the submodule in git clone --recursive git://github.com/bitsquare/bitsquare ### Implemented (prototype level): -* Screen for orderbook with filtering mock offers by amount, price and order type (buy, sell), other filters not impl. yet -* Screen for creating an offer (needs update) -* Screen for offer taking and payment process -* Simple storage for some filter attributes -* bitcoinj/wallet integration (basic) - +* Screen for orderbook with filtering mock offers by amount, price and order type (buy, sell) +* Screen for creating an offer +* Screen for offer taking and payment process (needs update) +* Simple persistence +* bitcoinj integration +* Setup with account registration and tx with OP_RETURN + embedded and blinded bank account data +* Offer fee payment with a OP_RETURN tx and fees to miners ### Next steps: -* Setup with account registration * Other trade variants (Buy BTC taker, Sell BTC offerer, Sell BTC offerer) * Arbitrator integration * Messaging system @@ -28,7 +28,14 @@ git clone --recursive git://github.com/bitsquare/bitsquare ### Screenshots of basic screens: +* [Registration screen 1](https://github.com/bitsquare/bitsquare/tree/master/screenshots/reg1.png) +* [Registration screen 2](https://github.com/bitsquare/bitsquare/tree/master/screenshots/reg2.png) +* [Registration screen 3](https://github.com/bitsquare/bitsquare/tree/master/screenshots/reg3.png) +* [Orderbook screen 1](https://github.com/bitsquare/bitsquare/tree/master/screenshots/orderbook1.png) +* [Orderbook screen 2](https://github.com/bitsquare/bitsquare/tree/master/screenshots/orderbook2.png) * [Orderbook screen](https://github.com/bitsquare/bitsquare/tree/master/screenshots/orderbook.png) +* [Create Offer screen 1](https://github.com/bitsquare/bitsquare/tree/master/screenshots/newOffer1.png) +* [Create Offer screen 2](https://github.com/bitsquare/bitsquare/tree/master/screenshots/newOffer2.png) * [Trade screen](https://github.com/bitsquare/bitsquare/tree/master/screenshots/trade.png) * [Bank transfer screen](https://github.com/bitsquare/bitsquare/tree/master/screenshots/bank_transfer.png) * [Trade completed screen](https://github.com/bitsquare/bitsquare/tree/master/screenshots/completed.png) diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000000..49d34f2dfc --- /dev/null +++ b/TODO.txt @@ -0,0 +1,13 @@ +- payment process update with new models +- btc payments in payment process +- arbitration integration + +Messaging! + +low prio: +- add settings after setup +- settings screen +- return to setup when unregistered, change/add bank accounts from settings + + + diff --git a/screenshots/newOffer1.png b/screenshots/newOffer1.png new file mode 100644 index 0000000000..60af81a858 Binary files /dev/null and b/screenshots/newOffer1.png differ diff --git a/screenshots/newOffer2.png b/screenshots/newOffer2.png new file mode 100644 index 0000000000..b1c1927dc3 Binary files /dev/null and b/screenshots/newOffer2.png differ diff --git a/screenshots/orderbook.png b/screenshots/orderbook.png deleted file mode 100644 index 7ac1f6d6f3..0000000000 Binary files a/screenshots/orderbook.png and /dev/null differ diff --git a/screenshots/orderbook1.png b/screenshots/orderbook1.png new file mode 100644 index 0000000000..9f96d54b96 Binary files /dev/null and b/screenshots/orderbook1.png differ diff --git a/screenshots/orderbook2.png b/screenshots/orderbook2.png new file mode 100644 index 0000000000..c54100fa6b Binary files /dev/null and b/screenshots/orderbook2.png differ diff --git a/screenshots/reg1.png b/screenshots/reg1.png new file mode 100644 index 0000000000..72220fad8a Binary files /dev/null and b/screenshots/reg1.png differ diff --git a/screenshots/reg2.png b/screenshots/reg2.png new file mode 100644 index 0000000000..5eec6f7adf Binary files /dev/null and b/screenshots/reg2.png differ diff --git a/screenshots/reg3.png b/screenshots/reg3.png new file mode 100644 index 0000000000..0ce4d3c912 Binary files /dev/null and b/screenshots/reg3.png differ diff --git a/screenshots/reg4.png b/screenshots/reg4.png new file mode 100644 index 0000000000..3663be0b57 Binary files /dev/null and b/screenshots/reg4.png differ diff --git a/src/main/java/io/bitsquare/BitSquare.java b/src/main/java/io/bitsquare/BitSquare.java index 839045e234..ee014497e8 100644 --- a/src/main/java/io/bitsquare/BitSquare.java +++ b/src/main/java/io/bitsquare/BitSquare.java @@ -6,7 +6,7 @@ import io.bitsquare.btc.WalletFacade; import io.bitsquare.di.BitSquareModule; import io.bitsquare.di.GuiceFXMLLoader; import io.bitsquare.gui.util.Localisation; -import io.bitsquare.settings.Startup; +import io.bitsquare.settings.Settings; import io.bitsquare.storage.Storage; import io.bitsquare.user.User; import javafx.application.Application; @@ -16,6 +16,8 @@ import javafx.stage.Stage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Locale; + public class BitSquare extends Application { private static final Logger log = LoggerFactory.getLogger(BitSquare.class); @@ -34,24 +36,30 @@ public class BitSquare extends Application // apply stored data final User user = injector.getInstance(User.class); + final Settings settings = injector.getInstance(Settings.class); final Storage storage = injector.getInstance(Storage.class); user.updateFromStorage((User) storage.read(user.getClass().getName())); - //TODO remove - final Startup setup = injector.getInstance(Startup.class); - setup.applyPersistedData(); + settings.updateFromStorage((Settings) storage.read(settings.getClass().getName())); + initSettings(settings, storage); stage.setTitle("BitSquare"); GuiceFXMLLoader.setInjector(injector); final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource("/io/bitsquare/gui/MainView.fxml"), Localisation.getResourceBundle()); final Parent mainView = loader.load(); + final Scene scene = new Scene(mainView, 800, 600); stage.setScene(scene); final String global = getClass().getResource("/io/bitsquare/gui/global.css").toExternalForm(); scene.getStylesheets().setAll(global); + stage.setMinWidth(740); + stage.setMinHeight(400); + stage.setWidth(800); + stage.setHeight(600); + stage.show(); } @@ -62,4 +70,31 @@ public class BitSquare extends Application super.stop(); } + + private void initSettings(Settings settings, Storage storage) + { + Settings savedSettings = (Settings) storage.read(settings.getClass().getName()); + if (savedSettings == null) + { + settings.getAcceptedCountryLocales().clear(); + settings.getAcceptedLanguageLocales().clear(); + + settings.addAcceptedLanguageLocale(Locale.getDefault()); + settings.addAcceptedCountryLocale(Locale.getDefault()); + + //TODO mock + settings.addAcceptedLanguageLocale(new Locale("en", "US")); + settings.addAcceptedLanguageLocale(new Locale("es", "ES")); + + settings.addAcceptedCountryLocale(new Locale("de", "AT")); + settings.addAcceptedCountryLocale(new Locale("en", "US")); + settings.addAcceptedCountryLocale(new Locale("es", "ES")); + + storage.write(settings.getClass().getName(), settings); + } + else + { + settings.updateFromStorage(savedSettings); + } + } } diff --git a/src/main/java/io/bitsquare/bank/BankAccount.java b/src/main/java/io/bitsquare/bank/BankAccount.java index c7e3f81335..3b8545b2e5 100644 --- a/src/main/java/io/bitsquare/bank/BankAccount.java +++ b/src/main/java/io/bitsquare/bank/BankAccount.java @@ -18,23 +18,26 @@ public class BankAccount implements Serializable private Currency currency; private String uid; - // TODO just for mock yet - public BankAccount(BankAccountType bankAccountType) - { - this.bankAccountType = bankAccountType; - - } - - public BankAccount(BankAccountType bankAccountType, String accountPrimaryID, String accountSecondaryID, String accountHolderName, Locale countryLocale, Currency currency) + + private String accountTitle; + + public BankAccount(BankAccountType bankAccountType, + Currency currency, + Locale countryLocale, + String accountTitle, + String accountHolderName, + String accountPrimaryID, + String accountSecondaryID) { this.bankAccountType = bankAccountType; + this.currency = currency; + this.countryLocale = countryLocale; + this.accountTitle = accountTitle; + this.accountHolderName = accountHolderName; this.accountPrimaryID = accountPrimaryID; this.accountSecondaryID = accountSecondaryID; - this.accountHolderName = accountHolderName; - this.countryLocale = countryLocale; - this.currency = currency; - uid = bankAccountType + "_" + accountPrimaryID + "_" + accountSecondaryID + "_" + accountHolderName + "_" + countryLocale.getISO3Country(); + uid = bankAccountType + "_" + accountPrimaryID + "_" + accountSecondaryID + "_" + accountHolderName + "_" + countryLocale.getCountry(); } public String getAccountPrimaryID() @@ -72,6 +75,11 @@ public class BankAccount implements Serializable return uid; } + public String getAccountTitle() + { + return accountTitle; + } + // Changes of that structure must be reflected in VERSION updates public String getStringifiedBankAccount() { @@ -81,15 +89,9 @@ public class BankAccount implements Serializable ", secondaryID='" + accountSecondaryID + '\'' + ", holderName='" + accountHolderName + '\'' + ", currency='" + currency.getCurrencyCode() + '\'' + - ", country='" + countryLocale.getISO3Country() + '\'' + + ", country='" + countryLocale.getCountry() + '\'' + ", v='" + VERSION + '\'' + '}'; } - public String getShortName() - { - return bankAccountType + " " + accountPrimaryID + " / " + accountSecondaryID + " / " + currency.getCurrencyCode(); - } - - } diff --git a/src/main/java/io/bitsquare/btc/AccountRegistrationWallet.java b/src/main/java/io/bitsquare/btc/AccountRegistrationWallet.java index 4c3a59ea1c..71385203fc 100644 --- a/src/main/java/io/bitsquare/btc/AccountRegistrationWallet.java +++ b/src/main/java/io/bitsquare/btc/AccountRegistrationWallet.java @@ -170,7 +170,7 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) { for (WalletFacade.WalletListener walletListener : walletListeners) - walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), WalletUtil.getConfirmationDepthInBlocks(this)); + walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), WalletUtil.getConfDepthInBlocks(this)); log.info("onTransactionConfidenceChanged " + tx.getConfidence().toString()); } @@ -205,7 +205,7 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList log.info("onScriptsAdded"); } - int getConfirmationNumBroadcastPeers() + int getConfNumBroadcastPeers() { Transaction transaction = WalletUtil.getTransaction(this); return (transaction == null || transaction.getConfidence() == null) ? 0 : transaction.getConfidence().numBroadcastPeers(); diff --git a/src/main/java/io/bitsquare/btc/Fees.java b/src/main/java/io/bitsquare/btc/Fees.java index b98dd242d2..0ea13ec92b 100644 --- a/src/main/java/io/bitsquare/btc/Fees.java +++ b/src/main/java/io/bitsquare/btc/Fees.java @@ -8,7 +8,6 @@ public class Fees { public static BigInteger ACCOUNT_REGISTRATION_FEE = Transaction.MIN_NONDUST_OUTPUT;// Utils.toNanoCoins("0.001"); - public static BigInteger OFFER_CREATION_FEE = new BigInteger("500000"); + public static BigInteger OFFER_CREATION_FEE = Transaction.MIN_NONDUST_OUTPUT; // Utils.toNanoCoins("0.001"); public static BigInteger OFFER_TAKER_FEE = OFFER_CREATION_FEE; - public static BigInteger BTC_NETWORK_FEE = new BigInteger("10000"); } diff --git a/src/main/java/io/bitsquare/btc/WalletFacade.java b/src/main/java/io/bitsquare/btc/WalletFacade.java index f2cd1eb1d2..cd5d6844d1 100644 --- a/src/main/java/io/bitsquare/btc/WalletFacade.java +++ b/src/main/java/io/bitsquare/btc/WalletFacade.java @@ -5,7 +5,10 @@ import com.google.bitcoin.kits.WalletAppKit; import com.google.bitcoin.params.MainNetParams; import com.google.bitcoin.params.RegTestParams; import com.google.bitcoin.script.Script; +import com.google.bitcoin.script.ScriptBuilder; import com.google.bitcoin.utils.Threading; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; import com.google.inject.Inject; import io.bitsquare.crypto.CryptoFacade; import javafx.application.Platform; @@ -18,6 +21,8 @@ import java.util.Date; import java.util.List; import java.util.UUID; +import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN; + /** * That facade delivers wallet functionality from the bitcoinJ library * Code from BitcoinJ must not be used outside that facade. @@ -79,12 +84,12 @@ public class WalletFacade implements WalletEventListener walletAppKit.startAsync(); walletAppKit.awaitRunning(); // Don't make the user wait for confirmations for now, as the intention is they're sending it their own money! - walletAppKit.wallet().allowSpendingUnconfirmedTransactions(); + getWallet().allowSpendingUnconfirmedTransactions(); walletAppKit.peerGroup().setMaxConnections(11); - walletAppKit.wallet().addEventListener(this); + getWallet().addEventListener(this); - log.info(walletAppKit.wallet().toString()); + log.info(getWallet().toString()); } public void shutDown() @@ -134,12 +139,12 @@ public class WalletFacade implements WalletEventListener public BigInteger getBalance() { - return walletAppKit.wallet().getBalance(Wallet.BalanceType.ESTIMATED); + return getWallet().getBalance(Wallet.BalanceType.ESTIMATED); } public String getAddress() { - return walletAppKit.wallet().getKeys().get(0).toAddress(networkParameters).toString(); + return getWallet().getKeys().get(0).toAddress(networkParameters).toString(); } // account registration @@ -171,14 +176,14 @@ public class WalletFacade implements WalletEventListener && blockChainFacade.verifyAddressInBlockChain(hashAsHexStringToVerify, address); } - public int getRegistrationConfirmationNumBroadcastPeers() + public int getRegConfNumBroadcastPeers() { - return getAccountRegistrationWallet().getConfirmationNumBroadcastPeers(); + return getAccountRegistrationWallet().getConfNumBroadcastPeers(); } - public int getRegistrationConfirmationDepthInBlocks() + public int getRegConfDepthInBlocks() { - return WalletUtil.getConfirmationDepthInBlocks(getAccountRegistrationWallet()); + return WalletUtil.getConfDepthInBlocks(getAccountRegistrationWallet()); } // WalletEventListener @@ -195,7 +200,7 @@ public class WalletFacade implements WalletEventListener public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) { for (WalletListener walletListener : walletListeners) - walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), WalletUtil.getConfirmationDepthInBlocks(walletAppKit.wallet())); + walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), WalletUtil.getConfDepthInBlocks(getWallet())); log.info("onTransactionConfidenceChanged " + tx.getConfidence().toString()); } @@ -239,6 +244,51 @@ public class WalletFacade implements WalletEventListener return accountRegistrationWallet; } + public String payOfferFee() throws InsufficientMoneyException + { + getWallet(); + + Script script = new ScriptBuilder() + .op(OP_RETURN) + .build(); + Transaction transaction = new Transaction(networkParameters); + TransactionOutput dataOutput = new TransactionOutput(networkParameters, + transaction, + Transaction.MIN_NONDUST_OUTPUT, + script.getProgram()); + transaction.addOutput(dataOutput); + Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(transaction); + + // give fee to miners yet. Later it could be spent to other traders via lottery... + sendRequest.fee = Fees.OFFER_CREATION_FEE; + + Wallet.SendResult sendResult = getWallet().sendCoins(sendRequest); + + Futures.addCallback(sendResult.broadcastComplete, new FutureCallback() + { + @Override + public void onSuccess(Transaction result) + { + log.info("sendResult onSuccess:" + result.toString()); + // Platform.runLater(overlayUi::done); + } + + @Override + public void onFailure(Throwable t) + { + log.warn("sendResult onFailure:" + t.toString()); + // We died trying to empty the wallet. + // crashAlert(t); + } + }); + + return transaction.getHashAsString(); + } + + private Wallet getWallet() + { + return walletAppKit.wallet(); + } // inner classes private class BlockChainDownloadListener extends com.google.bitcoin.core.DownloadListener diff --git a/src/main/java/io/bitsquare/btc/WalletUtil.java b/src/main/java/io/bitsquare/btc/WalletUtil.java index b54d55db1d..31e86402b8 100644 --- a/src/main/java/io/bitsquare/btc/WalletUtil.java +++ b/src/main/java/io/bitsquare/btc/WalletUtil.java @@ -11,7 +11,7 @@ public class WalletUtil { // TODO check if that is correct and safe - public static int getConfirmationDepthInBlocks(Wallet wallet) + public static int getConfDepthInBlocks(Wallet wallet) { Transaction transaction = WalletUtil.getTransaction(wallet); if (transaction != null && transaction.getConfidence() != null) diff --git a/src/main/java/io/bitsquare/di/BitSquareModule.java b/src/main/java/io/bitsquare/di/BitSquareModule.java index d11b16ac62..94a9048f39 100644 --- a/src/main/java/io/bitsquare/di/BitSquareModule.java +++ b/src/main/java/io/bitsquare/di/BitSquareModule.java @@ -16,9 +16,9 @@ import io.bitsquare.crypto.CryptoFacade; import io.bitsquare.msg.MessageFacade; import io.bitsquare.settings.OrderBookFilterSettings; import io.bitsquare.settings.Settings; -import io.bitsquare.settings.Startup; import io.bitsquare.storage.Storage; import io.bitsquare.trade.Trading; +import io.bitsquare.trade.orderbook.MockOrderBook; import io.bitsquare.trade.orderbook.OrderBook; import io.bitsquare.trade.orderbook.OrderBookFilter; import io.bitsquare.user.User; @@ -31,9 +31,8 @@ public class BitSquareModule extends AbstractModule @Override protected void configure() { - bind(Startup.class).asEagerSingleton(); bind(User.class).asEagerSingleton(); - bind(OrderBook.class).asEagerSingleton(); + bind(OrderBook.class).to(MockOrderBook.class).asEagerSingleton(); bind(Storage.class).asEagerSingleton(); bind(Settings.class).asEagerSingleton(); bind(OrderBookFilter.class).asEagerSingleton(); diff --git a/src/main/java/io/bitsquare/gui/ChildController.java b/src/main/java/io/bitsquare/gui/ChildController.java index 2d44b2fd25..b7ba6eadd8 100644 --- a/src/main/java/io/bitsquare/gui/ChildController.java +++ b/src/main/java/io/bitsquare/gui/ChildController.java @@ -3,4 +3,5 @@ package io.bitsquare.gui; public interface ChildController { void setNavigationController(NavigationController navigationController); + } diff --git a/src/main/java/io/bitsquare/gui/MainController.java b/src/main/java/io/bitsquare/gui/MainController.java index 76dcda7624..17ea9e1fa7 100644 --- a/src/main/java/io/bitsquare/gui/MainController.java +++ b/src/main/java/io/bitsquare/gui/MainController.java @@ -10,9 +10,7 @@ import io.bitsquare.gui.trade.TradeController; import io.bitsquare.gui.util.Formatter; import io.bitsquare.gui.util.Icons; import io.bitsquare.gui.util.Localisation; -import io.bitsquare.settings.Settings; import io.bitsquare.trade.Direction; -import io.bitsquare.trade.orderbook.OrderBookFilter; import io.bitsquare.user.User; import javafx.application.Platform; import javafx.beans.value.ChangeListener; @@ -39,9 +37,7 @@ public class MainController implements Initializable, NavigationController, Wall { private static final Logger log = LoggerFactory.getLogger(MainController.class); - private Settings settings; private User user; - private OrderBookFilter orderBookFilter; private WalletFacade walletFacade; private ChildController childController; private ToggleGroup toggleGroup; @@ -61,11 +57,9 @@ public class MainController implements Initializable, NavigationController, Wall public AnchorPane anchorPane; @Inject - public MainController(Settings settings, User user, OrderBookFilter orderBookFilter, WalletFacade walletFacade) + public MainController(User user, WalletFacade walletFacade) { - this.settings = settings; this.user = user; - this.orderBookFilter = orderBookFilter; this.walletFacade = walletFacade; } @@ -78,6 +72,7 @@ public class MainController implements Initializable, NavigationController, Wall walletFacade.addDownloadListener(this); walletFacade.initWallet(); + buildNavigation(); if (user.getAccountID() == null) { @@ -107,6 +102,11 @@ public class MainController implements Initializable, NavigationController, Wall return null; } + if (childController instanceof TradeController) + { + ((TradeController) childController).cleanup(); + } + final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(fxmlView), Localisation.getResourceBundle()); try { @@ -172,7 +172,7 @@ public class MainController implements Initializable, NavigationController, Wall addNavButton(leftNavPane, "Funds", Icons.FUNDS, Icons.FUNDS, NavigationController.FUNDS); addNavButton(leftNavPane, "Message", Icons.MSG, Icons.MSG, NavigationController.MSG); addBalanceInfo(rightNavPane); - addAccountComboBox(); + addAccountComboBox(rightNavPane); addNavButton(rightNavPane, "Settings", Icons.SETTINGS, Icons.SETTINGS, NavigationController.SETTINGS); @@ -226,15 +226,12 @@ public class MainController implements Initializable, NavigationController, Wall private TextField addBalanceInfo(Pane parent) { - Pane holder = new Pane(); TextField balanceLabel = new TextField(); balanceLabel.setEditable(false); balanceLabel.setMouseTransparent(true); balanceLabel.setPrefWidth(90); balanceLabel.setId("nav-balance-label"); balanceLabel.setText(Formatter.formatSatoshis(walletFacade.getBalance(), false)); - holder.getChildren().add(balanceLabel); - rightNavPane.getChildren().add(holder); Label balanceCurrencyLabel = new Label("BTC"); balanceCurrencyLabel.setPadding(new Insets(6, 0, 0, 0)); @@ -256,7 +253,7 @@ public class MainController implements Initializable, NavigationController, Wall return balanceLabel; } - private void addAccountComboBox() + private void addAccountComboBox(Pane parent) { if (user.getBankAccounts().size() > 1) { @@ -268,7 +265,7 @@ public class MainController implements Initializable, NavigationController, Wall @Override public String toString(BankAccount bankAccount) { - return bankAccount.getShortName(); + return bankAccount.getAccountTitle(); } @Override @@ -278,6 +275,16 @@ public class MainController implements Initializable, NavigationController, Wall } }); + VBox vBox = new VBox(); + vBox.setPadding(new Insets(12, 0, 0, 0)); + vBox.setSpacing(2); + Label titleLabel = new Label("Bank account"); + titleLabel.setMouseTransparent(true); + titleLabel.setPrefWidth(90); + titleLabel.setId("nav-button-label"); + + vBox.getChildren().setAll(accountComboBox, titleLabel); + parent.getChildren().add(vBox); accountComboBox.valueProperty().addListener(new ChangeListener() { @@ -285,16 +292,10 @@ public class MainController implements Initializable, NavigationController, Wall public void changed(ObservableValue ov, BankAccount oldValue, BankAccount newValue) { user.setCurrentBankAccount(newValue); - orderBookFilter.setCurrency(newValue.getCurrency()); - orderBookFilter.setCountryLocale(newValue.getCountryLocale()); } }); - Pane holder = new Pane(); - holder.getChildren().add(accountComboBox); - rightNavPane.getChildren().add(holder); } } - } \ No newline at end of file diff --git a/src/main/java/io/bitsquare/gui/MainView.fxml b/src/main/java/io/bitsquare/gui/MainView.fxml index caa4b0afd8..8208f968de 100644 --- a/src/main/java/io/bitsquare/gui/MainView.fxml +++ b/src/main/java/io/bitsquare/gui/MainView.fxml @@ -1,10 +1,9 @@ - - + 0) + return Icons.getIconImage(Icons.getIconIDForConfirmations(depthInBlocks)); + else + return Icons.getIconImage(Icons.getIconIDForPeersSeenTx(numBroadcastPeers)); + } + + +} diff --git a/src/main/java/io/bitsquare/gui/components/processbar/ProcessStepsBuilder.java b/src/main/java/io/bitsquare/gui/components/processbar/ProcessStepsBuilder.java index 30503730c3..26a0533310 100644 --- a/src/main/java/io/bitsquare/gui/components/processbar/ProcessStepsBuilder.java +++ b/src/main/java/io/bitsquare/gui/components/processbar/ProcessStepsBuilder.java @@ -1,6 +1,6 @@ package io.bitsquare.gui.components.processbar; -import io.bitsquare.gui.util.Utils; +import io.bitsquare.gui.util.GUIUtils; import javafx.animation.AnimationTimer; import javafx.scene.control.Button; import javafx.scene.control.Control; @@ -65,7 +65,7 @@ public class ProcessStepsBuilder // TODO // mock simulate network delay - Utils.setTimeout(100, (AnimationTimer animationTimer) -> { + GUIUtils.setTimeout(100, (AnimationTimer animationTimer) -> { next(); return null; }); diff --git a/src/main/java/io/bitsquare/gui/settings/SettingsController.java b/src/main/java/io/bitsquare/gui/settings/SettingsController.java index 75a4aa9515..0873cc351e 100644 --- a/src/main/java/io/bitsquare/gui/settings/SettingsController.java +++ b/src/main/java/io/bitsquare/gui/settings/SettingsController.java @@ -1,7 +1,11 @@ package io.bitsquare.gui.settings; +import com.google.inject.Inject; import io.bitsquare.gui.ChildController; import io.bitsquare.gui.NavigationController; +import io.bitsquare.settings.Settings; +import io.bitsquare.storage.Storage; +import io.bitsquare.user.User; import javafx.fxml.Initializable; import java.net.URL; @@ -9,15 +13,24 @@ import java.util.ResourceBundle; public class SettingsController implements Initializable, ChildController { - + private User user; + private Settings settings; + private Storage storage; private NavigationController navigationController; + @Inject + public SettingsController(User user, Settings settings, Storage storage) + { + this.user = user; + this.settings = settings; + this.storage = storage; + } + @Override public void initialize(URL url, ResourceBundle rb) { - } @Override diff --git a/src/main/java/io/bitsquare/gui/setup/SetupController.java b/src/main/java/io/bitsquare/gui/setup/SetupController.java index 6f88f7ae1d..d4fe9ac265 100644 --- a/src/main/java/io/bitsquare/gui/setup/SetupController.java +++ b/src/main/java/io/bitsquare/gui/setup/SetupController.java @@ -10,6 +10,7 @@ import io.bitsquare.btc.WalletFacade; import io.bitsquare.crypto.CryptoFacade; import io.bitsquare.gui.ChildController; import io.bitsquare.gui.NavigationController; +import io.bitsquare.gui.components.ConfirmationComponent; import io.bitsquare.gui.components.NetworkSyncPane; import io.bitsquare.gui.components.processbar.ProcessStepBar; import io.bitsquare.gui.components.processbar.ProcessStepItem; @@ -18,11 +19,10 @@ import io.bitsquare.gui.util.Formatter; import io.bitsquare.settings.Settings; import io.bitsquare.storage.Storage; import io.bitsquare.user.User; +import io.bitsquare.util.Utils; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.*; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; import javafx.scene.input.Clipboard; import javafx.scene.input.ClipboardContent; import javafx.scene.layout.AnchorPane; @@ -48,8 +48,7 @@ public class SetupController implements Initializable, ChildController, WalletFa private List processStepItems = new ArrayList(); private NavigationController navigationController; - private ImageView confirmIconImageView; - private TextField balanceLabel, confirmationsLabel, accountHolderName, accountPrimaryID, accountSecondaryID; + private TextField balanceLabel, accountTitle, accountHolderName, accountPrimaryID, accountSecondaryID; private ComboBox countryComboBox, bankTransferTypeComboBox, currencyComboBox; private Button addBankAccountButton; @@ -103,8 +102,7 @@ public class SetupController implements Initializable, ChildController, WalletFa public void onConfidenceChanged(int numBroadcastPeers, int depthInBlocks) { updateCreateAccountButton(); - confirmIconImageView.setImage(getConfirmIconImage(numBroadcastPeers, depthInBlocks)); - confirmationsLabel.setText(getConfirmationsText(numBroadcastPeers, depthInBlocks)); + log.info("onConfidenceChanged " + numBroadcastPeers + " / " + depthInBlocks); } @@ -133,24 +131,18 @@ public class SetupController implements Initializable, ChildController, WalletFa return bankTransferTypeComboBox.getSelectionModel().getSelectedItem() != null && countryComboBox.getSelectionModel().getSelectedItem() != null && currencyComboBox.getSelectionModel().getSelectedItem() != null + && accountTitle.getText().length() > 0 + && accountHolderName.getText().length() > 0 && accountPrimaryID.getText().length() > 0 && accountSecondaryID.getText().length() > 0 - && accountHolderName.getText().length() > 0 && accountIDsByBankTransferTypeValid; } - private Image getConfirmIconImage(int numBroadcastPeers, int depthInBlocks) - { - if (depthInBlocks > 0) - return Icons.getIconImage(Icons.getIconIDForConfirmations(depthInBlocks)); - else - return Icons.getIconImage(Icons.getIconIDForPeersSeenTx(numBroadcastPeers)); - } private void updateCreateAccountButton() { boolean funded = walletFacade.getAccountRegistrationBalance().compareTo(BigInteger.ZERO) > 0; - nextButton.setDisable(!funded || walletFacade.getRegistrationConfirmationDepthInBlocks() == 0); + nextButton.setDisable(!funded || walletFacade.getRegConfDepthInBlocks() == 0); } @@ -158,11 +150,6 @@ public class SetupController implements Initializable, ChildController, WalletFa // GUI BUILDER /////////////////////////////////////////////////////////////////////////////////// - private String getConfirmationsText(int registrationConfirmationNumBroadcastPeers, int registrationConfirmationDepthInBlocks) - { - return registrationConfirmationDepthInBlocks + " confirmation(s) / " + "Seen by " + registrationConfirmationNumBroadcastPeers + " peer(s)"; - } - private void buildStep0() { infoLabel.setText("You need to pay 0.01 BTC to the registration address.\n\n" + @@ -174,8 +161,7 @@ public class SetupController implements Initializable, ChildController, WalletFa int gridRow = -1; - TextField addressLabel = FormBuilder.addInputField(formGridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++gridRow); - addressLabel.setEditable(false); + TextField addressLabel = FormBuilder.addTextField(formGridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++gridRow, false, true); Label copyIcon = new Label(""); formGridPane.add(copyIcon, 2, gridRow); @@ -183,14 +169,9 @@ public class SetupController implements Initializable, ChildController, WalletFa AwesomeDude.setIcon(copyIcon, AwesomeIcon.COPY); Tooltip.install(copyIcon, new Tooltip("Copy address to clipboard")); - balanceLabel = FormBuilder.addInputField(formGridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++gridRow); - balanceLabel.setEditable(false); + balanceLabel = FormBuilder.addTextField(formGridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++gridRow); - confirmationsLabel = FormBuilder.addInputField(formGridPane, "Confirmations:", getConfirmationsText(walletFacade.getRegistrationConfirmationNumBroadcastPeers(), walletFacade.getRegistrationConfirmationDepthInBlocks()), ++gridRow); - confirmationsLabel.setEditable(false); - - confirmIconImageView = new ImageView(getConfirmIconImage(walletFacade.getRegistrationConfirmationNumBroadcastPeers(), walletFacade.getRegistrationConfirmationDepthInBlocks())); - formGridPane.add(confirmIconImageView, 2, gridRow); + ConfirmationComponent confirmationComponent = new ConfirmationComponent(walletFacade, formGridPane, ++gridRow); nextButton.setText("Payment done"); updateCreateAccountButton(); @@ -221,13 +202,29 @@ public class SetupController implements Initializable, ChildController, WalletFa formGridPane.getChildren().clear(); int gridRow = -1; - bankTransferTypeComboBox = FormBuilder.addComboBox(formGridPane, "Bank account type:", settings.getAllBankAccountTypes(), ++gridRow); + bankTransferTypeComboBox = FormBuilder.addComboBox(formGridPane, "Bank account type:", Utils.getAllBankAccountTypes(), ++gridRow); + bankTransferTypeComboBox.setConverter(new StringConverter() + { + @Override + public String toString(BankAccountType bankAccountType) + { + return Localisation.get(bankAccountType.toString()); + } + + @Override + public BankAccountType fromString(String s) + { + return null; + } + }); + bankTransferTypeComboBox.setPromptText("Select bank account type"); + accountTitle = FormBuilder.addInputField(formGridPane, "Bank account title:", "", ++gridRow); accountHolderName = FormBuilder.addInputField(formGridPane, "Bank account holder name:", "", ++gridRow); accountPrimaryID = FormBuilder.addInputField(formGridPane, "Bank account primary ID", "", ++gridRow); accountSecondaryID = FormBuilder.addInputField(formGridPane, "Bank account secondary ID:", "", ++gridRow); - currencyComboBox = FormBuilder.addComboBox(formGridPane, "Currency used for bank account:", settings.getAllCurrencies(), ++gridRow); + currencyComboBox = FormBuilder.addComboBox(formGridPane, "Currency used for bank account:", Utils.getAllCurrencies(), ++gridRow); currencyComboBox.setPromptText("Select currency"); currencyComboBox.setConverter(new StringConverter() { @@ -244,7 +241,7 @@ public class SetupController implements Initializable, ChildController, WalletFa } }); - countryComboBox = FormBuilder.addComboBox(formGridPane, "Country of bank account:", settings.getAllLocales(), ++gridRow); + countryComboBox = FormBuilder.addComboBox(formGridPane, "Country of bank account:", Utils.getAllLocales(), ++gridRow); countryComboBox.setPromptText("Select country"); countryComboBox.setConverter(new StringConverter() { @@ -270,6 +267,7 @@ public class SetupController implements Initializable, ChildController, WalletFa skipButton.setText("Register later"); // handlers + accountTitle.textProperty().addListener((ov, oldValue, newValue) -> checkCreateAccountButtonState()); accountHolderName.textProperty().addListener((ov, oldValue, newValue) -> checkCreateAccountButtonState()); accountPrimaryID.textProperty().addListener((ov, oldValue, newValue) -> checkCreateAccountButtonState()); accountSecondaryID.textProperty().addListener((ov, oldValue, newValue) -> checkCreateAccountButtonState()); @@ -292,6 +290,8 @@ public class SetupController implements Initializable, ChildController, WalletFa addBankAccountButton.setOnAction(e -> { addBankAccount(); + storage.write(user.getClass().getName(), user); + if (verifyBankAccountData()) { bankTransferTypeComboBox.getSelectionModel().clearSelection(); @@ -313,13 +313,15 @@ public class SetupController implements Initializable, ChildController, WalletFa user.setAccountID(walletFacade.getAccountRegistrationAddress().toString()); user.setMessageID(walletFacade.getAccountRegistrationPubKey().toString()); - storage.saveUser(user); - + storage.write(user.getClass().getName(), user); processStepBar.next(); buildStep2(); } catch (InsufficientMoneyException e1) { log.warn(e1.toString()); + // TODO + processStepBar.next(); + buildStep2(); } } else @@ -336,12 +338,14 @@ public class SetupController implements Initializable, ChildController, WalletFa { if (verifyBankAccountData()) { - BankAccount bankAccount = new BankAccount((BankAccountType) bankTransferTypeComboBox.getSelectionModel().getSelectedItem(), - accountPrimaryID.getText(), - accountSecondaryID.getText(), - accountHolderName.getText(), + BankAccount bankAccount = new BankAccount( + (BankAccountType) bankTransferTypeComboBox.getSelectionModel().getSelectedItem(), + (Currency) currencyComboBox.getSelectionModel().getSelectedItem(), (Locale) countryComboBox.getSelectionModel().getSelectedItem(), - (Currency) currencyComboBox.getSelectionModel().getSelectedItem()); + accountTitle.getText(), + accountHolderName.getText(), + accountPrimaryID.getText(), + accountSecondaryID.getText()); user.addBankAccount(bankAccount); } } @@ -360,20 +364,20 @@ public class SetupController implements Initializable, ChildController, WalletFa formGridPane.getChildren().clear(); int gridRow = -1; List bankAccounts = user.getBankAccounts(); - Iterator iterator = bankAccounts.iterator(); + Iterator iterator = bankAccounts.iterator(); int index = 0; while (iterator.hasNext()) { FormBuilder.addHeaderLabel(formGridPane, "Bank account " + (index + 1), ++gridRow); - Map.Entry entry = (Map.Entry) iterator.next(); + BankAccount bankAccount = iterator.next(); // need to get updated gridRow from subroutine - gridRow = buildBankAccountDetails(entry.getValue(), ++gridRow); + gridRow = buildBankAccountDetails(bankAccount, ++gridRow); FormBuilder.addVSpacer(formGridPane, ++gridRow); index++; } FormBuilder.addVSpacer(formGridPane, ++gridRow); - FormBuilder.addInputField(formGridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++gridRow).setMouseTransparent(true); - FormBuilder.addInputField(formGridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++gridRow).setMouseTransparent(true); + FormBuilder.addTextField(formGridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++gridRow); + FormBuilder.addTextField(formGridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++gridRow); nextButton.setText("Done"); skipButton.setOpacity(0); @@ -385,11 +389,13 @@ public class SetupController implements Initializable, ChildController, WalletFa // util private int buildBankAccountDetails(BankAccount bankAccount, int row) { - FormBuilder.addInputField(formGridPane, "Bank account holder name:", bankAccount.getAccountHolderName(), ++row).setMouseTransparent(true); - FormBuilder.addInputField(formGridPane, "Bank account type", bankAccount.getBankAccountType().toString(), ++row).setMouseTransparent(true); - FormBuilder.addInputField(formGridPane, "Bank account primary ID", bankAccount.getAccountPrimaryID(), ++row).setMouseTransparent(true); - FormBuilder.addInputField(formGridPane, "Bank account secondary ID:", bankAccount.getAccountSecondaryID(), ++row).setMouseTransparent(true); + FormBuilder.addTextField(formGridPane, "Bank account holder name:", bankAccount.getAccountHolderName(), ++row); + FormBuilder.addTextField(formGridPane, "Bank account type", bankAccount.getBankAccountType().toString(), ++row); + FormBuilder.addTextField(formGridPane, "Bank account primary ID", bankAccount.getAccountPrimaryID(), ++row); + FormBuilder.addTextField(formGridPane, "Bank account secondary ID:", bankAccount.getAccountSecondaryID(), ++row); return row; } + + } diff --git a/src/main/java/io/bitsquare/gui/setup/SetupView.fxml b/src/main/java/io/bitsquare/gui/setup/SetupView.fxml index 9c6607493c..8490499276 100644 --- a/src/main/java/io/bitsquare/gui/setup/SetupView.fxml +++ b/src/main/java/io/bitsquare/gui/setup/SetupView.fxml @@ -4,7 +4,7 @@ + xmlns:fx="http://javafx.com/fxml"> diff --git a/src/main/java/io/bitsquare/gui/trade/TradeController.java b/src/main/java/io/bitsquare/gui/trade/TradeController.java index 81c1228d05..8492e633e2 100644 --- a/src/main/java/io/bitsquare/gui/trade/TradeController.java +++ b/src/main/java/io/bitsquare/gui/trade/TradeController.java @@ -84,5 +84,14 @@ public class TradeController implements Initializable, NavigationController, Chi orderBookController.setDirection(direction); } + public void cleanup() + { + if (orderBookController != null) + { + orderBookController.cleanup(); + orderBookController = null; + } + } + } diff --git a/src/main/java/io/bitsquare/gui/trade/offer/CreateOfferController.java b/src/main/java/io/bitsquare/gui/trade/offer/CreateOfferController.java index c9646a3892..2c283dfbaf 100644 --- a/src/main/java/io/bitsquare/gui/trade/offer/CreateOfferController.java +++ b/src/main/java/io/bitsquare/gui/trade/offer/CreateOfferController.java @@ -1,77 +1,65 @@ package io.bitsquare.gui.trade.offer; +import com.google.bitcoin.core.InsufficientMoneyException; import com.google.inject.Inject; +import io.bitsquare.btc.Fees; +import io.bitsquare.btc.WalletFacade; import io.bitsquare.gui.ChildController; import io.bitsquare.gui.NavigationController; -import io.bitsquare.gui.util.Converter; -import io.bitsquare.gui.util.Formatter; -import io.bitsquare.settings.OrderBookFilterSettings; +import io.bitsquare.gui.components.ConfirmationComponent; +import io.bitsquare.gui.util.*; import io.bitsquare.settings.Settings; import io.bitsquare.trade.Direction; import io.bitsquare.trade.Offer; -import io.bitsquare.trade.OfferConstraints; import io.bitsquare.trade.Trading; -import io.bitsquare.trade.orderbook.OrderBook; import io.bitsquare.trade.orderbook.OrderBookFilter; import io.bitsquare.user.User; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.fxml.Initializable; -import javafx.scene.control.*; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.TabPane; +import javafx.scene.control.TextField; import javafx.scene.image.Image; -import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.Pane; +import javafx.scene.layout.GridPane; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.math.BigInteger; import java.net.URL; -import java.util.ArrayList; -import java.util.Currency; import java.util.ResourceBundle; -import java.util.UUID; -public class CreateOfferController implements Initializable, ChildController +public class CreateOfferController implements Initializable, ChildController, WalletFacade.WalletListener { private static final Logger log = LoggerFactory.getLogger(CreateOfferController.class); private NavigationController navigationController; private Trading trading; - private OrderBookFilterSettings orderBookFilterSettings; + private WalletFacade walletFacade; private Settings settings; private User user; - private double filterPaneItemOffset; private Direction direction; - @FXML - public AnchorPane holderPane; - @FXML - public Pane detailsPane; + private Button placeOfferButton; + private int gridRow; + @FXML + private AnchorPane holderPane; + @FXML + private GridPane formGridPane; @FXML public Label buyLabel; @FXML - public TextField volume; - @FXML - public ImageView directionImageView; - - @FXML - public TextField amount; - @FXML - public TextField price; - @FXML - public TextField minAmount; - @FXML - public Button placeOfferButton; + public TextField volume, amount, price, minAmount; @Inject - public CreateOfferController(Trading trading, OrderBookFilterSettings orderBookFilterSettings, Settings settings, User user) + public CreateOfferController(Trading trading, WalletFacade walletFacade, Settings settings, User user) { this.trading = trading; - this.orderBookFilterSettings = orderBookFilterSettings; + this.walletFacade = walletFacade; this.settings = settings; this.user = user; } @@ -79,14 +67,34 @@ public class CreateOfferController implements Initializable, ChildController @Override public void initialize(URL url, ResourceBundle rb) { - createFilterPane(); + walletFacade.addRegistrationWalletListener(this); + gridRow = 2; + FormBuilder.addVSpacer(formGridPane, ++gridRow); + FormBuilder.addHeaderLabel(formGridPane, "Offer details:", ++gridRow); + FormBuilder.addTextField(formGridPane, "Bank account type:", Localisation.get(user.getCurrentBankAccount().getBankAccountType().getType().toString()), ++gridRow); + FormBuilder.addTextField(formGridPane, "Bank account currency:", user.getCurrentBankAccount().getCurrency().getCurrencyCode(), ++gridRow); + FormBuilder.addTextField(formGridPane, "Bank account county:", user.getCurrentBankAccount().getCountryLocale().getDisplayCountry(), ++gridRow); + FormBuilder.addTextField(formGridPane, "Accepted countries:", Formatter.countryLocalesToString(settings.getAcceptedCountryLocales()), ++gridRow); + FormBuilder.addTextField(formGridPane, "Accepted languages:", Formatter.languageLocalesToString(settings.getAcceptedLanguageLocales()), ++gridRow); + + FormBuilder.addVSpacer(formGridPane, ++gridRow); + Label placeOfferTitle = FormBuilder.addHeaderLabel(formGridPane, "Place offer:", ++gridRow); + + TextField feeLabel = FormBuilder.addTextField(formGridPane, "Offer fee:", Formatter.formatSatoshis(Fees.OFFER_CREATION_FEE, true), ++gridRow); + feeLabel.setMouseTransparent(true); + + placeOfferButton = new Button("Place offer"); + formGridPane.add(placeOfferButton, 1, ++gridRow); + placeOfferButton.setDefaultButton(true); + + // handlers amount.textProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, String oldValue, String newValue) { - setVolume(); + updateVolume(); } }); @@ -95,23 +103,66 @@ public class CreateOfferController implements Initializable, ChildController @Override public void changed(ObservableValue observable, String oldValue, String newValue) { - setVolume(); + updateVolume(); } }); placeOfferButton.setOnAction(e -> { - // TODO not impl yet. use mocks - OfferConstraints offerConstraints = new OrderBook(settings).getRandomOfferConstraints(); - Offer offer = new Offer(UUID.randomUUID(), - direction, - Converter.convertToDouble(price.getText()), - Converter.convertToDouble(amount.getText()), - Converter.convertToDouble(minAmount.getText()), - settings.getCurrency(), - user, - offerConstraints); - trading.placeNewOffer(offer); + if (inputValid()) + { + Offer offer = new Offer(user.getAccountID(), + user.getMessageID(), + direction, + Converter.stringToDouble(price.getText()), + Converter.stringToDouble(amount.getText()), + Converter.stringToDouble(minAmount.getText()), + user.getCurrentBankAccount().getBankAccountType().getType(), + user.getCurrentBankAccount().getCurrency(), + user.getCurrentBankAccount().getCountryLocale(), + settings.getAcceptedCountryLocales(), + settings.getAcceptedLanguageLocales()); + + try + { + String txID = trading.placeNewOffer(offer); + formGridPane.getChildren().remove(placeOfferButton); + placeOfferTitle.setText("Transaction sent:"); + buildConfirmationView(txID); + } catch (InsufficientMoneyException e1) + { + //TODO popup + log.error(e.toString()); + } + } + }); + } + + + @Override + public void onConfidenceChanged(int numBroadcastPeers, int depthInBlocks) + { + log.info("onConfidenceChanged " + numBroadcastPeers + " / " + depthInBlocks); + } + + @Override + public void onCoinsReceived(BigInteger newBalance) + { + log.info("onCoinsReceived " + newBalance); + } + + private void buildConfirmationView(String txID) + { + FormBuilder.addTextField(formGridPane, "Transaction ID:", txID, ++gridRow, false, true); + + ConfirmationComponent confirmationComponent = new ConfirmationComponent(walletFacade, formGridPane, ++gridRow); + + Button closeButton = new Button("Close"); + formGridPane.add(closeButton, 1, ++gridRow); + closeButton.setDefaultButton(true); + + + closeButton.setOnAction(e -> { TabPane tabPane = ((TabPane) (holderPane.getParent().getParent())); tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem()); @@ -119,6 +170,7 @@ public class CreateOfferController implements Initializable, ChildController }); } + @Override public void setNavigationController(NavigationController navigationController) { @@ -132,140 +184,36 @@ public class CreateOfferController implements Initializable, ChildController minAmount.setText(Formatter.formatPrice(orderBookFilter.getAmount())); price.setText(Formatter.formatPrice(orderBookFilter.getPrice())); - configDirection(); + String iconPath = (direction == Direction.BUY) ? Icons.BUY : Icons.SELL; + buyLabel.setText(Formatter.formatDirection(direction, false) + ":"); + updateVolume(); } - private void configDirection() + //TODO + private boolean inputValid() { - String iconPath; - String buyLabelText; - if (direction == Direction.BUY) - { - iconPath = "/images/buy.png"; - buyLabelText = "BUY"; - } + return true; + } + + private void updateVolume() + { + double amountAsDouble = Converter.stringToDouble(amount.getText()); + double priceAsDouble = Converter.stringToDouble(price.getText()); + volume.setText(Formatter.formatPrice(amountAsDouble * priceAsDouble)); + } + + private Image getConfirmIconImage(int numBroadcastPeers, int depthInBlocks) + { + if (depthInBlocks > 0) + return Icons.getIconImage(Icons.getIconIDForConfirmations(depthInBlocks)); else - { - iconPath = "/images/sell.png"; - buyLabelText = "SELL"; - } - Image icon = new Image(getClass().getResourceAsStream(iconPath)); - directionImageView.setImage(icon); - buyLabel.setText(buyLabelText); + return Icons.getIconImage(Icons.getIconIDForPeersSeenTx(numBroadcastPeers)); } - private void createFilterPane() + private String getConfirmationsText(int registrationConfirmationNumBroadcastPeers, int registrationConfirmationDepthInBlocks) { - filterPaneItemOffset = 30; - - ArrayList currencies = orderBookFilterSettings.getCurrencies(); - Currency currency = orderBookFilterSettings.getCurrency(); - ComboBox currencyComboBox = createCurrencyItem("Currency: ", currency, currencies); - currencyComboBox.valueProperty().addListener(new ChangeListener() - { - @Override - public void changed(ObservableValue ov, Currency oldValue, Currency newValue) - { - orderBookFilterSettings.setCurrency(newValue); - } - }); - - Label bankLabel = createFilterItem("Bank transfer types: ", "SEPA, OKPAY"); - - Label countriesLabel = createFilterItem("Countries: ", "DE, GB, AT"); - Label languagesLabel = createFilterItem("Languages: ", "DE, EN"); - Label arbitratorsLabel = createFilterItem("Arbitrators: ", "Paysty, BitRated"); - Label identityLabel = createFilterItem("Identity verifications: ", "Passport, Google+, Facebook, Skype"); - TextField collateralLabel = createCollateralItem("Collateral (%): ", 10); + return registrationConfirmationDepthInBlocks + " confirmation(s) / " + "Seen by " + registrationConfirmationNumBroadcastPeers + " peer(s)"; } - private ComboBox createCurrencyItem(String labelText, Currency currency, ArrayList currencies) - { - final Separator separator = new Separator(); - separator.setPrefWidth(380); - separator.setLayoutY(0 + filterPaneItemOffset); - separator.setLayoutX(0); - final Label label = new Label(labelText); - label.setLayoutY(10 + filterPaneItemOffset); - ObservableList options = FXCollections.observableArrayList(currencies); - final ComboBox comboBox = new ComboBox(options); - comboBox.setLayoutX(70); - comboBox.setLayoutY(5 + filterPaneItemOffset); - comboBox.setValue(currency); - - - detailsPane.getChildren().addAll(separator, label, comboBox); - filterPaneItemOffset += 40; - return comboBox; - } - - private Label createFilterItem(String labelText, String valueText) - { - final Separator separator = new Separator(); - separator.setPrefWidth(380); - separator.setLayoutY(0 + filterPaneItemOffset); - separator.setLayoutX(0); - final Label label = new Label(labelText + valueText); - label.setLayoutY(10 + filterPaneItemOffset); - label.setPrefWidth(310); - Tooltip tooltip = new Tooltip(valueText); - label.setTooltip(tooltip); - - final Button edit = new Button("Edit"); - edit.setPrefWidth(50); - edit.setLayoutX(330); - edit.setLayoutY(5 + filterPaneItemOffset); - - detailsPane.getChildren().addAll(separator, label, edit); - filterPaneItemOffset += 40; - return label; - } - - private TextField createCollateralItem(String labelText, double collateral) - { - final Separator separator = new Separator(); - separator.setPrefWidth(380); - separator.setLayoutY(0 + filterPaneItemOffset); - separator.setLayoutX(0); - final Label label = new Label(labelText); - label.setLayoutY(10 + filterPaneItemOffset); - label.setPrefWidth(310); - - final TextField collateralValue = new TextField(Double.toString(collateral)); - collateralValue.setLayoutX(90); - collateralValue.setLayoutY(5 + filterPaneItemOffset); - collateralValue.setPrefWidth(50); - - detailsPane.getChildren().addAll(separator, label, collateralValue); - filterPaneItemOffset += 40; - - return collateralValue; - } - - - private double textInputToNumber(String oldValue, String newValue) - { - //TODO use regex.... or better custom textfield component - double d = 0.0; - if (!newValue.equals("")) - { - d = Converter.convertToDouble(newValue); - if (d == Double.NEGATIVE_INFINITY) - { - amount.setText(oldValue); - d = Converter.convertToDouble(oldValue); - } - } - return d; - } - - private void setVolume() - { - double a = textInputToNumber(amount.getText(), amount.getText()); - double p = textInputToNumber(price.getText(), price.getText()); - volume.setText(Formatter.formatPrice(a * p)); - } - - } diff --git a/src/main/java/io/bitsquare/gui/trade/offer/CreateOfferView.fxml b/src/main/java/io/bitsquare/gui/trade/offer/CreateOfferView.fxml index e3c739201f..91f0737e4c 100644 --- a/src/main/java/io/bitsquare/gui/trade/offer/CreateOfferView.fxml +++ b/src/main/java/io/bitsquare/gui/trade/offer/CreateOfferView.fxml @@ -1,78 +1,50 @@ - + - - - - - + + + + - + - - - -