fixed validation bugs and bugs at create order view

This commit is contained in:
Manfred Karrer 2014-08-20 21:55:27 +02:00
parent 844029d967
commit 7e8ee84ed1
19 changed files with 328 additions and 246 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -4,4 +4,4 @@
<?import javafx.scene.layout.AnchorPane?>
<TabPane xmlns:fx="http://javafx.com/fxml/1" fx:id="tabPane" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
fx:controller="io.bitsquare.gui.market.MarketController"/>
fx:controller="io.bitsquare.gui.market.BuyController"/>

View file

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

View file

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

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<TabPane xmlns:fx="http://javafx.com/fxml/1" fx:id="tabPane" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
fx:controller="io.bitsquare.gui.market.SellController"/>

View file

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

View file

@ -7,8 +7,8 @@
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" fx:id="rootContainer" prefHeight="500" prefWidth="800" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0"
AnchorPane.topAnchor="10.0" xmlns="http://javafx.com/javafx/8" fx:controller="io.bitsquare.gui.market.createOffer.CreateOfferController">
<AnchorPane fx:id="rootContainer" prefHeight="500" prefWidth="800" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0"
AnchorPane.topAnchor="10.0" xmlns="http://javafx.com/javafx/8" fx:controller="io.bitsquare.gui.market.createOffer.CreateOfferController" xmlns:fx="http://javafx.com/fxml/1" >
<GridPane hgap="5.0" vgap="5.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
@ -63,7 +63,7 @@
<!-- button -->
<VSpacer GridPane.rowIndex="7" prefHeight="10"/>
<Button GridPane.rowIndex="8" GridPane.columnIndex="1" fx:id="placeOfferButton" onAction="#onPlaceOffer" defaultButton="true" text="Place offer"/>
<Button GridPane.rowIndex="8" GridPane.columnIndex="1" fx:id="placeOfferButton" onAction="#onPlaceOffer" disable="true" defaultButton="true" text="Place offer"/>
<Button GridPane.rowIndex="8" GridPane.columnIndex="1" fx:id="closeButton" onAction="#onClose" visible="false" defaultButton="true" focusTraversable="false" text="Close"/>

View file

