From 7e8ee84ed1a0fe372b85bf89c7fc57dd72c84e40 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Wed, 20 Aug 2014 21:55:27 +0200 Subject: [PATCH] fixed validation bugs and bugs at create order view --- .../java/io/bitsquare/btc/WalletFacade.java | 2 +- .../java/io/bitsquare/di/BitSquareModule.java | 2 - .../java/io/bitsquare/di/GuiceFXMLLoader.java | 2 +- .../java/io/bitsquare/gui/MainController.java | 7 - .../java/io/bitsquare/gui/NavigationItem.java | 4 +- .../gui/components/ValidatingTextField.java | 131 +++++++++------- .../gui/components/btc/BalanceTextField.java | 15 +- .../bitsquare/gui/market/BuyController.java | 14 ++ .../market/{MarketView.fxml => BuyView.fxml} | 2 +- .../gui/market/MarketController.java | 135 ----------------- .../bitsquare/gui/market/SellController.java | 143 ++++++++++++++++++ .../io/bitsquare/gui/market/SellView.fxml | 7 + .../createOffer/CreateOfferController.java | 52 ++++--- .../market/createOffer/CreateOfferView.fxml | 6 +- .../market/orderbook/OrderBookController.java | 15 +- .../io/bitsquare/gui/util/BtcValidator.java | 19 +-- .../bitsquare/gui/util/NumberValidator.java | 1 - .../bitsquare/trade/orderbook/OrderBook.java | 6 +- .../createoffer/tasks/ValidateOffer.java | 11 +- 19 files changed, 328 insertions(+), 246 deletions(-) create mode 100644 src/main/java/io/bitsquare/gui/market/BuyController.java rename src/main/java/io/bitsquare/gui/market/{MarketView.fxml => BuyView.fxml} (82%) delete mode 100644 src/main/java/io/bitsquare/gui/market/MarketController.java create mode 100644 src/main/java/io/bitsquare/gui/market/SellController.java create mode 100644 src/main/java/io/bitsquare/gui/market/SellView.fxml diff --git a/src/main/java/io/bitsquare/btc/WalletFacade.java b/src/main/java/io/bitsquare/btc/WalletFacade.java index 34142bf08c..4fc4a34887 100644 --- a/src/main/java/io/bitsquare/btc/WalletFacade.java +++ b/src/main/java/io/bitsquare/btc/WalletFacade.java @@ -648,7 +648,7 @@ public class WalletFacade Coin fee = FeePolicy.CREATE_OFFER_FEE.subtract(FeePolicy.TX_FEE); log.trace("fee: " + fee.toFriendlyString()); tx.addOutput(fee, feePolicy.getAddressForCreateOfferFee()); - printInputs("payCreateOfferFee", tx); + // printInputs("payCreateOfferFee", tx); Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx); sendRequest.shuffleOutputs = false; // we allow spending of unconfirmed tx (double spend risk is low and usability would suffer if we need to wait for 1 confirmation) diff --git a/src/main/java/io/bitsquare/di/BitSquareModule.java b/src/main/java/io/bitsquare/di/BitSquareModule.java index 5e61adc62b..e78d0d4e9f 100644 --- a/src/main/java/io/bitsquare/di/BitSquareModule.java +++ b/src/main/java/io/bitsquare/di/BitSquareModule.java @@ -20,7 +20,6 @@ import io.bitsquare.settings.Settings; import io.bitsquare.storage.Persistence; import io.bitsquare.trade.TradeManager; import io.bitsquare.trade.orderbook.OrderBook; -import io.bitsquare.trade.orderbook.OrderBookFilter; import io.bitsquare.user.User; import javax.inject.Inject; @@ -34,7 +33,6 @@ public class BitSquareModule extends AbstractModule bind(OrderBook.class).asEagerSingleton(); bind(Persistence.class).asEagerSingleton(); bind(Settings.class).asEagerSingleton(); - bind(OrderBookFilter.class).asEagerSingleton(); bind(CryptoFacade.class).asEagerSingleton(); bind(WalletFacade.class).asEagerSingleton(); diff --git a/src/main/java/io/bitsquare/di/GuiceFXMLLoader.java b/src/main/java/io/bitsquare/di/GuiceFXMLLoader.java index 1d33b0c50b..cc51e1b5d1 100644 --- a/src/main/java/io/bitsquare/di/GuiceFXMLLoader.java +++ b/src/main/java/io/bitsquare/di/GuiceFXMLLoader.java @@ -40,8 +40,8 @@ public class GuiceFXMLLoader { this.url = url; + // useCaching = false; isCached = useCaching && cachedGUIItems.containsKey(url); - if (!isCached) { loader = new FXMLLoader(url, Localisation.getResourceBundle()); diff --git a/src/main/java/io/bitsquare/gui/MainController.java b/src/main/java/io/bitsquare/gui/MainController.java index 284a4df5a8..4681ffb416 100644 --- a/src/main/java/io/bitsquare/gui/MainController.java +++ b/src/main/java/io/bitsquare/gui/MainController.java @@ -6,7 +6,6 @@ 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.market.MarketController; import io.bitsquare.gui.orders.OrdersController; import io.bitsquare.gui.util.ImageUtil; import io.bitsquare.gui.util.Profiler; @@ -14,7 +13,6 @@ import io.bitsquare.gui.util.Transitions; import io.bitsquare.msg.BootstrapListener; import io.bitsquare.msg.MessageFacade; import io.bitsquare.storage.Persistence; -import io.bitsquare.trade.Direction; import io.bitsquare.trade.TradeManager; import io.bitsquare.user.User; import io.bitsquare.util.AWTSystemTray; @@ -332,11 +330,6 @@ public class MainController implements Initializable, NavigationController controller = loadView(navigationItem); - if (controller instanceof MarketController) - { - ((MarketController) controller).setDirection(navigationItem == NavigationItem.BUY ? Direction.BUY : Direction.SELL); - } - persistence.write(this, "selectedNavigationItem", navigationItem); prevToggleButton = toggleButton; diff --git a/src/main/java/io/bitsquare/gui/NavigationItem.java b/src/main/java/io/bitsquare/gui/NavigationItem.java index 32f1424554..069af9f6bc 100644 --- a/src/main/java/io/bitsquare/gui/NavigationItem.java +++ b/src/main/java/io/bitsquare/gui/NavigationItem.java @@ -6,8 +6,8 @@ public enum NavigationItem { MAIN("/io/bitsquare/gui/MainView.fxml"), HOME("/io/bitsquare/gui/home/HomeView.fxml", ImageUtil.HOME, ImageUtil.HOME_ACTIVE), - BUY("/io/bitsquare/gui/market/MarketView.fxml", ImageUtil.NAV_BUY, ImageUtil.NAV_BUY_ACTIVE), - SELL("/io/bitsquare/gui/market/MarketView.fxml", ImageUtil.NAV_SELL, ImageUtil.NAV_SELL_ACTIVE), + BUY("/io/bitsquare/gui/market/BuyView.fxml", ImageUtil.NAV_BUY, ImageUtil.NAV_BUY_ACTIVE), + SELL("/io/bitsquare/gui/market/SellView.fxml", ImageUtil.NAV_SELL, ImageUtil.NAV_SELL_ACTIVE), ORDERS("/io/bitsquare/gui/orders/OrdersView.fxml", ImageUtil.ORDERS, ImageUtil.ORDERS_ACTIVE), FUNDS("/io/bitsquare/gui/funds/FundsView.fxml", ImageUtil.FUNDS, ImageUtil.FUNDS_ACTIVE), MSG("/io/bitsquare/gui/msg/MsgView.fxml", ImageUtil.MSG, ImageUtil.MSG_ACTIVE), diff --git a/src/main/java/io/bitsquare/gui/components/ValidatingTextField.java b/src/main/java/io/bitsquare/gui/components/ValidatingTextField.java index dd8fa01e34..5ed031ede0 100644 --- a/src/main/java/io/bitsquare/gui/components/ValidatingTextField.java +++ b/src/main/java/io/bitsquare/gui/components/ValidatingTextField.java @@ -1,7 +1,6 @@ package io.bitsquare.gui.components; import io.bitsquare.gui.util.NumberValidator; -import java.util.LinkedList; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.geometry.Insets; @@ -28,21 +27,26 @@ import org.slf4j.LoggerFactory; public class ValidatingTextField extends TextField { private static final Logger log = LoggerFactory.getLogger(ValidatingTextField.class); - private static final Effect DEFAULT_EFFECT = new DropShadow(BlurType.GAUSSIAN, Color.RED, 4, 0.0, 0, 0); + private static PopOver popOver; - // we hold all error popups any only display the latest one - private static final LinkedList allErrorPopups = new LinkedList<>(); + private Effect invalidEffect = new DropShadow(BlurType.GAUSSIAN, Color.RED, 4, 0.0, 0, 0); - private Effect invalidEffect = DEFAULT_EFFECT; - private final BooleanProperty valid = new SimpleBooleanProperty(true); + private final BooleanProperty isValid = new SimpleBooleanProperty(true); private NumberValidator numberValidator; private boolean validateOnFocusOut = true; private boolean needsValidationOnFocusOut; - private PopOver popOver; - private Region errorPopupLayoutReference; - private double errorPopOverX; - private double errorPopOverY; + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Static + /////////////////////////////////////////////////////////////////////////////////////////// + + public static void hidePopover() + { + if (popOver != null) + popOver.hide(); + } /////////////////////////////////////////////////////////////////////////////////////////// @@ -52,6 +56,7 @@ public class ValidatingTextField extends TextField public ValidatingTextField() { super(); + setupListeners(); } @@ -75,19 +80,44 @@ public class ValidatingTextField extends TextField this.numberValidator = numberValidator; } + /** + * @param errorPopupLayoutReference The node used as reference for positioning + */ public void setErrorPopupLayoutReference(Region errorPopupLayoutReference) { this.errorPopupLayoutReference = errorPopupLayoutReference; } + /////////////////////////////////////////////////////////////////////////////////////////// + // Getters + /////////////////////////////////////////////////////////////////////////////////////////// + + public boolean getIsValid() + { + return isValid.get(); + } + + public BooleanProperty isValidProperty() + { + return isValid; + } + + /////////////////////////////////////////////////////////////////////////////////////////// // Private methods /////////////////////////////////////////////////////////////////////////////////////////// private void setupListeners() { - this.textProperty().addListener((ov, oldValue, newValue) -> { + sceneProperty().addListener((ov, oldValue, newValue) -> { + // we got removed from the scene + // lets hide an open popup + if (newValue == null) + hidePopover(); + }); + + textProperty().addListener((ov, oldValue, newValue) -> { if (numberValidator != null) { if (!validateOnFocusOut) @@ -97,12 +127,12 @@ public class ValidatingTextField extends TextField } }); - this.focusedProperty().addListener((ov, oldValue, newValue) -> { - if (validateOnFocusOut && needsValidationOnFocusOut && !newValue && getScene()!= null && getScene().getWindow().isFocused()) + focusedProperty().addListener((ov, oldValue, newValue) -> { + if (validateOnFocusOut && needsValidationOnFocusOut && !newValue && getScene() != null && getScene().getWindow().isFocused()) validate(getText()); }); - this.valid.addListener((ov, oldValue, newValue) -> applyEffect(newValue)); + isValid.addListener((ov, oldValue, newValue) -> applyEffect(newValue)); } private void validate(String input) @@ -110,7 +140,7 @@ public class ValidatingTextField extends TextField if (input != null) { NumberValidator.ValidationResult validationResult = numberValidator.validate(input); - valid.set(validationResult.isValid); + isValid.set(validationResult.isValid); applyErrorMessage(validationResult); } } @@ -119,35 +149,19 @@ public class ValidatingTextField extends TextField { if (validationResult.isValid) { - if (allErrorPopups.contains(popOver)) + if (popOver != null) { - allErrorPopups.remove(popOver); popOver.hide(); } - if (allErrorPopups.size() > 0) - { - PopOver lastPopOver = allErrorPopups.getLast(); - lastPopOver.show(getScene().getWindow()); - } - popOver = null; } else { - if (allErrorPopups.size() > 0) - { - PopOver lastPopOver = allErrorPopups.getLast(); - lastPopOver.hide(); - } + if (popOver == null) + createErrorPopOver(validationResult.errorMessage); + else + setErrorMessage(validationResult.errorMessage); - if (allErrorPopups.contains(popOver)) - { - allErrorPopups.remove(popOver); - popOver.hide(); - } - - popOver = createErrorPopOver(validationResult.errorMessage); - popOver.show(getScene().getWindow(), errorPopOverX, errorPopOverY); - allErrorPopups.add(popOver); + popOver.show(getScene().getWindow(), getErrorPopupPosition().getX(), getErrorPopupPosition().getY()); } } @@ -156,30 +170,39 @@ public class ValidatingTextField extends TextField setEffect(isValid ? null : invalidEffect); } - private PopOver createErrorPopOver(String errorMessage) + private Point2D getErrorPopupPosition() + { + Window window = getScene().getWindow(); + Point2D point; + double x; + if (errorPopupLayoutReference == null) + { + point = localToScene(0, 0); + x = point.getX() + window.getX() + getWidth() + 20; + } + else + { + point = errorPopupLayoutReference.localToScene(0, 0); + x = point.getX() + window.getX() + errorPopupLayoutReference.getWidth() + 20; + } + double y = point.getY() + window.getY() + Math.floor(getHeight() / 2); + return new Point2D(x, y); + } + + private static void setErrorMessage(String errorMessage) + { + ((Label) popOver.getContentNode()).setText(errorMessage); + } + + private static void createErrorPopOver(String errorMessage) { Label errorLabel = new Label(errorMessage); errorLabel.setId("validation-error"); errorLabel.setPadding(new Insets(0, 10, 0, 10)); - PopOver popOver = new PopOver(errorLabel); + popOver = new PopOver(errorLabel); popOver.setAutoFix(true); popOver.setDetachedTitle(""); popOver.setArrowIndent(5); - Window window = getScene().getWindow(); - - Point2D point; - if (errorPopupLayoutReference == null) - { - point = localToScene(0, 0); - errorPopOverX = point.getX() + window.getX() + getWidth() + 20; - } - else - { - point = errorPopupLayoutReference.localToScene(0, 0); - errorPopOverX = point.getX() + window.getX() + errorPopupLayoutReference.getWidth() + 20; - } - errorPopOverY = point.getY() + window.getY() + Math.floor(getHeight() / 2); - return popOver; } } \ No newline at end of file diff --git a/src/main/java/io/bitsquare/gui/components/btc/BalanceTextField.java b/src/main/java/io/bitsquare/gui/components/btc/BalanceTextField.java index f9a88c437d..afe4df02fe 100644 --- a/src/main/java/io/bitsquare/gui/components/btc/BalanceTextField.java +++ b/src/main/java/io/bitsquare/gui/components/btc/BalanceTextField.java @@ -24,6 +24,7 @@ public class BalanceTextField extends AnchorPane private WalletFacade walletFacade; private ConfidenceListener confidenceListener; private BalanceListener balanceListener; + private Coin balance; /////////////////////////////////////////////////////////////////////////////////////////// @@ -96,11 +97,21 @@ public class BalanceTextField extends AnchorPane walletFacade.removeBalanceListener(balanceListener); } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Getters + /////////////////////////////////////////////////////////////////////////////////////////// + + public Coin getBalance() + { + return balance; + } + + /////////////////////////////////////////////////////////////////////////////////////////// // Private methods /////////////////////////////////////////////////////////////////////////////////////////// - private void updateConfidence(TransactionConfidence confidence) { if (confidence != null) @@ -136,10 +147,12 @@ public class BalanceTextField extends AnchorPane private void updateBalance(Coin balance) { + this.balance = balance; if (balance != null) { //TODO use BitSquareFormatter balanceTextField.setText(balance.toFriendlyString()); } } + } diff --git a/src/main/java/io/bitsquare/gui/market/BuyController.java b/src/main/java/io/bitsquare/gui/market/BuyController.java new file mode 100644 index 0000000000..2f38370802 --- /dev/null +++ b/src/main/java/io/bitsquare/gui/market/BuyController.java @@ -0,0 +1,14 @@ +package io.bitsquare.gui.market; + +import io.bitsquare.trade.Direction; + +public class BuyController extends SellController +{ + @Override + protected void applyDirection() + { + //tabPane.getSelectionModel().select(0); + orderBookController.applyDirection(Direction.BUY); + } +} + diff --git a/src/main/java/io/bitsquare/gui/market/MarketView.fxml b/src/main/java/io/bitsquare/gui/market/BuyView.fxml similarity index 82% rename from src/main/java/io/bitsquare/gui/market/MarketView.fxml rename to src/main/java/io/bitsquare/gui/market/BuyView.fxml index 1f2bc1edbb..91e66e209b 100644 --- a/src/main/java/io/bitsquare/gui/market/MarketView.fxml +++ b/src/main/java/io/bitsquare/gui/market/BuyView.fxml @@ -4,4 +4,4 @@ \ No newline at end of file + fx:controller="io.bitsquare.gui.market.BuyController"/> \ No newline at end of file diff --git a/src/main/java/io/bitsquare/gui/market/MarketController.java b/src/main/java/io/bitsquare/gui/market/MarketController.java deleted file mode 100644 index 9a3252456a..0000000000 --- a/src/main/java/io/bitsquare/gui/market/MarketController.java +++ /dev/null @@ -1,135 +0,0 @@ -package io.bitsquare.gui.market; - -import io.bitsquare.di.GuiceFXMLLoader; -import io.bitsquare.gui.ChildController; -import io.bitsquare.gui.NavigationController; -import io.bitsquare.gui.NavigationItem; -import io.bitsquare.gui.market.orderbook.OrderBookController; -import io.bitsquare.trade.Direction; -import java.io.IOException; -import java.net.URL; -import java.util.ResourceBundle; -import javafx.fxml.FXML; -import javafx.fxml.Initializable; -import javafx.scene.Parent; -import javafx.scene.control.Tab; -import javafx.scene.control.TabPane; - -public class MarketController implements Initializable, NavigationController, ChildController -{ - private boolean orderbookCreated; - - private OrderBookController orderBookController; - - @FXML - private TabPane tabPane; - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Interface implementation: Initializable - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void initialize(URL url, ResourceBundle rb) - { - navigateToView(NavigationItem.ORDER_BOOK); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Interface implementation: NavigationController - /////////////////////////////////////////////////////////////////////////////////////////// - - - @Override - public ChildController navigateToView(NavigationItem navigationItem) - { - - if (navigationItem == NavigationItem.ORDER_BOOK && orderbookCreated) - { - tabPane.getSelectionModel().select(0); - return null; - } - - final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl())); - try - { - final Parent view = loader.load(); - ChildController childController = loader.getController(); - childController.setNavigationController(this); - - if (childController instanceof OrderBookController) - { - orderBookController = (OrderBookController) childController; - } - - String tabLabel; - switch (navigationItem) - { - case CREATE_OFFER: - tabLabel = "Create offer"; - break; - case TAKE_OFFER: - tabLabel = "Take offer"; - break; - default: - tabLabel = "Orderbook"; - break; - } - final Tab tab = new Tab(tabLabel); - tab.setContent(view); - tabPane.getTabs().add(tab); - - if (navigationItem == NavigationItem.ORDER_BOOK) - { - tab.setClosable(false); - orderbookCreated = true; - } - - tabPane.getSelectionModel().select(tabPane.getTabs().size() - 1); - - return childController; - } catch (IOException e) - { - e.printStackTrace(); - } - return null; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Interface implementation: ChildController - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void setNavigationController(NavigationController navigationController) - { - - } - - @Override - public void cleanup() - { - if (orderBookController != null) - { - orderBookController.cleanup(); - orderBookController = null; - } - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Setter - /////////////////////////////////////////////////////////////////////////////////////////// - - public void setDirection(Direction direction) - { - tabPane.getSelectionModel().select(0); - if (orderBookController != null) - { - orderBookController.setDirection(direction); - } - } - -} - diff --git a/src/main/java/io/bitsquare/gui/market/SellController.java b/src/main/java/io/bitsquare/gui/market/SellController.java new file mode 100644 index 0000000000..893e112ce1 --- /dev/null +++ b/src/main/java/io/bitsquare/gui/market/SellController.java @@ -0,0 +1,143 @@ +package io.bitsquare.gui.market; + +import io.bitsquare.di.GuiceFXMLLoader; +import io.bitsquare.gui.ChildController; +import io.bitsquare.gui.NavigationController; +import io.bitsquare.gui.NavigationItem; +import io.bitsquare.gui.components.ValidatingTextField; +import io.bitsquare.gui.market.orderbook.OrderBookController; +import io.bitsquare.trade.Direction; +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; +import javafx.application.Platform; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.Parent; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.google.common.base.Preconditions.checkArgument; + +public class SellController implements Initializable, NavigationController, ChildController +{ + private static final Logger log = LoggerFactory.getLogger(SellController.class); + + protected OrderBookController orderBookController; + protected GuiceFXMLLoader orderBookLoader; + + @FXML + protected TabPane tabPane; + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Interface implementation: Initializable + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void initialize(URL url, ResourceBundle rb) + { + // TODO find better solution + // Textfield focus out triggers validation, use runLater as quick fix... + tabPane.getSelectionModel().selectedIndexProperty().addListener((observableValue) -> Platform.runLater(() -> ValidatingTextField.hidePopover())); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Interface implementation: NavigationController + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public ChildController navigateToView(NavigationItem navigationItem) + { + if (navigationItem == NavigationItem.ORDER_BOOK) + { + return loadOrderBook(); + } + else + { + checkArgument(navigationItem.equals(NavigationItem.CREATE_OFFER) || navigationItem.equals(NavigationItem.TAKE_OFFER)); + + // 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); + try + { + final Parent view = loader.load(); + ChildController childController = loader.getController(); + childController.setNavigationController(this); + + String tabLabel = navigationItem.equals(NavigationItem.CREATE_OFFER) ? "Create offer" : "Take offer"; + final Tab tab = new Tab(tabLabel); + tab.setContent(view); + tabPane.getTabs().add(tab); + tabPane.getSelectionModel().select(tabPane.getTabs().size() - 1); + + return childController; + } catch (IOException e) + { + e.printStackTrace(); + log.error(e.getMessage()); + } + return null; + } + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Interface implementation: ChildController + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void setNavigationController(NavigationController navigationController) + { + navigateToView(NavigationItem.ORDER_BOOK); + } + + @Override + public void cleanup() + { + if (orderBookController != null) + { + orderBookController.cleanup(); + orderBookController = null; + } + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Protected + /////////////////////////////////////////////////////////////////////////////////////////// + + protected void applyDirection() + { + orderBookController.applyDirection(Direction.SELL); + } + + protected ChildController loadOrderBook() + { + // Orderbook must not be cached by GuiceFXMLLoader as we use 2 instances for sell and buy screens. + if (orderBookLoader == null) + { + orderBookLoader = new GuiceFXMLLoader(getClass().getResource(NavigationItem.ORDER_BOOK.getFxmlUrl()), false); + try + { + final Parent view = orderBookLoader.load(); + final Tab tab = new Tab("Orderbook"); + tab.setClosable(false); + tab.setContent(view); + tabPane.getTabs().add(tab); + } catch (IOException e) + { + e.printStackTrace(); + } + } + orderBookController = orderBookLoader.getController(); + orderBookController.setNavigationController(this); + applyDirection(); + return orderBookController; + } + +} + diff --git a/src/main/java/io/bitsquare/gui/market/SellView.fxml b/src/main/java/io/bitsquare/gui/market/SellView.fxml new file mode 100644 index 0000000000..ac7de429dd --- /dev/null +++ b/src/main/java/io/bitsquare/gui/market/SellView.fxml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferController.java b/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferController.java index 5240a8faaa..56da94515f 100644 --- a/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferController.java +++ b/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferController.java @@ -77,6 +77,7 @@ public class CreateOfferController implements Initializable, ChildController, Hi final ViewModel viewModel = new ViewModel(); private final double collateral; private Direction direction; + private AddressEntry addressEntry; @FXML private AnchorPane rootContainer; @FXML private Label buyLabel, confirmationLabel, txTitleLabel, collateralLabel; @@ -137,17 +138,13 @@ public class CreateOfferController implements Initializable, ChildController, Hi @Override public void initialize(URL url, ResourceBundle rb) { - - // Node wrappedButton = Borders.wrap(button).etchedBorder().buildAll() - - setupBindings(); setupValidation(); //TODO if (walletFacade.getWallet() != null) { - AddressEntry addressEntry = walletFacade.getUnusedTradeAddressInfo(); + addressEntry = walletFacade.getUnusedTradeAddressInfo(); addressTextField.setAddress(addressEntry.getAddress().toString()); balanceTextField.setAddress(addressEntry.getAddress()); @@ -215,11 +212,18 @@ public class CreateOfferController implements Initializable, ChildController, Hi placeOfferButton.visibleProperty().bind(viewModel.isOfferPlacedScreen.not()); closeButton.visibleProperty().bind(viewModel.isOfferPlacedScreen); + + //TODO /* progressIndicator.visibleProperty().bind(viewModel.isOfferPlacedScreen); confirmationLabel.visibleProperty().bind(viewModel.isOfferPlacedScreen); txTitleLabel.visibleProperty().bind(viewModel.isOfferPlacedScreen); transactionIdTextField.visibleProperty().bind(viewModel.isOfferPlacedScreen); */ + + placeOfferButton.disableProperty().bind(amountTextField.isValidProperty() + .and(minAmountTextField.isValidProperty()) + .and(volumeTextField.isValidProperty()) + .and(priceTextField.isValidProperty()).not()); } private void setupValidation() @@ -258,7 +262,7 @@ public class CreateOfferController implements Initializable, ChildController, Hi priceTextField.focusedProperty().addListener((ov, oldValue, newValue) -> { // only on focus out and ignore focus loss from window if (!newValue && priceTextField.getScene() != null && priceTextField.getScene().getWindow().isFocused()) - volumeTextField.reValidate(); + volumeTextField.reValidate(); }); } @@ -302,20 +306,30 @@ public class CreateOfferController implements Initializable, ChildController, Hi @FXML public void onPlaceOffer() { - viewModel.isPlaceOfferButtonDisabled.set(true); + amountTextField.reValidate(); + minAmountTextField.reValidate(); + volumeTextField.reValidate(); + priceTextField.reValidate(); - tradeManager.requestPlaceOffer(direction, - BitSquareFormatter.parseToDouble(viewModel.price.get()), - BitSquareFormatter.parseToCoin(viewModel.amount.get()), - BitSquareFormatter.parseToCoin(viewModel.minAmount.get()), - (transaction) -> { - viewModel.isOfferPlacedScreen.set(true); - viewModel.transactionId.set(transaction.getHashAsString()); - }, - errorMessage -> { - Popups.openErrorPopup("An error occurred", errorMessage); - viewModel.isPlaceOfferButtonDisabled.set(false); - }); + //balanceTextField.getBalance() + + if (amountTextField.getIsValid() && minAmountTextField.getIsValid() && volumeTextField.getIsValid() && amountTextField.getIsValid()) + { + viewModel.isPlaceOfferButtonDisabled.set(true); + + tradeManager.requestPlaceOffer(direction, + BitSquareFormatter.parseToDouble(viewModel.price.get()), + BitSquareFormatter.parseToCoin(viewModel.amount.get()), + BitSquareFormatter.parseToCoin(viewModel.minAmount.get()), + (transaction) -> { + viewModel.isOfferPlacedScreen.set(true); + viewModel.transactionId.set(transaction.getHashAsString()); + }, + errorMessage -> { + Popups.openErrorPopup("An error occurred", errorMessage); + viewModel.isPlaceOfferButtonDisabled.set(false); + }); + } } @FXML diff --git a/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferView.fxml b/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferView.fxml index 1298d377c3..9806d3f106 100644 --- a/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferView.fxml +++ b/src/main/java/io/bitsquare/gui/market/createOffer/CreateOfferView.fxml @@ -7,8 +7,8 @@ - + @@ -63,7 +63,7 @@ -