mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-03-15 10:26:37 -04:00
new validation impl., use bindings in create offer controller, profiler added, use caching for FXML loader
This commit is contained in:
parent
83203554e9
commit
1bc0dbfa31
@ -8,13 +8,12 @@ import io.bitsquare.di.BitSquareModule;
|
||||
import io.bitsquare.di.GuiceFXMLLoader;
|
||||
import io.bitsquare.gui.NavigationItem;
|
||||
import io.bitsquare.gui.popups.Popups;
|
||||
import io.bitsquare.locale.Localisation;
|
||||
import io.bitsquare.gui.util.Profiler;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.settings.Settings;
|
||||
import io.bitsquare.storage.Persistence;
|
||||
import io.bitsquare.user.User;
|
||||
import io.bitsquare.util.AWTSystemTray;
|
||||
import io.bitsquare.util.FileUtil;
|
||||
import io.bitsquare.util.StorageDirectory;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -47,6 +46,8 @@ public class BitSquare extends Application
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
Profiler.init();
|
||||
Profiler.printMsgWithTime("main called");
|
||||
log.debug("Startup: main " + Arrays.asList(args).toString());
|
||||
if (args != null && args.length > 0) APP_NAME = args[0];
|
||||
|
||||
@ -63,15 +64,10 @@ public class BitSquare extends Application
|
||||
return APP_NAME;
|
||||
}
|
||||
|
||||
public static String getUID()
|
||||
{
|
||||
return FileUtil.getApplicationFileName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws IOException
|
||||
{
|
||||
log.trace("Startup: start");
|
||||
Profiler.printMsgWithTime("start called");
|
||||
BitSquare.primaryStage = primaryStage;
|
||||
|
||||
Thread.currentThread().setUncaughtExceptionHandler((thread, throwable) -> Popups.handleUncaughtExceptions(Throwables.getRootCause(throwable)));
|
||||
@ -85,7 +81,7 @@ public class BitSquare extends Application
|
||||
|
||||
walletFacade = injector.getInstance(WalletFacade.class);
|
||||
messageFacade = injector.getInstance(MessageFacade.class);
|
||||
log.trace("Startup: messageFacade, walletFacade inited");
|
||||
Profiler.printMsgWithTime("Startup: messageFacade, walletFacade inited");
|
||||
|
||||
// apply stored data
|
||||
final User user = injector.getInstance(User.class);
|
||||
@ -99,30 +95,29 @@ public class BitSquare extends Application
|
||||
|
||||
settings.applyPersistedSettings((Settings) persistence.read(settings.getClass().getName()));
|
||||
|
||||
primaryStage.setTitle("BitSquare (" + getUID() + ")");
|
||||
primaryStage.setTitle("BitSquare (" + APP_NAME + ")");
|
||||
|
||||
GuiceFXMLLoader.setInjector(injector);
|
||||
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(NavigationItem.MAIN.getFxmlUrl()), Localisation.getResourceBundle());
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(NavigationItem.MAIN.getFxmlUrl()));
|
||||
final Parent mainView = loader.load();
|
||||
BorderPane rootPane = new BorderPane();
|
||||
rootPane.setTop(getMenuBar());
|
||||
rootPane.setCenter(mainView);
|
||||
|
||||
final Scene scene = new Scene(rootPane, 800, 600);
|
||||
scene.getStylesheets().setAll(getClass().getResource("/io/bitsquare/gui/bitsquare.css").toExternalForm());
|
||||
final Scene scene = new Scene(rootPane, 1000, 750);
|
||||
scene.getStylesheets().setAll(getClass().getResource("/io/bitsquare/gui/bitsquare.css").toExternalForm(),
|
||||
getClass().getResource("/io/bitsquare/gui/validation.css").toExternalForm());
|
||||
|
||||
setupCloseHandlers(primaryStage, scene);
|
||||
|
||||
primaryStage.setScene(scene);
|
||||
primaryStage.setMinWidth(750);
|
||||
primaryStage.setMinHeight(500);
|
||||
primaryStage.setWidth(1000);
|
||||
primaryStage.setHeight(750);
|
||||
|
||||
primaryStage.show();
|
||||
|
||||
log.debug("Startup: stage displayed");
|
||||
Profiler.printMsgWithTime("Startup: primaryStage.show");
|
||||
}
|
||||
|
||||
private void setupCloseHandlers(Stage primaryStage, Scene scene)
|
||||
|
@ -1,36 +1,90 @@
|
||||
package io.bitsquare.di;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import io.bitsquare.locale.Localisation;
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.util.Callback;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Guice support for fxml controllers
|
||||
* Support caching. Speed up switches between UI screens.
|
||||
*/
|
||||
public class GuiceFXMLLoader extends FXMLLoader
|
||||
public class GuiceFXMLLoader
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(GuiceFXMLLoader.class);
|
||||
private static Injector injector = null;
|
||||
private FXMLLoader loader;
|
||||
private final boolean isCached;
|
||||
private final URL url;
|
||||
private Item item;
|
||||
|
||||
public static void setInjector(Injector injector)
|
||||
{
|
||||
GuiceFXMLLoader.injector = injector;
|
||||
}
|
||||
// private static ClassLoader cachingClassLoader = new CachingClassLoader(FXMLLoader.getDefaultClassLoader());
|
||||
public GuiceFXMLLoader(URL url, ResourceBundle resourceBundle)
|
||||
|
||||
// TODO maybe add more sophisticated caching strategy with removal of rarely accessed items
|
||||
private static final Map<URL, Item> cachedGUIItems = new HashMap<>();
|
||||
|
||||
public GuiceFXMLLoader(URL url)
|
||||
{
|
||||
super(url, resourceBundle);
|
||||
// might be helpful for performance, but need further profiling. has memory drawbacks
|
||||
//setClassLoader(cachingClassLoader);
|
||||
setupControllerFactory();
|
||||
this(url, true);
|
||||
}
|
||||
|
||||
private void setupControllerFactory()
|
||||
public GuiceFXMLLoader(URL url, boolean useCaching)
|
||||
{
|
||||
if (GuiceFXMLLoader.injector != null)
|
||||
this.url = url;
|
||||
|
||||
isCached = useCaching && cachedGUIItems.containsKey(url);
|
||||
|
||||
if (!isCached)
|
||||
{
|
||||
setControllerFactory(new GuiceControllerFactory(GuiceFXMLLoader.injector));
|
||||
loader = new FXMLLoader(url, Localisation.getResourceBundle());
|
||||
if (GuiceFXMLLoader.injector != null)
|
||||
loader.setControllerFactory(new GuiceControllerFactory(GuiceFXMLLoader.injector));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T load() throws java.io.IOException
|
||||
{
|
||||
if (isCached)
|
||||
{
|
||||
item = cachedGUIItems.get(url);
|
||||
log.debug("loaded from cache " + url);
|
||||
return (T) cachedGUIItems.get(url).view;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("load from disc " + url);
|
||||
T result = loader.load();
|
||||
item = new Item(result, loader.getController());
|
||||
cachedGUIItems.put(url, item);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getController()
|
||||
{
|
||||
return (T) item.controller;
|
||||
}
|
||||
|
||||
|
||||
class Item<T>
|
||||
{
|
||||
final T view;
|
||||
final T controller;
|
||||
|
||||
Item(T view, T controller)
|
||||
{
|
||||
this.view = view;
|
||||
this.controller = controller;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import io.bitsquare.gui.market.MarketController;
|
||||
import io.bitsquare.gui.orders.OrdersController;
|
||||
import io.bitsquare.gui.util.Icons;
|
||||
import io.bitsquare.gui.util.Transitions;
|
||||
import io.bitsquare.locale.Localisation;
|
||||
import io.bitsquare.msg.BootstrapListener;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.storage.Persistence;
|
||||
@ -21,7 +20,6 @@ import io.bitsquare.util.AWTSystemTray;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
@ -53,7 +51,7 @@ public class MainController implements Initializable, NavigationController
|
||||
private final ToggleGroup toggleGroup = new ToggleGroup();
|
||||
|
||||
|
||||
private ChildController childController;
|
||||
private ChildController controller;
|
||||
private ToggleButton prevToggleButton;
|
||||
private Image prevToggleButtonIcon;
|
||||
private ToggleButton buyButton, sellButton, homeButton, msgButton, ordersButton, fundsButton, settingsButton;
|
||||
@ -108,75 +106,6 @@ public class MainController implements Initializable, NavigationController
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb)
|
||||
{
|
||||
Platform.runLater(this::init);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Interface implementation: NavigationController
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@Override
|
||||
public ChildController navigateToView(NavigationItem navigationItem)
|
||||
{
|
||||
switch (navigationItem)
|
||||
{
|
||||
case HOME:
|
||||
homeButton.fire();
|
||||
break;
|
||||
case FUNDS:
|
||||
fundsButton.fire();
|
||||
break;
|
||||
case MSG:
|
||||
msgButton.fire();
|
||||
break;
|
||||
case ORDERS:
|
||||
ordersButton.fire();
|
||||
break;
|
||||
case SETTINGS:
|
||||
settingsButton.fire();
|
||||
break;
|
||||
case SELL:
|
||||
sellButton.fire();
|
||||
break;
|
||||
case BUY:
|
||||
buyButton.fire();
|
||||
break;
|
||||
}
|
||||
return childController;
|
||||
}
|
||||
|
||||
|
||||
private ChildController loadView(NavigationItem navigationItem)
|
||||
{
|
||||
if (childController != null)
|
||||
{
|
||||
childController.cleanup();
|
||||
}
|
||||
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
||||
try
|
||||
{
|
||||
final Node view = loader.load();
|
||||
contentPane.getChildren().setAll(view);
|
||||
childController = loader.getController();
|
||||
childController.setNavigationController(this);
|
||||
} catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
log.error("Loading view failed. " + navigationItem.getFxmlUrl());
|
||||
}
|
||||
return childController;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void init()
|
||||
{
|
||||
messageFacade.init(new BootstrapListener()
|
||||
{
|
||||
@ -215,6 +144,70 @@ public class MainController implements Initializable, NavigationController
|
||||
tradeManager.addTakeOfferRequestListener(this::onTakeOfferRequested);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Interface implementation: NavigationController
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@Override
|
||||
public ChildController navigateToView(NavigationItem navigationItem)
|
||||
{
|
||||
switch (navigationItem)
|
||||
{
|
||||
case HOME:
|
||||
homeButton.fire();
|
||||
break;
|
||||
case FUNDS:
|
||||
fundsButton.fire();
|
||||
break;
|
||||
case MSG:
|
||||
msgButton.fire();
|
||||
break;
|
||||
case ORDERS:
|
||||
ordersButton.fire();
|
||||
break;
|
||||
case SETTINGS:
|
||||
settingsButton.fire();
|
||||
break;
|
||||
case SELL:
|
||||
sellButton.fire();
|
||||
break;
|
||||
case BUY:
|
||||
buyButton.fire();
|
||||
break;
|
||||
}
|
||||
return controller;
|
||||
}
|
||||
|
||||
|
||||
private ChildController loadView(NavigationItem navigationItem)
|
||||
{
|
||||
if (controller != null)
|
||||
{
|
||||
controller.cleanup();
|
||||
}
|
||||
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
|
||||
try
|
||||
{
|
||||
final Node view = loader.load();
|
||||
contentPane.getChildren().setAll(view);
|
||||
controller = loader.getController();
|
||||
controller.setNavigationController(this);
|
||||
} catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
log.error("Loading view failed. " + navigationItem.getFxmlUrl());
|
||||
}
|
||||
return controller;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void initialisationDone()
|
||||
{
|
||||
addNavigation();
|
||||
@ -292,11 +285,11 @@ public class MainController implements Initializable, NavigationController
|
||||
prevToggleButtonIcon = ((ImageView) (toggleButton.getGraphic())).getImage();
|
||||
((ImageView) (toggleButton.getGraphic())).setImage(Icons.getIconImage(navigationItem.getActiveIcon()));
|
||||
|
||||
childController = loadView(navigationItem);
|
||||
controller = loadView(navigationItem);
|
||||
|
||||
if (childController instanceof MarketController)
|
||||
if (controller instanceof MarketController)
|
||||
{
|
||||
((MarketController) childController).setDirection(navigationItem == NavigationItem.BUY ? Direction.BUY : Direction.SELL);
|
||||
((MarketController) controller).setDirection(navigationItem == NavigationItem.BUY ? Direction.BUY : Direction.SELL);
|
||||
}
|
||||
|
||||
persistence.write(this, "selectedNavigationItem", navigationItem);
|
||||
|
@ -6,7 +6,6 @@ import io.bitsquare.gui.NavigationController;
|
||||
import io.bitsquare.gui.NavigationItem;
|
||||
import io.bitsquare.gui.arbitrators.profile.ArbitratorProfileController;
|
||||
import io.bitsquare.locale.LanguageUtil;
|
||||
import io.bitsquare.locale.Localisation;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.listeners.ArbitratorListener;
|
||||
import io.bitsquare.settings.Settings;
|
||||
@ -113,7 +112,7 @@ public class ArbitratorOverviewController implements Initializable, ChildControl
|
||||
arbitratorProfileController.cleanup();
|
||||
}
|
||||
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
|
||||
try
|
||||
{
|
||||
final Node view = loader.load();
|
||||
|
@ -9,7 +9,6 @@ import io.bitsquare.gui.ChildController;
|
||||
import io.bitsquare.gui.NavigationController;
|
||||
import io.bitsquare.gui.arbitrators.profile.ArbitratorProfileController;
|
||||
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
|
||||
import io.bitsquare.gui.util.BitSquareConverter;
|
||||
import io.bitsquare.gui.util.BitSquareFormatter;
|
||||
import io.bitsquare.gui.util.BitSquareValidator;
|
||||
import io.bitsquare.gui.util.ConfidenceDisplay;
|
||||
@ -475,11 +474,11 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getMessagePublicKey());
|
||||
String name = nameTextField.getText();
|
||||
|
||||
double maxTradeVolume = BitSquareConverter.stringToDouble(maxTradeVolumeTextField.getText());
|
||||
double passiveServiceFee = BitSquareConverter.stringToDouble(passiveServiceFeeTextField.getText());
|
||||
double minPassiveServiceFee = BitSquareConverter.stringToDouble(minPassiveServiceFeeTextField.getText());
|
||||
double arbitrationFee = BitSquareConverter.stringToDouble(arbitrationFeeTextField.getText());
|
||||
double minArbitrationFee = BitSquareConverter.stringToDouble(minArbitrationFeeTextField.getText());
|
||||
double maxTradeVolume = BitSquareFormatter.parseToDouble(maxTradeVolumeTextField.getText());
|
||||
double passiveServiceFee = BitSquareFormatter.parseToDouble(passiveServiceFeeTextField.getText());
|
||||
double minPassiveServiceFee = BitSquareFormatter.parseToDouble(minPassiveServiceFeeTextField.getText());
|
||||
double arbitrationFee = BitSquareFormatter.parseToDouble(arbitrationFeeTextField.getText());
|
||||
double minArbitrationFee = BitSquareFormatter.parseToDouble(minArbitrationFeeTextField.getText());
|
||||
|
||||
String webUrl = webPageTextField.getText();
|
||||
String description = descriptionTextArea.getText();
|
||||
|
@ -111,7 +111,7 @@
|
||||
-fx-fill: black;
|
||||
}
|
||||
|
||||
.table-view .table-row-cell:selected .table-row-cell:row-selection .table-row-cell:cell-selection .text {
|
||||
.table-view .table-row-cell:selected .table-row-cell:row-selection .table-row-cell:cell-selection .text {
|
||||
-fx-fill: white;
|
||||
}
|
||||
|
||||
@ -204,3 +204,9 @@
|
||||
.scroll-pane .corner {
|
||||
-fx-background-insets: 0;
|
||||
}
|
||||
|
||||
|
||||
/* validation */
|
||||
#validation-error {
|
||||
-fx-text-fill: red;
|
||||
}
|
@ -4,7 +4,6 @@ import io.bitsquare.di.GuiceFXMLLoader;
|
||||
import io.bitsquare.gui.ChildController;
|
||||
import io.bitsquare.gui.Hibernate;
|
||||
import io.bitsquare.gui.NavigationController;
|
||||
import io.bitsquare.locale.Localisation;
|
||||
import io.bitsquare.storage.Persistence;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -92,7 +91,7 @@ public class CachingTabPane extends TabPane
|
||||
{
|
||||
// load for the first time
|
||||
String fxmlView = tabInfoList.get(selectedTabIndex).url;
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(fxmlView), Localisation.getResourceBundle());
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(fxmlView));
|
||||
try
|
||||
{
|
||||
tabInfoList.get(selectedTabIndex).view = loader.load();
|
||||
|
@ -132,7 +132,7 @@ public class ValidatedTextField extends TextField
|
||||
@Override
|
||||
public void changed(ObservableValue<? extends String> ov, String t, String t1)
|
||||
{
|
||||
if (textProperty().get().length() > maxLength.get())
|
||||
if (textProperty().get() != null && textProperty().get().length() > maxLength.get())
|
||||
{
|
||||
setText(t);
|
||||
}
|
||||
@ -173,7 +173,7 @@ public class ValidatedTextField extends TextField
|
||||
@Override
|
||||
protected boolean computeValue()
|
||||
{
|
||||
return !textProperty().get().matches(mask.get());
|
||||
return (textProperty().get() != null) ? !textProperty().get().matches(mask.get()) : false;
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -189,7 +189,7 @@ public class ValidatedTextField extends TextField
|
||||
@Override
|
||||
protected boolean computeValue()
|
||||
{
|
||||
return textProperty().get().length() < minLength.get();
|
||||
return (textProperty().get() != null) ? textProperty().get().length() < minLength.get() : false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,182 @@
|
||||
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;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.effect.BlurType;
|
||||
import javafx.scene.effect.DropShadow;
|
||||
import javafx.scene.effect.Effect;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.stage.Window;
|
||||
import org.controlsfx.control.PopOver;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* TextField with validation support. Validation is executed on the Validator object.
|
||||
* In case of a invalid result we display a error message with a PopOver.
|
||||
* The position is derived from the textField or if set from the errorPopupLayoutReference object.
|
||||
* <p>
|
||||
* That class implements just what we need for the moment. It is not intended as a general purpose library class.
|
||||
*/
|
||||
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);
|
||||
|
||||
// we hold all error popups any only display the latest one
|
||||
private static final LinkedList<PopOver> allErrorPopups = new LinkedList<>();
|
||||
|
||||
private Effect invalidEffect = DEFAULT_EFFECT;
|
||||
private final BooleanProperty valid = 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;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public ValidatingTextField()
|
||||
{
|
||||
super();
|
||||
setupListeners();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void reValidate()
|
||||
{
|
||||
validate(getText());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setNumberValidator(NumberValidator numberValidator)
|
||||
{
|
||||
this.numberValidator = numberValidator;
|
||||
}
|
||||
|
||||
public void setErrorPopupLayoutReference(Region errorPopupLayoutReference)
|
||||
{
|
||||
this.errorPopupLayoutReference = errorPopupLayoutReference;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void setupListeners()
|
||||
{
|
||||
this.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
if (numberValidator != null)
|
||||
{
|
||||
if (!validateOnFocusOut)
|
||||
validate(newValue);
|
||||
else
|
||||
needsValidationOnFocusOut = true;
|
||||
}
|
||||
});
|
||||
|
||||
this.focusedProperty().addListener((ov, oldValue, newValue) -> {
|
||||
if (validateOnFocusOut && needsValidationOnFocusOut && !newValue && getScene().getWindow().isFocused())
|
||||
validate(getText());
|
||||
});
|
||||
|
||||
this.valid.addListener((ov, oldValue, newValue) -> applyEffect(newValue));
|
||||
}
|
||||
|
||||
private void validate(String input)
|
||||
{
|
||||
NumberValidator.ValidationResult validationResult = numberValidator.validate(input);
|
||||
valid.set(validationResult.isValid);
|
||||
applyErrorMessage(validationResult);
|
||||
}
|
||||
|
||||
private void applyErrorMessage(NumberValidator.ValidationResult validationResult)
|
||||
{
|
||||
if (validationResult.isValid)
|
||||
{
|
||||
if (allErrorPopups.contains(popOver))
|
||||
{
|
||||
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 (allErrorPopups.contains(popOver))
|
||||
{
|
||||
allErrorPopups.remove(popOver);
|
||||
popOver.hide();
|
||||
}
|
||||
|
||||
popOver = createErrorPopOver(validationResult.errorMessage);
|
||||
popOver.show(getScene().getWindow(), errorPopOverX, errorPopOverY);
|
||||
allErrorPopups.add(popOver);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyEffect(boolean isValid)
|
||||
{
|
||||
setEffect(isValid ? null : invalidEffect);
|
||||
}
|
||||
|
||||
private PopOver 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.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;
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ public class FundsController implements Initializable, ChildController, Navigati
|
||||
private final Persistence persistence;
|
||||
|
||||
@FXML
|
||||
private CachingTabPane tabPane;
|
||||
private CachingTabPane root;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -40,7 +40,7 @@ public class FundsController implements Initializable, ChildController, Navigati
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb)
|
||||
{
|
||||
tabPane.initialize(this, persistence, NavigationItem.DEPOSIT.getFxmlUrl(), NavigationItem.WITHDRAWAL.getFxmlUrl(), NavigationItem.TRANSACTIONS.getFxmlUrl());
|
||||
root.initialize(this, persistence, NavigationItem.DEPOSIT.getFxmlUrl(), NavigationItem.WITHDRAWAL.getFxmlUrl(), NavigationItem.TRANSACTIONS.getFxmlUrl());
|
||||
}
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ public class FundsController implements Initializable, ChildController, Navigati
|
||||
@Override
|
||||
public void cleanup()
|
||||
{
|
||||
tabPane.cleanup();
|
||||
root.cleanup();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -66,7 +66,7 @@ public class FundsController implements Initializable, ChildController, Navigati
|
||||
@Override
|
||||
public ChildController navigateToView(NavigationItem navigationItem)
|
||||
{
|
||||
return tabPane.navigateToView(navigationItem.getFxmlUrl());
|
||||
return root.navigateToView(navigationItem.getFxmlUrl());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
<?import io.bitsquare.gui.components.CachingTabPane?>
|
||||
<?import javafx.scene.control.Tab?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<CachingTabPane 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"
|
||||
xmlns="http://javafx.com/javafx/8" fx:controller="io.bitsquare.gui.funds.FundsController">
|
||||
<CachingTabPane xmlns:fx="http://javafx.com/fxml/1" fx:id="root" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
|
||||
xmlns="http://javafx.com/javafx/8" fx:controller="io.bitsquare.gui.funds.FundsController">
|
||||
|
||||
<Tab text="Deposit" closable="false"/>
|
||||
<Tab text="Withdrawal" closable="false"/>
|
||||
|
@ -19,6 +19,7 @@ import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.input.Clipboard;
|
||||
import javafx.scene.input.ClipboardContent;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Callback;
|
||||
import javax.inject.Inject;
|
||||
import org.slf4j.Logger;
|
||||
@ -31,12 +32,10 @@ public class DepositController implements Initializable, ChildController, Hibern
|
||||
private final WalletFacade walletFacade;
|
||||
private ObservableList<DepositListItem> addressList;
|
||||
|
||||
@FXML
|
||||
private TableView<DepositListItem> tableView;
|
||||
@FXML
|
||||
private TableColumn<String, DepositListItem> labelColumn, addressColumn, balanceColumn, copyColumn, confidenceColumn;
|
||||
@FXML
|
||||
private Button addNewAddressButton;
|
||||
@FXML private VBox root;
|
||||
@FXML private TableView<DepositListItem> tableView;
|
||||
@FXML private TableColumn<String, DepositListItem> labelColumn, addressColumn, balanceColumn, copyColumn, confidenceColumn;
|
||||
@FXML private Button addNewAddressButton;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -4,7 +4,7 @@
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.control.cell.PropertyValueFactory?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml/1" spacing="10" fx:controller="io.bitsquare.gui.funds.deposit.DepositController"
|
||||
<VBox fx:id="root" xmlns:fx="http://javafx.com/fxml/1" spacing="10" fx:controller="io.bitsquare.gui.funds.deposit.DepositController"
|
||||
xmlns="http://javafx.com/javafx/8">
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
|
||||
|
@ -15,6 +15,7 @@ import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Callback;
|
||||
import javax.inject.Inject;
|
||||
import org.slf4j.Logger;
|
||||
@ -27,12 +28,10 @@ public class TransactionsController implements Initializable, ChildController, H
|
||||
private final WalletFacade walletFacade;
|
||||
private ObservableList<TransactionsListItem> transactionsListItems;
|
||||
|
||||
@FXML
|
||||
private TableView<TransactionsListItem> tableView;
|
||||
@FXML
|
||||
private TableColumn<String, TransactionsListItem> dateColumn, addressColumn, amountColumn, typeColumn, confidenceColumn;
|
||||
@FXML
|
||||
private Button addNewAddressButton;
|
||||
@FXML private VBox root;
|
||||
@FXML private TableView<TransactionsListItem> tableView;
|
||||
@FXML private TableColumn<String, TransactionsListItem> dateColumn, addressColumn, amountColumn, typeColumn, confidenceColumn;
|
||||
@FXML private Button addNewAddressButton;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -4,7 +4,7 @@
|
||||
<?import javafx.scene.control.cell.PropertyValueFactory?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml/1" spacing="10" fx:controller="io.bitsquare.gui.funds.transactions.TransactionsController"
|
||||
<VBox fx:id="root" xmlns:fx="http://javafx.com/fxml/1" spacing="10" fx:controller="io.bitsquare.gui.funds.transactions.TransactionsController"
|
||||
xmlns="http://javafx.com/javafx/8">
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
|
||||
|
@ -29,6 +29,7 @@ import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.input.Clipboard;
|
||||
import javafx.scene.input.ClipboardContent;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Callback;
|
||||
import javax.inject.Inject;
|
||||
import org.controlsfx.control.action.Action;
|
||||
@ -44,14 +45,11 @@ public class WithdrawalController implements Initializable, ChildController, Hib
|
||||
private final WalletFacade walletFacade;
|
||||
private ObservableList<WithdrawalListItem> addressList;
|
||||
|
||||
@FXML
|
||||
private TableView<WithdrawalListItem> tableView;
|
||||
@FXML
|
||||
private TableColumn<String, WithdrawalListItem> labelColumn, addressColumn, balanceColumn, copyColumn, confidenceColumn;
|
||||
@FXML
|
||||
private Button addNewAddressButton;
|
||||
@FXML
|
||||
private TextField withdrawFromTextField, withdrawToTextField, amountTextField, changeAddressTextField;
|
||||
@FXML private VBox root;
|
||||
@FXML private TableView<WithdrawalListItem> tableView;
|
||||
@FXML private TableColumn<String, WithdrawalListItem> labelColumn, addressColumn, balanceColumn, copyColumn, confidenceColumn;
|
||||
@FXML private Button addNewAddressButton;
|
||||
@FXML private TextField withdrawFromTextField, withdrawToTextField, amountTextField, changeAddressTextField;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -4,7 +4,7 @@
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.control.cell.PropertyValueFactory?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml/1" spacing="10" fx:controller="io.bitsquare.gui.funds.withdrawal.WithdrawalController" xmlns="http://javafx.com/javafx/8">
|
||||
<VBox fx:id="root" xmlns:fx="http://javafx.com/fxml/1" spacing="10" fx:controller="io.bitsquare.gui.funds.withdrawal.WithdrawalController" xmlns="http://javafx.com/javafx/8">
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
|
||||
</padding>
|
||||
|
@ -6,23 +6,18 @@ import io.bitsquare.gui.ChildController;
|
||||
import io.bitsquare.gui.NavigationController;
|
||||
import io.bitsquare.gui.NavigationItem;
|
||||
import io.bitsquare.gui.arbitrators.registration.ArbitratorRegistrationController;
|
||||
import io.bitsquare.locale.Localisation;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public class HomeController implements Initializable, ChildController, NavigationController
|
||||
{
|
||||
@FXML
|
||||
public Pane rootContainer;
|
||||
private ArbitratorRegistrationController arbitratorRegistrationController;
|
||||
|
||||
@Override
|
||||
@ -54,10 +49,11 @@ public class HomeController implements Initializable, ChildController, Navigatio
|
||||
arbitratorRegistrationController.cleanup();
|
||||
}
|
||||
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
||||
// dont use caching here, cause exc. -> need to investigate and is rarely called so no caching is better
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), false);
|
||||
try
|
||||
{
|
||||
final Node view = loader.load();
|
||||
final Parent view = loader.load();
|
||||
arbitratorRegistrationController = loader.getController();
|
||||
arbitratorRegistrationController.setNavigationController(this);
|
||||
|
||||
@ -72,7 +68,7 @@ public class HomeController implements Initializable, ChildController, Navigatio
|
||||
stage.setY(rootStage.getY() + 50);
|
||||
stage.initModality(Modality.WINDOW_MODAL);
|
||||
stage.initOwner(rootStage);
|
||||
Scene scene = new Scene((Parent) view, 800, 600);
|
||||
Scene scene = new Scene(view, 800, 600);
|
||||
stage.setScene(scene);
|
||||
stage.show();
|
||||
|
||||
|
@ -5,16 +5,15 @@ 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.locale.Localisation;
|
||||
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;
|
||||
import javafx.scene.layout.Pane;
|
||||
|
||||
public class MarketController implements Initializable, NavigationController, ChildController
|
||||
{
|
||||
@ -52,10 +51,10 @@ public class MarketController implements Initializable, NavigationController, Ch
|
||||
return null;
|
||||
}
|
||||
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
|
||||
try
|
||||
{
|
||||
final Pane view = loader.load();
|
||||
final Parent view = loader.load();
|
||||
ChildController childController = loader.getController();
|
||||
childController.setNavigationController(this);
|
||||
|
||||
|
@ -9,12 +9,15 @@ import io.bitsquare.gui.ChildController;
|
||||
import io.bitsquare.gui.Hibernate;
|
||||
import io.bitsquare.gui.NavigationController;
|
||||
import io.bitsquare.gui.NavigationItem;
|
||||
import io.bitsquare.gui.components.ValidatingTextField;
|
||||
import io.bitsquare.gui.components.btc.AddressTextField;
|
||||
import io.bitsquare.gui.components.btc.BalanceTextField;
|
||||
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
|
||||
import io.bitsquare.gui.popups.Popups;
|
||||
import io.bitsquare.gui.util.BitSquareConverter;
|
||||
import io.bitsquare.gui.util.BitSquareFormatter;
|
||||
import io.bitsquare.gui.util.BtcValidator;
|
||||
import io.bitsquare.gui.util.FiatValidator;
|
||||
import io.bitsquare.gui.util.ValidationHelper;
|
||||
import io.bitsquare.locale.Localisation;
|
||||
import io.bitsquare.settings.Settings;
|
||||
import io.bitsquare.trade.Direction;
|
||||
@ -36,6 +39,7 @@ import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TabPane;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.Region;
|
||||
import javax.inject.Inject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -64,7 +68,7 @@ class ViewModel
|
||||
final StringProperty acceptedLanguages = new SimpleStringProperty();
|
||||
final StringProperty transactionId = new SimpleStringProperty();
|
||||
final BooleanProperty isOfferPlacedScreen = new SimpleBooleanProperty();
|
||||
final BooleanProperty isPlaceOfferButtonDisabled = new SimpleBooleanProperty();
|
||||
final BooleanProperty isPlaceOfferButtonDisabled = new SimpleBooleanProperty(false);
|
||||
}
|
||||
|
||||
public class CreateOfferController implements Initializable, ChildController, Hibernate
|
||||
@ -74,33 +78,34 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||
private NavigationController navigationController;
|
||||
private final TradeManager tradeManager;
|
||||
private final WalletFacade walletFacade;
|
||||
private final ViewModel viewModel = new ViewModel();
|
||||
final ViewModel viewModel = new ViewModel();
|
||||
private final double collateral;
|
||||
private Direction direction;
|
||||
|
||||
@FXML private AnchorPane rootContainer;
|
||||
@FXML private Label buyLabel, confirmationLabel, txTitleLabel, collateralLabel;
|
||||
@FXML private TextField volumeTextField, amountTextField, priceTextField, totalsTextField;
|
||||
|
||||
@FXML private ValidatingTextField amountTextField, minAmountTextField, priceTextField, volumeTextField;
|
||||
@FXML private Button placeOfferButton, closeButton;
|
||||
@FXML private TextField collateralTextField, minAmountTextField, bankAccountTypeTextField, bankAccountCurrencyTextField, bankAccountCountyTextField, acceptedCountriesTextField, acceptedLanguagesTextField,
|
||||
@FXML private TextField totalsTextField, collateralTextField, bankAccountTypeTextField, bankAccountCurrencyTextField, bankAccountCountyTextField, acceptedCountriesTextField, acceptedLanguagesTextField,
|
||||
feeLabel, transactionIdTextField;
|
||||
@FXML private ConfidenceProgressIndicator progressIndicator;
|
||||
@FXML private AddressTextField addressTextField;
|
||||
@FXML private BalanceTextField balanceTextField;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private CreateOfferController(TradeManager tradeManager, WalletFacade walletFacade, Settings settings, User user)
|
||||
CreateOfferController(TradeManager tradeManager, WalletFacade walletFacade, Settings settings, User user)
|
||||
{
|
||||
this.tradeManager = tradeManager;
|
||||
this.walletFacade = walletFacade;
|
||||
|
||||
this.collateral = settings.getCollateral();
|
||||
|
||||
viewModel.collateralLabel.set("Collateral (" + BitSquareFormatter.formatCollateralPercent(collateral) + "):");
|
||||
BankAccount bankAccount = user.getCurrentBankAccount();
|
||||
if (bankAccount != null)
|
||||
{
|
||||
@ -126,20 +131,6 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||
viewModel.amount.set(BitSquareFormatter.formatCoin(orderBookFilter.getAmount()));
|
||||
viewModel.minAmount.set(BitSquareFormatter.formatCoin(orderBookFilter.getAmount()));
|
||||
viewModel.price.set(BitSquareFormatter.formatPrice(orderBookFilter.getPrice()));
|
||||
viewModel.collateralLabel.set("Collateral (" + BitSquareFormatter.formatCollateralPercent(collateral) + "):");
|
||||
|
||||
//TODO just for dev testing
|
||||
if (BitSquare.fillFormsWithDummyData)
|
||||
{
|
||||
if (orderBookFilter.getAmount() == null)
|
||||
{
|
||||
amountTextField.setText("1");
|
||||
minAmountTextField.setText("0.1");
|
||||
}
|
||||
|
||||
if (orderBookFilter.getPrice() == 0)
|
||||
priceTextField.setText("" + (int) (499 - new Random().nextDouble() * 1000 / 100));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -150,15 +141,34 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb)
|
||||
{
|
||||
AddressEntry addressEntry = walletFacade.getUnusedTradeAddressInfo();
|
||||
addressTextField.setAddress(addressEntry.getAddress().toString());
|
||||
setupBindings();
|
||||
setupValidation();
|
||||
|
||||
balanceTextField.setAddress(addressEntry.getAddress());
|
||||
balanceTextField.setWalletFacade(walletFacade);
|
||||
//TODO
|
||||
if (walletFacade.getWallet() != null)
|
||||
{
|
||||
AddressEntry addressEntry = walletFacade.getUnusedTradeAddressInfo();
|
||||
addressTextField.setAddress(addressEntry.getAddress().toString());
|
||||
|
||||
balanceTextField.setAddress(addressEntry.getAddress());
|
||||
balanceTextField.setWalletFacade(walletFacade);
|
||||
}
|
||||
|
||||
|
||||
//TODO just for dev testing
|
||||
if (BitSquare.fillFormsWithDummyData)
|
||||
{
|
||||
amountTextField.setText("1");
|
||||
minAmountTextField.setText("0.1");
|
||||
priceTextField.setText("" + (int) (499 - new Random().nextDouble() * 1000 / 100));
|
||||
}
|
||||
}
|
||||
|
||||
private void setupBindings()
|
||||
{
|
||||
// setup bindings
|
||||
DoubleBinding amountBinding = createDoubleBinding(() -> BitSquareConverter.stringToDouble(viewModel.amount.get()), viewModel.amount);
|
||||
DoubleBinding priceBinding = createDoubleBinding(() -> BitSquareConverter.stringToDouble(viewModel.price.get()), viewModel.price);
|
||||
DoubleBinding amountBinding = createDoubleBinding(() -> BitSquareFormatter.parseToDouble(viewModel.amount.get()), viewModel.amount);
|
||||
DoubleBinding priceBinding = createDoubleBinding(() -> BitSquareFormatter.parseToDouble(viewModel.price.get()), viewModel.price);
|
||||
|
||||
viewModel.volume.bind(createStringBinding(() -> BitSquareFormatter.formatVolume(amountBinding.get() * priceBinding.get()), amountBinding, priceBinding));
|
||||
viewModel.collateral.bind(createStringBinding(() -> BitSquareFormatter.formatCollateralAsBtc(viewModel.amount.get(), collateral), amountBinding));
|
||||
@ -185,7 +195,6 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||
transactionIdTextField.textProperty().bind(viewModel.transactionId);
|
||||
|
||||
placeOfferButton.visibleProperty().bind(viewModel.isOfferPlacedScreen.not());
|
||||
placeOfferButton.disableProperty().bind(viewModel.isPlaceOfferButtonDisabled);
|
||||
progressIndicator.visibleProperty().bind(viewModel.isOfferPlacedScreen);
|
||||
confirmationLabel.visibleProperty().bind(viewModel.isOfferPlacedScreen);
|
||||
txTitleLabel.visibleProperty().bind(viewModel.isOfferPlacedScreen);
|
||||
@ -193,6 +202,25 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||
closeButton.visibleProperty().bind(viewModel.isOfferPlacedScreen);
|
||||
}
|
||||
|
||||
private void setupValidation()
|
||||
{
|
||||
BtcValidator amountValidator = new BtcValidator();
|
||||
amountTextField.setNumberValidator(amountValidator);
|
||||
amountTextField.setErrorPopupLayoutReference((Region) amountTextField.getParent());
|
||||
priceTextField.setNumberValidator(new FiatValidator());
|
||||
priceTextField.setErrorPopupLayoutReference((Region) amountTextField.getParent());
|
||||
BtcValidator minAmountValidator = new BtcValidator();
|
||||
minAmountTextField.setNumberValidator(minAmountValidator);
|
||||
|
||||
ValidationHelper.setupMinAmountInRangeOfAmountValidation(amountTextField,
|
||||
minAmountTextField,
|
||||
viewModel.amount,
|
||||
viewModel.minAmount,
|
||||
amountValidator,
|
||||
minAmountValidator);
|
||||
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Interface implementation: ChildController
|
||||
@ -229,27 +257,24 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI Handlers
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@FXML
|
||||
public void onPlaceOffer()
|
||||
{
|
||||
if (inputsValid())
|
||||
{
|
||||
viewModel.isPlaceOfferButtonDisabled.set(true);
|
||||
viewModel.isPlaceOfferButtonDisabled.set(true);
|
||||
|
||||
tradeManager.requestPlaceOffer(direction,
|
||||
BitSquareConverter.stringToDouble(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);
|
||||
});
|
||||
}
|
||||
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
|
||||
@ -260,48 +285,5 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||
|
||||
navigationController.navigateToView(NavigationItem.ORDER_BOOK);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private boolean inputsValid()
|
||||
{
|
||||
//TODO
|
||||
/* boolean inputFieldsValid;
|
||||
double amount = BitSquareConverter.stringToDouble(viewModel.amount.get());
|
||||
double minAmount = BitSquareConverter.stringToDouble(viewModel.minAmount.get());
|
||||
double price = BitSquareConverter.stringToDouble(viewModel.price.get());
|
||||
|
||||
inputFieldsValid = price > 0 &&
|
||||
amount > 0 &&
|
||||
minAmount > 0 &&
|
||||
minAmount <= amount/* &&
|
||||
viewModel.collateral >= settings.getMinCollateral() &&
|
||||
viewModel.collateral <= settings.getMaxCollateral()*/ /*;
|
||||
|
||||
if (!inputFieldsValid)
|
||||
{
|
||||
Popups.openWarningPopup("Invalid input", "Your input is invalid");
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
/* Arbitrator arbitrator = settings.getRandomArbitrator(getAmountAsCoin());
|
||||
if (arbitrator == null)
|
||||
{
|
||||
Popups.openWarningPopup("No arbitrator available", "No arbitrator from your arbitrator list does match the collateral and amount value.");
|
||||
return false;
|
||||
}*/
|
||||
/*
|
||||
if (user.getCurrentBankAccount() == null)
|
||||
{
|
||||
log.error("Must never happen!");
|
||||
Popups.openWarningPopup("No bank account selected", "No bank account selected.");
|
||||
return false;
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
<?import io.bitsquare.gui.components.btc.AddressTextField?>
|
||||
<?import io.bitsquare.gui.components.btc.BalanceTextField?>
|
||||
<?import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator?>
|
||||
<?import io.bitsquare.gui.components.ValidatingTextField?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
@ -16,16 +17,16 @@
|
||||
<Label fx:id="buyLabel" GridPane.rowIndex="1"/>
|
||||
|
||||
<HBox spacing="5" GridPane.rowIndex="1" GridPane.columnIndex="1" GridPane.hgrow="NEVER" alignment="CENTER_LEFT">
|
||||
<TextField fx:id="amountTextField" prefWidth="70.0" alignment="CENTER_RIGHT"/>
|
||||
<ValidatingTextField fx:id="amountTextField" prefWidth="70.0" alignment="CENTER_RIGHT"/>
|
||||
<Label text="BTC for:"/>
|
||||
<TextField fx:id="priceTextField" prefWidth="70.0" alignment="CENTER_RIGHT"/>
|
||||
<ValidatingTextField fx:id="priceTextField" prefWidth="70.0" alignment="CENTER_RIGHT"/>
|
||||
<Label text="EUR ="/>
|
||||
<TextField fx:id="volumeTextField" prefWidth="70.0" alignment="CENTER_RIGHT" editable="false"/>
|
||||
<ValidatingTextField fx:id="volumeTextField" prefWidth="70.0" alignment="CENTER_RIGHT" editable="false"/>
|
||||
<Label text="EUR in total"/>
|
||||
</HBox>
|
||||
|
||||
<Label text="Min. Amount (BTC):" GridPane.rowIndex="2"/>
|
||||
<TextField fx:id="minAmountTextField" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
|
||||
<ValidatingTextField fx:id="minAmountTextField" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
|
||||
|
||||
<Label fx:id="collateralLabel" text="Collateral:" GridPane.rowIndex="3"/>
|
||||
<TextField fx:id="collateralTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="3"/>
|
||||
|
@ -14,7 +14,6 @@ import io.bitsquare.gui.NavigationItem;
|
||||
import io.bitsquare.gui.market.createOffer.CreateOfferController;
|
||||
import io.bitsquare.gui.market.trade.TakerOfferController;
|
||||
import io.bitsquare.gui.popups.Popups;
|
||||
import io.bitsquare.gui.util.BitSquareConverter;
|
||||
import io.bitsquare.gui.util.BitSquareFormatter;
|
||||
import io.bitsquare.gui.util.Icons;
|
||||
import io.bitsquare.locale.Country;
|
||||
@ -564,7 +563,7 @@ public class OrderBookController implements Initializable, ChildController
|
||||
} catch (ParseException e)
|
||||
{
|
||||
amount.setText(oldValue);
|
||||
d = BitSquareConverter.stringToDouble(oldValue);
|
||||
d = BitSquareFormatter.parseToDouble(oldValue);
|
||||
}
|
||||
}
|
||||
return d;
|
||||
|
@ -9,7 +9,6 @@ import io.bitsquare.gui.NavigationController;
|
||||
import io.bitsquare.gui.NavigationItem;
|
||||
import io.bitsquare.gui.components.ValidatedTextField;
|
||||
import io.bitsquare.gui.popups.Popups;
|
||||
import io.bitsquare.gui.util.BitSquareConverter;
|
||||
import io.bitsquare.gui.util.BitSquareFormatter;
|
||||
import io.bitsquare.gui.util.BitSquareValidator;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
@ -290,7 +289,7 @@ public class TakerOfferController implements Initializable, ChildController
|
||||
// values
|
||||
private double getAmountAsDouble()
|
||||
{
|
||||
return BitSquareConverter.stringToDouble(getAmountString());
|
||||
return BitSquareFormatter.parseToDouble(getAmountString());
|
||||
}
|
||||
|
||||
private Coin getAmountInSatoshis()
|
||||
|
@ -4,7 +4,7 @@
|
||||
<?import javafx.scene.control.Tab?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<CachingTabPane 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"
|
||||
xmlns="http://javafx.com/javafx/8" fx:controller="io.bitsquare.gui.orders.OrdersController">
|
||||
xmlns="http://javafx.com/javafx/8" fx:controller="io.bitsquare.gui.orders.OrdersController">
|
||||
|
||||
<Tab text="Open offers" closable="false"/>
|
||||
<Tab text="Pending trades" closable="false"/>
|
||||
|
@ -54,6 +54,7 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||
private List<String> regionList;
|
||||
private ObservableList<Arbitrator> arbitratorList;
|
||||
|
||||
@FXML private TabPane root;
|
||||
@FXML
|
||||
private ListView<Locale> languagesListView;
|
||||
@FXML
|
||||
@ -133,7 +134,6 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||
addMockArbitrator();
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private void addMockArbitrator()
|
||||
{
|
||||
if (settings.getAcceptedArbitrators().isEmpty())
|
||||
@ -204,7 +204,7 @@ public class SettingsController implements Initializable, ChildController, Navig
|
||||
childController.cleanup();
|
||||
}
|
||||
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()), Localisation.getResourceBundle());
|
||||
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl()));
|
||||
try
|
||||
{
|
||||
final Node view = loader.load();
|
||||
|
@ -3,7 +3,7 @@
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<TabPane xmlns:fx="http://javafx.com/fxml/1" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
|
||||
<TabPane fx:id="root" xmlns:fx="http://javafx.com/fxml/1" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
|
||||
xmlns="http://javafx.com/javafx/8" fx:controller="io.bitsquare.gui.settings.SettingsController">
|
||||
|
||||
<Tab text="General" closable="false">
|
||||
|
@ -1,25 +0,0 @@
|
||||
package io.bitsquare.gui.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class BitSquareConverter
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(BitSquareConverter.class);
|
||||
|
||||
/**
|
||||
* @param input String to be converted to a double. Both decimal points "." and "," are supported. Thousands separator is not supported.
|
||||
* @return Returns a double value. Any invalid value returns Double.NEGATIVE_INFINITY.
|
||||
*/
|
||||
public static double stringToDouble(String input)
|
||||
{
|
||||
try
|
||||
{
|
||||
input = input.replace(",", ".");
|
||||
return Double.parseDouble(input);
|
||||
} catch (NumberFormatException | NullPointerException e)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,9 @@ import java.util.Locale;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
//TODO cleanup...
|
||||
public class BitSquareFormatter
|
||||
{
|
||||
@ -45,26 +48,25 @@ public class BitSquareFormatter
|
||||
*/
|
||||
public static Coin parseToCoin(String input)
|
||||
{
|
||||
Coin result;
|
||||
try
|
||||
{
|
||||
input = input.replace(",", ".");
|
||||
Double.parseDouble(input);
|
||||
|
||||
} catch (NumberFormatException | NullPointerException e)
|
||||
result = Coin.parseCoin(input);
|
||||
} catch (Exception e)
|
||||
{
|
||||
log.warn("Exception at parseBtcToCoin: " + e.toString());
|
||||
input = "0";
|
||||
//log.warn("Exception at parseBtcToCoin: " + e.toString());
|
||||
result = Coin.ZERO;
|
||||
}
|
||||
return Coin.parseCoin(input);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// FIAT
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
public static String formatPrice(double price)
|
||||
{
|
||||
return formatDouble(price);
|
||||
@ -85,13 +87,31 @@ public class BitSquareFormatter
|
||||
// Other
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @param input String to be converted to a double. Both decimal points "." and "," are supported. Thousands separator is not supported.
|
||||
* @return Returns a double value. Any invalid value returns Double.NEGATIVE_INFINITY.
|
||||
*/
|
||||
public static double parseToDouble(String input)
|
||||
{
|
||||
try
|
||||
{
|
||||
checkNotNull(input);
|
||||
checkArgument(input.length() > 0);
|
||||
input = input.replace(",", ".").trim();
|
||||
return Double.parseDouble(input);
|
||||
} catch (Exception e)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static String formatCollateralAsBtc(String amount, double collateral)
|
||||
{
|
||||
Coin amountAsCoin = BitSquareFormatter.parseToCoin(amount);
|
||||
Coin collateralAsCoin = amountAsCoin.divide((long) (1d / collateral));
|
||||
return formatCoinWithCode(collateralAsCoin);
|
||||
}
|
||||
|
||||
|
||||
public static String formatTotalsAsBtc(String amount, double collateral, Coin fees)
|
||||
{
|
||||
Coin amountAsCoin = BitSquareFormatter.parseToCoin(amount);
|
||||
@ -99,7 +119,7 @@ public class BitSquareFormatter
|
||||
Coin totals = collateralAsCoin.add(fees);
|
||||
return formatCoinWithCode(totals);
|
||||
}
|
||||
|
||||
|
||||
public static String formatDirection(Direction direction, boolean allUpperCase)
|
||||
{
|
||||
String result = (direction == Direction.BUY) ? "Buy" : "Sell";
|
||||
|
@ -9,7 +9,8 @@ import javafx.scene.effect.DropShadow;
|
||||
import javafx.scene.effect.Effect;
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
//TODO to be removed
|
||||
@Deprecated
|
||||
public class BitSquareValidator
|
||||
{
|
||||
private static final Effect invalidEffect = new DropShadow(BlurType.GAUSSIAN, Color.RED, 4, 0.0, 0, 0);
|
||||
|
81
src/main/java/io/bitsquare/gui/util/BtcValidator.java
Normal file
81
src/main/java/io/bitsquare/gui/util/BtcValidator.java
Normal file
@ -0,0 +1,81 @@
|
||||
package io.bitsquare.gui.util;
|
||||
|
||||
import com.google.bitcoin.core.NetworkParameters;
|
||||
import java.math.BigDecimal;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* BtcValidator for validating BTC values.
|
||||
* <p>
|
||||
* That class implements just what we need for the moment. It is not intended as a general purpose library class.
|
||||
*/
|
||||
public class BtcValidator extends NumberValidator
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(BtcValidator.class);
|
||||
private ValidationResult overriddenValidationResult;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public ValidationResult validate(String input)
|
||||
{
|
||||
ValidationResult result = validateIfNotEmpty(input);
|
||||
if (result.isValid)
|
||||
{
|
||||
input = cleanInput(input);
|
||||
result = validateIfNumber(input);
|
||||
}
|
||||
|
||||
if (result.isValid)
|
||||
{
|
||||
result = validateIfNotZero(input)
|
||||
.and(validateIfNotNegative(input))
|
||||
.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...
|
||||
*
|
||||
* @param overriddenValidationResult
|
||||
*/
|
||||
public void overrideResult(ValidationResult overriddenValidationResult)
|
||||
{
|
||||
this.overriddenValidationResult = overriddenValidationResult;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected ValidationResult validateIfNotFractionalBtcValue(String input)
|
||||
{
|
||||
BigDecimal bd = new BigDecimal(input);
|
||||
final BigDecimal satoshis = bd.movePointRight(8);
|
||||
if (satoshis.scale() > 0)
|
||||
return new ValidationResult(false, "Input results in a Bitcoin value with a fraction of the smallest unit (Satoshi).", ErrorType.FRACTIONAL_SATOSHI);
|
||||
else
|
||||
return new ValidationResult(true);
|
||||
}
|
||||
|
||||
protected ValidationResult validateIfNotExceedsMaxBtcValue(String input)
|
||||
{
|
||||
BigDecimal bd = new BigDecimal(input);
|
||||
final BigDecimal satoshis = bd.movePointRight(8);
|
||||
if (satoshis.longValue() > NetworkParameters.MAX_MONEY.longValue())
|
||||
return new ValidationResult(false, "Input larger as maximum possible Bitcoin value is not allowed.", ErrorType.EXCEEDS_MAX_BTC_VALUE);
|
||||
else
|
||||
return new ValidationResult(true);
|
||||
}
|
||||
}
|
67
src/main/java/io/bitsquare/gui/util/FiatValidator.java
Normal file
67
src/main/java/io/bitsquare/gui/util/FiatValidator.java
Normal file
@ -0,0 +1,67 @@
|
||||
package io.bitsquare.gui.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* FiatNumberValidator for validating fiat values.
|
||||
* <p>
|
||||
* That class implements just what we need for the moment. It is not intended as a general purpose library class.
|
||||
*/
|
||||
public class FiatValidator extends NumberValidator
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(FiatValidator.class);
|
||||
|
||||
//TODO Find appropriate values - depends on currencies
|
||||
public static final double MIN_FIAT_VALUE = 0.01; // usually a cent is the smallest currency unit
|
||||
public static final double MAX_FIAT_VALUE = 1000000;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public ValidationResult validate(String input)
|
||||
{
|
||||
ValidationResult result = validateIfNotEmpty(input);
|
||||
if (result.isValid)
|
||||
{
|
||||
input = cleanInput(input);
|
||||
result = validateIfNumber(input);
|
||||
}
|
||||
|
||||
if (result.isValid)
|
||||
{
|
||||
result = validateIfNotZero(input)
|
||||
.and(validateIfNotNegative(input))
|
||||
.and(validateIfNotExceedsMinFiatValue(input))
|
||||
.and(validateIfNotExceedsMaxFiatValue(input));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected ValidationResult validateIfNotExceedsMinFiatValue(String input)
|
||||
{
|
||||
double d = Double.parseDouble(input);
|
||||
if (d < MIN_FIAT_VALUE)
|
||||
return new ValidationResult(false, "Input smaller as minimum possible Fiat value is not allowed..", ErrorType.UNDERCUT_MIN_FIAT_VALUE);
|
||||
else
|
||||
return new ValidationResult(true);
|
||||
}
|
||||
|
||||
protected ValidationResult validateIfNotExceedsMaxFiatValue(String input)
|
||||
{
|
||||
double d = Double.parseDouble(input);
|
||||
if (d > MAX_FIAT_VALUE)
|
||||
return new ValidationResult(false, "Input larger as maximum possible Fiat value is not allowed.", ErrorType.EXCEEDS_MAX_FIAT_VALUE);
|
||||
else
|
||||
return new ValidationResult(true);
|
||||
}
|
||||
}
|
127
src/main/java/io/bitsquare/gui/util/NumberValidator.java
Normal file
127
src/main/java/io/bitsquare/gui/util/NumberValidator.java
Normal file
@ -0,0 +1,127 @@
|
||||
package io.bitsquare.gui.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* NumberValidator for validating basic number values.
|
||||
* Localisation not supported at the moment
|
||||
* The decimal mark can be either "." or ",". Thousand separators are not supported yet, but might be added alter with Local support.
|
||||
* <p>
|
||||
* That class implements just what we need for the moment. It is not intended as a general purpose library class.
|
||||
*/
|
||||
public abstract class NumberValidator
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(NumberValidator.class);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Abstract methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
abstract public ValidationResult validate(String input);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
protected ValidationResult validateIfNotEmpty(String input)
|
||||
{
|
||||
if (input == null || input.length() == 0)
|
||||
return new ValidationResult(false, "Empty input is not allowed.", ErrorType.EMPTY_INPUT);
|
||||
else
|
||||
return new ValidationResult(true);
|
||||
}
|
||||
|
||||
protected String cleanInput(String input)
|
||||
{
|
||||
return input.replace(",", ".").trim();
|
||||
}
|
||||
|
||||
protected ValidationResult validateIfNumber(String input)
|
||||
{
|
||||
try
|
||||
{
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
Double.parseDouble(input);
|
||||
return new ValidationResult(true);
|
||||
} catch (Exception e)
|
||||
{
|
||||
return new ValidationResult(false, "Input is not a valid number.", ErrorType.NOT_A_NUMBER);
|
||||
}
|
||||
}
|
||||
|
||||
protected ValidationResult validateIfNotZero(String input)
|
||||
{
|
||||
if (Double.parseDouble(input) == 0)
|
||||
return new ValidationResult(false, "Input of 0 is not allowed.", ErrorType.ZERO_NUMBER);
|
||||
else
|
||||
return new ValidationResult(true);
|
||||
}
|
||||
|
||||
protected ValidationResult validateIfNotNegative(String input)
|
||||
{
|
||||
if (Double.parseDouble(input) < 0)
|
||||
return new ValidationResult(false, "A negative value is not allowed.", ErrorType.NEGATIVE_NUMBER);
|
||||
else
|
||||
return new ValidationResult(true);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ErrorType
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public enum ErrorType
|
||||
{
|
||||
EMPTY_INPUT,
|
||||
NOT_A_NUMBER,
|
||||
ZERO_NUMBER,
|
||||
NEGATIVE_NUMBER,
|
||||
FRACTIONAL_SATOSHI,
|
||||
EXCEEDS_MAX_FIAT_VALUE, UNDERCUT_MIN_FIAT_VALUE, AMOUNT_LESS_THAN_MIN_AMOUNT, MIN_AMOUNT_LARGER_THAN_MIN_AMOUNT, EXCEEDS_MAX_BTC_VALUE
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ValidationResult
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static class ValidationResult
|
||||
{
|
||||
public final boolean isValid;
|
||||
public final String errorMessage;
|
||||
public final ErrorType errorType;
|
||||
|
||||
public ValidationResult(boolean isValid, String errorMessage, ErrorType errorType)
|
||||
{
|
||||
this.isValid = isValid;
|
||||
this.errorMessage = errorMessage;
|
||||
this.errorType = errorType;
|
||||
}
|
||||
|
||||
ValidationResult(boolean isValid)
|
||||
{
|
||||
this(isValid, null, null);
|
||||
}
|
||||
|
||||
public ValidationResult and(ValidationResult next)
|
||||
{
|
||||
if (this.isValid)
|
||||
return next;
|
||||
else
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "ValidationResult{" +
|
||||
"isValid=" + isValid +
|
||||
", errorMessage='" + errorMessage + '\'' +
|
||||
", errorType=" + errorType +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
50
src/main/java/io/bitsquare/gui/util/Profiler.java
Normal file
50
src/main/java/io/bitsquare/gui/util/Profiler.java
Normal file
@ -0,0 +1,50 @@
|
||||
package io.bitsquare.gui.util;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javafx.animation.AnimationTimer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Profiler
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(Profiler.class);
|
||||
|
||||
private static final Stopwatch globalStopwatch = Stopwatch.createStarted();
|
||||
private static final ThreadLocal<Stopwatch> threadStopwatch = ThreadLocal.withInitial(Stopwatch::createStarted);
|
||||
private static final ThreadLocal<Long> last = ThreadLocal.withInitial(() -> 0L);
|
||||
private static long lastCurrentTimeMillis = System.currentTimeMillis();
|
||||
private static long lastFPSTime = System.currentTimeMillis();
|
||||
private static long counter = 0;
|
||||
|
||||
public static void printMsgWithTime(String msg)
|
||||
{
|
||||
final long elapsed = threadStopwatch.get().elapsed(TimeUnit.MILLISECONDS);
|
||||
log.trace("Msg: {} elapsed: {}ms / total time:[globalStopwatch: {}ms / threadStopwatch: {}ms / currentTimeMillis: {}ms]",
|
||||
msg,
|
||||
elapsed - last.get(),
|
||||
globalStopwatch.elapsed(TimeUnit.MILLISECONDS),
|
||||
elapsed,
|
||||
System.currentTimeMillis() - lastCurrentTimeMillis);
|
||||
lastCurrentTimeMillis = System.currentTimeMillis();
|
||||
last.set(elapsed);
|
||||
}
|
||||
|
||||
public static void init()
|
||||
{
|
||||
AnimationTimer fpsTimer = new AnimationTimer()
|
||||
{
|
||||
@Override
|
||||
public void handle(long l)
|
||||
{
|
||||
counter++;
|
||||
long elapsed = (System.currentTimeMillis() - lastFPSTime);
|
||||
if (elapsed > 19)
|
||||
log.trace("FPS: elapsed: {}ms / FPS total counter: {}", elapsed, counter);
|
||||
|
||||
lastFPSTime = System.currentTimeMillis();
|
||||
}
|
||||
};
|
||||
fpsTimer.start();
|
||||
}
|
||||
}
|
97
src/main/java/io/bitsquare/gui/util/ValidationHelper.java
Normal file
97
src/main/java/io/bitsquare/gui/util/ValidationHelper.java
Normal file
@ -0,0 +1,97 @@
|
||||
package io.bitsquare.gui.util;
|
||||
|
||||
import io.bitsquare.gui.components.ValidatingTextField;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.scene.control.TextField;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Helper class for setting up the validation and dependencies for minAmount and Amount.
|
||||
* TODO Might be improved but does the job for now...
|
||||
*/
|
||||
public class ValidationHelper
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(ValidationHelper.class);
|
||||
|
||||
/**
|
||||
* Handles validation between minAmount and amount fields
|
||||
*/
|
||||
public static void setupMinAmountInRangeOfAmountValidation(ValidatingTextField amountTextField,
|
||||
ValidatingTextField minAmountTextField,
|
||||
StringProperty amount,
|
||||
StringProperty minAmount,
|
||||
BtcValidator amountValidator,
|
||||
BtcValidator minAmountValidator)
|
||||
{
|
||||
|
||||
|
||||
amountTextField.focusedProperty().addListener((ov, oldValue, newValue) -> {
|
||||
// only on focus out and ignore focus loss from window
|
||||
if (!newValue && amountTextField.getScene().getWindow().isFocused())
|
||||
validateMinAmount(amountTextField,
|
||||
minAmountTextField,
|
||||
amount,
|
||||
minAmount,
|
||||
amountValidator,
|
||||
minAmountValidator,
|
||||
amountTextField);
|
||||
});
|
||||
|
||||
minAmountTextField.focusedProperty().addListener((ov, oldValue, newValue) -> {
|
||||
// only on focus out and ignore focus loss from window
|
||||
if (!newValue && minAmountTextField.getScene().getWindow().isFocused())
|
||||
validateMinAmount(amountTextField,
|
||||
minAmountTextField,
|
||||
amount,
|
||||
minAmount,
|
||||
amountValidator,
|
||||
minAmountValidator,
|
||||
minAmountTextField);
|
||||
});
|
||||
}
|
||||
|
||||
private static void validateMinAmount(ValidatingTextField amountTextField,
|
||||
ValidatingTextField minAmountTextField,
|
||||
StringProperty amount,
|
||||
StringProperty minAmount,
|
||||
BtcValidator amountValidator,
|
||||
BtcValidator minAmountValidator,
|
||||
TextField currentTextField)
|
||||
{
|
||||
amountValidator.overrideResult(null);
|
||||
if (!amountValidator.validate(amount.get()).isValid)
|
||||
return;
|
||||
|
||||
minAmountValidator.overrideResult(null);
|
||||
if (!minAmountValidator.validate(minAmount.get()).isValid)
|
||||
return;
|
||||
|
||||
if (currentTextField == amountTextField)
|
||||
{
|
||||
if (Double.parseDouble(amount.get()) < Double.parseDouble(minAmount.get()))
|
||||
{
|
||||
amountValidator.overrideResult(new NumberValidator.ValidationResult(false, "Amount cannot be smaller than minimum amount.", NumberValidator.ErrorType.AMOUNT_LESS_THAN_MIN_AMOUNT));
|
||||
amountTextField.reValidate();
|
||||
}
|
||||
else
|
||||
{
|
||||
amountValidator.overrideResult(null);
|
||||
minAmountTextField.reValidate();
|
||||
}
|
||||
}
|
||||
else if (currentTextField == minAmountTextField)
|
||||
{
|
||||
if (Double.parseDouble(minAmount.get()) > Double.parseDouble(amount.get()))
|
||||
{
|
||||
minAmountValidator.overrideResult(new NumberValidator.ValidationResult(false, "Minimum amount cannot be larger than amount.", NumberValidator.ErrorType.MIN_AMOUNT_LARGER_THAN_MIN_AMOUNT));
|
||||
minAmountTextField.reValidate();
|
||||
}
|
||||
else
|
||||
{
|
||||
minAmountValidator.overrideResult(null);
|
||||
amountTextField.reValidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
22
src/main/java/io/bitsquare/gui/validation.css
Normal file
22
src/main/java/io/bitsquare/gui/validation.css
Normal file
@ -0,0 +1,22 @@
|
||||
.text-field.validation_error, .text-area.validation_error .content, .date-picker.validation_error > .text-field {
|
||||
-fx-effect: innershadow(three-pass-box, red, 12 , 0.5, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
#error-msg-item .label {
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
|
||||
#error-msg-item:focused {
|
||||
-fx-background-color: #B80000;
|
||||
}
|
||||
|
||||
#error-msg-item:focused .label {
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
|
||||
#error-msg {
|
||||
-fx-background-color: #B80000;
|
||||
-fx-padding: 0;
|
||||
-fx-background-radius: 4 4 4 4;
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
package io.bitsquare.trade.handlers;
|
||||
|
||||
/**
|
||||
* For reporting throwables only
|
||||
*/
|
||||
|
@ -42,10 +42,10 @@ public class VerifyAndSignContract
|
||||
//TODO PublicKey cause problems, need to be changed to hex
|
||||
/*if (contractAsJson.equals(peersContractAsJson))
|
||||
{*/
|
||||
log.trace("The 2 contracts as json does match");
|
||||
String signature = cryptoFacade.signContract(registrationKey, contractAsJson);
|
||||
//log.trace("signature: " + signature);
|
||||
resultHandler.onResult(contract, contractAsJson, signature);
|
||||
log.trace("The 2 contracts as json does match");
|
||||
String signature = cryptoFacade.signContract(registrationKey, contractAsJson);
|
||||
//log.trace("signature: " + signature);
|
||||
resultHandler.onResult(contract, contractAsJson, signature);
|
||||
/* }
|
||||
else
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ public class AWTSystemTray
|
||||
trayIcon.setToolTip("BitSquare P2P Fiat-Bitcoin exchange");
|
||||
|
||||
PopupMenu popupMenu = new PopupMenu();
|
||||
MenuItem aboutItem = new MenuItem("Info about " + BitSquare.getUID());
|
||||
MenuItem aboutItem = new MenuItem("Info about " + BitSquare.getAppName());
|
||||
popupMenu.add(aboutItem);
|
||||
popupMenu.addSeparator();
|
||||
showGuiItem = new MenuItem("Close exchange window");
|
||||
|
@ -1,98 +0,0 @@
|
||||
package io.bitsquare.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CachingClassLoader extends ClassLoader
|
||||
{
|
||||
private final Map<String, Class> classes = new HashMap<String, Class>();
|
||||
private final ClassLoader parent;
|
||||
|
||||
public CachingClassLoader(ClassLoader parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException
|
||||
{
|
||||
Class<?> c = findClass(name);
|
||||
if (c == null)
|
||||
{
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String className) throws ClassNotFoundException
|
||||
{
|
||||
if (classes.containsKey(className))
|
||||
{
|
||||
// System.out.print("############## cached " + className);
|
||||
Class<?> result = classes.get(className);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Class<?> result = parent.loadClass(className);
|
||||
System.out.print("############## not cached " + className);
|
||||
classes.put(className, result);
|
||||
return result;
|
||||
} catch (ClassNotFoundException ignore)
|
||||
{
|
||||
// System.out.println();
|
||||
classes.put(className, null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========= delegating methods =============
|
||||
@Override
|
||||
public URL getResource(String name)
|
||||
{
|
||||
return parent.getResource(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<URL> getResources(String name) throws IOException
|
||||
{
|
||||
return parent.getResources(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return parent.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultAssertionStatus(boolean enabled)
|
||||
{
|
||||
parent.setDefaultAssertionStatus(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPackageAssertionStatus(String packageName, boolean enabled)
|
||||
{
|
||||
parent.setPackageAssertionStatus(packageName, enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClassAssertionStatus(String className, boolean enabled)
|
||||
{
|
||||
parent.setClassAssertionStatus(className, enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAssertionStatus()
|
||||
{
|
||||
parent.clearAssertionStatus();
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package io.bitsquare.util;
|
||||
|
||||
import com.google.bitcoin.core.Utils;
|
||||
import io.bitsquare.BitSquare;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import org.slf4j.Logger;
|
||||
@ -21,6 +20,7 @@ public class FileUtil
|
||||
return File.createTempFile("temp_" + prefix, null, StorageDirectory.getStorageDirectory());
|
||||
}
|
||||
|
||||
/*
|
||||
public static String getApplicationFileName()
|
||||
{
|
||||
File executionRoot = new File(StorageDirectory.class.getProtectionDomain().getCodeSource().getLocation().getFile());
|
||||
@ -50,9 +50,11 @@ public class FileUtil
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// fallback use AppName
|
||||
return BitSquare.getAppName();
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
public static void writeTempFileToFile(File tempFile, File file) throws IOException
|
||||
{
|
||||
|
@ -2,7 +2,8 @@ package io.bitsquare;
|
||||
|
||||
import io.bitsquare.btc.BtcValidatorTest;
|
||||
import io.bitsquare.gui.util.BitSquareConverterTest;
|
||||
import io.bitsquare.gui.util.BitSquareValidatorTest;
|
||||
import io.bitsquare.gui.util.BitSquareNumberValidatorTest;
|
||||
import io.bitsquare.gui.util.FiatValidatorTest;
|
||||
import io.bitsquare.msg.P2PNodeTest;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
@ -11,8 +12,10 @@ import org.junit.runners.Suite;
|
||||
@Suite.SuiteClasses({
|
||||
BtcValidatorTest.class,
|
||||
BitSquareConverterTest.class,
|
||||
BitSquareValidatorTest.class,
|
||||
P2PNodeTest.class
|
||||
BitSquareNumberValidatorTest.class,
|
||||
P2PNodeTest.class,
|
||||
FiatValidatorTest.class,
|
||||
BtcValidatorTest.class
|
||||
})
|
||||
|
||||
public class BitSquareTestSuite
|
||||
|
@ -11,19 +11,19 @@ public class BitSquareConverterTest
|
||||
public void testStringToDouble()
|
||||
{
|
||||
|
||||
assertEquals(1, BitSquareConverter.stringToDouble("1"), 0);
|
||||
assertEquals(0.1, BitSquareConverter.stringToDouble("0.1"), 0);
|
||||
assertEquals(0.1, BitSquareConverter.stringToDouble("0,1"), 0);
|
||||
assertEquals(1, BitSquareConverter.stringToDouble("1.0"), 0);
|
||||
assertEquals(1, BitSquareConverter.stringToDouble("1,0"), 0);
|
||||
assertEquals(1, BitSquareFormatter.parseToDouble("1"), 0);
|
||||
assertEquals(0.1, BitSquareFormatter.parseToDouble("0.1"), 0);
|
||||
assertEquals(0.1, BitSquareFormatter.parseToDouble("0,1"), 0);
|
||||
assertEquals(1, BitSquareFormatter.parseToDouble("1.0"), 0);
|
||||
assertEquals(1, BitSquareFormatter.parseToDouble("1,0"), 0);
|
||||
|
||||
assertEquals(0, BitSquareConverter.stringToDouble("1,000.2"), 0);
|
||||
assertEquals(0, BitSquareConverter.stringToDouble("1,000.2"), 0);
|
||||
assertEquals(0, BitSquareConverter.stringToDouble(null), 0);
|
||||
assertEquals(0, BitSquareConverter.stringToDouble(""), 0);
|
||||
assertEquals(0, BitSquareConverter.stringToDouble(""), 0);
|
||||
assertEquals(0, BitSquareConverter.stringToDouble("."), 0);
|
||||
assertEquals(0, BitSquareConverter.stringToDouble(","), 0);
|
||||
assertEquals(0, BitSquareConverter.stringToDouble("a"), 0);
|
||||
assertEquals(0, BitSquareFormatter.parseToDouble("1,000.2"), 0);
|
||||
assertEquals(0, BitSquareFormatter.parseToDouble("1,000.2"), 0);
|
||||
assertEquals(0, BitSquareFormatter.parseToDouble(null), 0);
|
||||
assertEquals(0, BitSquareFormatter.parseToDouble(""), 0);
|
||||
assertEquals(0, BitSquareFormatter.parseToDouble(""), 0);
|
||||
assertEquals(0, BitSquareFormatter.parseToDouble("."), 0);
|
||||
assertEquals(0, BitSquareFormatter.parseToDouble(","), 0);
|
||||
assertEquals(0, BitSquareFormatter.parseToDouble("a"), 0);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import org.junit.Test;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class BitSquareValidatorTest
|
||||
public class BitSquareNumberValidatorTest
|
||||
{
|
||||
@Test
|
||||
public void testValidateStringAsDouble()
|
35
src/test/java/io/bitsquare/gui/util/BtcValidatorTest.java
Normal file
35
src/test/java/io/bitsquare/gui/util/BtcValidatorTest.java
Normal file
@ -0,0 +1,35 @@
|
||||
package io.bitsquare.gui.util;
|
||||
|
||||
import com.google.bitcoin.core.Coin;
|
||||
import com.google.bitcoin.core.NetworkParameters;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class BtcValidatorTest
|
||||
{
|
||||
@Test
|
||||
public void testValidate()
|
||||
{
|
||||
BtcValidator validator = new BtcValidator();
|
||||
NumberValidator.ValidationResult validationResult;
|
||||
|
||||
// invalid cases
|
||||
validationResult = validator.validate("0.000000011");// minBtc is "0.00000001"
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate("21000001"); //maxBtc is "21000000"
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
// valid cases
|
||||
String minBtc = Coin.SATOSHI.toPlainString(); // "0.00000001"
|
||||
validationResult = validator.validate(minBtc);
|
||||
assertTrue(validationResult.isValid);
|
||||
|
||||
String maxBtc = Coin.valueOf(NetworkParameters.MAX_MONEY.longValue()).toPlainString(); //"21000000"
|
||||
validationResult = validator.validate(maxBtc);
|
||||
assertTrue(validationResult.isValid);
|
||||
}
|
||||
|
||||
}
|
88
src/test/java/io/bitsquare/gui/util/FiatValidatorTest.java
Normal file
88
src/test/java/io/bitsquare/gui/util/FiatValidatorTest.java
Normal file
@ -0,0 +1,88 @@
|
||||
package io.bitsquare.gui.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class FiatValidatorTest
|
||||
{
|
||||
@Test
|
||||
public void testValidate()
|
||||
{
|
||||
FiatValidator validator = new FiatValidator();
|
||||
NumberValidator.ValidationResult validationResult;
|
||||
|
||||
|
||||
// invalid cases
|
||||
validationResult = validator.validate(null);
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate("");
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate("0");
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate("-1");
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate("a");
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate("2a");
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate("a2");
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
// at the moment we dont support thousand separators, can be added later
|
||||
validationResult = validator.validate("1,100.1");
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
// at the moment we dont support thousand separators, can be added later
|
||||
validationResult = validator.validate("1.100,1");
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate("1.100.1");
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate("1,100,1");
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate(String.valueOf(FiatValidator.MIN_FIAT_VALUE - 0.0000001));
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate(String.valueOf(FiatValidator.MAX_FIAT_VALUE + 0.0000001));
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate(String.valueOf(Double.MIN_VALUE));
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate(String.valueOf(Double.MAX_VALUE));
|
||||
assertFalse(validationResult.isValid);
|
||||
|
||||
|
||||
// valid cases
|
||||
validationResult = validator.validate("1");
|
||||
assertTrue(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate("0,1");
|
||||
assertTrue(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate("0.1");
|
||||
assertTrue(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate(",1");
|
||||
assertTrue(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate(".1");
|
||||
assertTrue(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate(String.valueOf(FiatValidator.MIN_FIAT_VALUE));
|
||||
assertTrue(validationResult.isValid);
|
||||
|
||||
validationResult = validator.validate(String.valueOf(FiatValidator.MAX_FIAT_VALUE));
|
||||
assertTrue(validationResult.isValid);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user