@ -92,15 +92,16 @@ public class OrderBookController implements Initializable, ChildController
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private OrderBookController(OrderBook orderBook, OrderBookFilter orderBookFilter, User user, MessageFacade messageFacade, WalletFacade walletFacade, Settings settings, Persistence persistence)
private OrderBookController(OrderBook orderBook, User user, MessageFacade messageFacade, WalletFacade walletFacade, Settings settings, Persistence persistence)
{
this.orderBook = orderBook;
this.orderBookFilter = orderBookFilter;
this.user = user;
this.messageFacade = messageFacade;
this.walletFacade = walletFacade;
this.settings = settings;
this.persistence = persistence;
this.orderBookFilter = new OrderBookFilter();
}
@ -111,12 +112,15 @@ public class OrderBookController implements Initializable, ChildController
@Override
public void initialize(URL url, ResourceBundle rb)
{
orderBook.init();
// init table
setCountryColumnCellFactory();
setBankAccountTypeColumnCellFactory();
setDirectionColumnCellFactory();
}
private void init()
{
orderBook.init();
offerList = orderBook.getOfferList();
offerList.comparatorProperty().bind(orderBookTable.comparatorProperty());
orderBookTable.setItems(offerList);
@ -178,8 +182,9 @@ public class OrderBookController implements Initializable, ChildController
// Public methods
///////////////////////////////////////////////////////////////////////////////////////////
public void setDirection(Direction direction)
public void applyDirection(Direction direction)
{
init();
orderBookTable.getSelectionModel().clearSelection();
price.setText("");
orderBookFilter.setDirection(direction);

View file

@ -13,7 +13,7 @@ import org.slf4j.LoggerFactory;
public class BtcValidator extends NumberValidator
{
private static final Logger log = LoggerFactory.getLogger(BtcValidator.class);
private ValidationResult overriddenValidationResult;
private ValidationResult externalValidationResult;
///////////////////////////////////////////////////////////////////////////////////////////
@ -23,6 +23,9 @@ public class BtcValidator extends NumberValidator
@Override
public ValidationResult validate(String input)
{
if (externalValidationResult != null)
return externalValidationResult;
ValidationResult result = validateIfNotEmpty(input);
if (result.isValid)
{
@ -37,23 +40,21 @@ public class BtcValidator extends NumberValidator
.and(validateIfNotFractionalBtcValue(input))
.and(validateIfNotExceedsMaxBtcValue(input));
}
if (overriddenValidationResult != null)
return overriddenValidationResult;
return result;
}
/**
* Used to integrate external validation (e.g. for MinAmount/Amount)
* TODO Might be improved but does the job for now...
* TODO To be improved but does the job for now...
*
* @param overriddenValidationResult
* @param externalValidationResult
*/
public void overrideResult(ValidationResult overriddenValidationResult)
public void overrideResult(ValidationResult externalValidationResult)
{
this.overriddenValidationResult = overriddenValidationResult;
this.externalValidationResult = externalValidationResult;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Protected methods

View file

@ -25,7 +25,6 @@ public abstract class NumberValidator
// Protected methods
///////////////////////////////////////////////////////////////////////////////////////////
protected ValidationResult validateIfNotEmpty(String input)
{
if (input == null || input.length() == 0)

View file

@ -140,7 +140,7 @@ public class OrderBook implements OrderBookListener
//noinspection UnnecessaryLocalVariable
boolean result = currencyResult && countryResult && languageResult && amountResult && directionResult && priceResult && arbitratorResult;
/*
/*
log.debug("result = " + result +
", currencyResult = " + currencyResult +
", countryResult = " + countryResult +
@ -149,8 +149,8 @@ public class OrderBook implements OrderBookListener
", directionResult = " + directionResult +
", priceResult = " + priceResult +
", arbitratorResult = " + arbitratorResult
);
);*/
/*
log.debug("currentBankAccount.getCurrency() = " + currentBankAccount.getCurrency() +
", offer.getCurrency() = " + offer.getCurrency());
log.debug("offer.getCountryLocale() = " + offer.getBankAccountCountryLocale() +

View file

@ -1,5 +1,7 @@
package io.bitsquare.trade.protocol.createoffer.tasks;
import com.google.bitcoin.core.Coin;
import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.Restritions;
import io.bitsquare.trade.Offer;
import io.bitsquare.trade.handlers.FaultHandler;
@ -37,17 +39,22 @@ public class ValidateOffer
checkArgument(offer.getAcceptedCountries().size() > 0);
checkArgument(offer.getAcceptedLanguageLocales().size() > 0);
checkArgument(offer.getAmount().isGreaterThan(Restritions.MIN_TRADE_AMOUNT));
checkArgument(offer.getMinAmount().compareTo(Restritions.MIN_TRADE_AMOUNT) >= 0);
checkArgument(offer.getAmount().compareTo(Restritions.MIN_TRADE_AMOUNT) >= 0);
checkArgument(offer.getAmount().compareTo(offer.getMinAmount()) >= 0);
checkArgument(offer.getCollateral() > 0);
checkArgument(offer.getPrice() > 0);
// TODO check balance
Coin collateralAsCoin = offer.getAmount().divide((long) (1d / offer.getCollateral()));
Coin totalsToFund = collateralAsCoin.add(FeePolicy.CREATE_OFFER_FEE.add(FeePolicy.TX_FEE));
// getAddressInfoByTradeID(offerId)
// TODO when offer is flattened continue here...
resultHandler.onResult();
} catch (Throwable t)
{
faultHandler.onFault("Offer validation failed with exception: " + t.getMessage(), t);
faultHandler.onFault("Offer validation failed.", t);
}
}
}