Improve UI

This commit is contained in:
Manfred Karrer 2014-09-30 15:49:01 +02:00
parent c5028c178c
commit 3c05af90f2
27 changed files with 613 additions and 309 deletions

View File

@ -127,7 +127,7 @@ public class BitSquare extends Application {
try {
final Parent view = loader.load();
final Scene scene = new Scene(view, 1000, 750);
final Scene scene = new Scene(view, 1000, 800);
scene.getStylesheets().setAll(getClass().getResource("/io/bitsquare/gui/bitsquare.css").toExternalForm(),
getClass().getResource("/io/bitsquare/gui/images.css").toExternalForm());
@ -136,12 +136,12 @@ public class BitSquare extends Application {
primaryStage.setScene(scene);
// TODO resizing not fully supported yet
/*
primaryStage.setMinWidth(750);
primaryStage.setMinHeight(500);*/
primaryStage.setMinWidth(1000);
primaryStage.setMinHeight(750);
primaryStage.setMinWidth(75);
primaryStage.setMinHeight(50);
/* primaryStage.setMinWidth(1000);
primaryStage.setMinHeight(750);*/
Profiler.initScene(primaryStage.getScene());

View File

@ -26,8 +26,7 @@ public enum BankAccountType {
INTERNATIONAL("primary ID", "secondary ID"),
OK_PAY("primary ID", "secondary ID"),
NET_TELLER("primary ID", "secondary ID"),
PERFECT_MONEY("primary ID", "secondary ID"),
OTHER("primary ID", "secondary ID");
PERFECT_MONEY("primary ID", "secondary ID");
private final String primaryId;
private final String secondaryId;

View File

@ -612,7 +612,6 @@ public class WalletFacade {
public String sendFunds(String withdrawFromAddress,
String withdrawToAddress,
String changeAddress,
Coin amount,
FutureCallback<Transaction> callback) throws AddressFormatException,
InsufficientMoneyException, IllegalArgumentException {

View File

@ -96,19 +96,17 @@ public class InfoDisplay extends Parent {
textFlow.getChildren().addAll(testLabel);
testLabel.widthProperty().addListener((ov, o, n) -> {
if ((double) n > textFlow.getWidth()) {
link.setText(BSResources.get("shared.readMore"));
useReadMore = true;
}
else {
link.setText(BSResources.get("shared.openHelp"));
}
useReadMore = (double) n > textFlow.getWidth();
link.setText(BSResources.get(useReadMore ? "shared.readMore" : "shared.openHelp"));
Platform.runLater(() -> textFlow.getChildren().setAll(label, link));
});
// update the width when the window gets resized
ChangeListener<Number> listener = (ov2, oldValue2, windowWidth) ->
label.setPrefWidth((double) windowWidth - localToScene(0, 0).getX() - 35);
ChangeListener<Number> listener = (ov2, oldValue2, windowWidth) -> {
if (label.prefWidthProperty().isBound())
label.prefWidthProperty().unbind();
label.setPrefWidth((double) windowWidth - localToScene(0, 0).getX() - 35);
};
// when clicking "Read more..." we expand and change the link to the Help
@ -120,12 +118,14 @@ public class InfoDisplay extends Parent {
label.setWrapText(true);
link.setText(BSResources.get("shared.openHelp"));
getScene().getWindow().widthProperty().removeListener(listener);
label.prefWidthProperty().unbind();
if (label.prefWidthProperty().isBound())
label.prefWidthProperty().unbind();
label.prefWidthProperty().bind(textFlow.widthProperty());
link.setVisited(false);
// focus border is a bit confusing here so we remove it
link.setStyle("-fx-focus-color: transparent;");
link.setOnAction(onAction.get());
getParent().layout();
}
else {
onAction.get().handle(actionEvent);
@ -154,7 +154,13 @@ public class InfoDisplay extends Parent {
public void setText(String text) {
this.text.set(text);
layout();
if (getScene() != null) {
Platform.runLater(() -> {
label.setVisible(true);
label.prefWidthProperty().unbind();
label.setPrefWidth(getScene().getWindow().getWidth() - localToScene(0, 0).getX() - 35);
});
}
}
public void setGridPane(GridPane gridPane) {

View File

@ -34,7 +34,6 @@ import javafx.event.ActionEvent;
import org.controlsfx.control.action.AbstractAction;
import org.controlsfx.control.action.Action;
import org.controlsfx.dialog.Dialog;
import org.controlsfx.dialog.DialogStyle;
import org.controlsfx.dialog.Dialogs;
import org.slf4j.Logger;
@ -86,7 +85,6 @@ public class Popups {
.message(message)
.masthead(masthead)
.actions(actions)
.style(DialogStyle.UNDECORATED)
.showInformation();
}

View File

@ -173,10 +173,10 @@ class ProcessStepBarSkin<T> extends BehaviorSkinBase<ProcessStepBar<T>, Behavior
public void past() {
log.debug("deSelect " + processStepItem.getLabel());
BorderStroke borderStroke = new BorderStroke(Colors.GREEN, BorderStrokeStyle.SOLID, null,
BorderStroke borderStroke = new BorderStroke(Color.valueOf("#444444"), BorderStrokeStyle.SOLID, null,
new BorderWidths(borderWidth, borderWidth, borderWidth, borderWidth), Insets.EMPTY);
this.setBorder(new Border(borderStroke));
setTextFill(Colors.GREEN);
setTextFill(Color.valueOf("#444444"));
}
public double getArrowWidth() {

View File

@ -228,8 +228,8 @@ public class MainViewCB extends ViewCB<MainPM> {
presentationModel.numPendingTrades.addListener((ov, oldValue, newValue) ->
{
if ((int) newValue > (int) oldValue)
applyPendingTradesInfoIcon((int) newValue);
//if ((int) newValue > (int) oldValue)
applyPendingTradesInfoIcon((int) newValue);
});
applyPendingTradesInfoIcon(presentationModel.numPendingTrades.get());
navigation.navigateToLastStoredItem();

View File

@ -39,8 +39,7 @@
</Label>
<TextField fx:id="feeTextField"
GridPane.columnIndex="1"
GridPane.rowIndex="0"
editable="false" focusTraversable="false">
GridPane.rowIndex="0" mouseTransparent="true" editable="false" focusTraversable="false">
<GridPane.margin>
<Insets top="10.0"/>
</GridPane.margin>

View File

@ -23,7 +23,7 @@
AnchorPane.topAnchor="0.0"
xmlns:fx="http://javafx.com/fxml">
<Tab fx:id="withdrawalTab" text="Withdrawal" closable="false"/>
<Tab fx:id="transactionsTab" text="Transactions" closable="false"/>
<Tab fx:id="withdrawalTab" text="Open for withdrawal" closable="false"/>
<Tab fx:id="transactionsTab" text="History" closable="false"/>
</TabPane>

View File

@ -53,13 +53,10 @@
<TextField fx:id="withdrawFromTextField" promptText="Select a source address from the table"
GridPane.rowIndex="1" GridPane.columnIndex="1"/>
<Label text="Change address:" GridPane.rowIndex="2"/>
<TextField fx:id="changeAddressTextField" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
<Label text="Withdraw to address:" GridPane.rowIndex="2"/>
<TextField fx:id="withdrawToTextField" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
<Label text="Withdraw to address:" GridPane.rowIndex="3"/>
<TextField fx:id="withdrawToTextField" GridPane.rowIndex="3" GridPane.columnIndex="1"/>
<Button text="Withdraw" defaultButton="true" onAction="#onWithdraw" GridPane.rowIndex="4"
<Button text="Withdraw" defaultButton="true" onAction="#onWithdraw" GridPane.rowIndex="3"
GridPane.columnIndex="1"/>
<columnConstraints>

View File

@ -65,13 +65,13 @@ public class WithdrawalViewCB extends CachedViewCB {
private final WalletFacade walletFacade;
private BSFormatter formatter;
private ObservableList<WithdrawalListItem> addressList;
private final ObservableList<WithdrawalListItem> addressList = FXCollections.observableArrayList();
@FXML TableView<WithdrawalListItem> table;
@FXML TableColumn<WithdrawalListItem, WithdrawalListItem> labelColumn, addressColumn, balanceColumn, copyColumn,
confidenceColumn;
@FXML Button addNewAddressButton;
@FXML TextField withdrawFromTextField, withdrawToTextField, amountTextField, changeAddressTextField;
@FXML TextField withdrawFromTextField, withdrawToTextField, amountTextField;
///////////////////////////////////////////////////////////////////////////////////////////
@ -119,7 +119,6 @@ public class WithdrawalViewCB extends CachedViewCB {
if (Coin.ZERO.compareTo(newValue.getBalance()) <= 0) {
amountTextField.setText(newValue.getBalance().toPlainString());
withdrawFromTextField.setText(newValue.getAddressEntry().getAddressString());
changeAddressTextField.setText(newValue.getAddressEntry().getAddressString());
}
else {
withdrawFromTextField.setText("");
@ -130,11 +129,7 @@ public class WithdrawalViewCB extends CachedViewCB {
}
});
List<AddressEntry> addressEntryList = walletFacade.getAddressEntryList();
addressList = FXCollections.observableArrayList();
addressList.addAll(addressEntryList.stream().map(anAddressEntryList ->
new WithdrawalListItem(anAddressEntryList, walletFacade, formatter)).collect(Collectors.toList()));
fillList();
table.setItems(addressList);
}
@ -180,7 +175,9 @@ public class WithdrawalViewCB extends CachedViewCB {
try {
walletFacade.sendFunds(
withdrawFromTextField.getText(), withdrawToTextField.getText(),
changeAddressTextField.getText(), amount, callback);
amount, callback);
fillList();
} catch (AddressFormatException e) {
Popups.openErrorPopup("Address invalid",
"The address is not correct. Please check the address format.");
@ -205,6 +202,14 @@ public class WithdrawalViewCB extends CachedViewCB {
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void fillList() {
addressList.clear();
List<AddressEntry> addressEntryList = walletFacade.getAddressEntryList();
addressList.addAll(addressEntryList.stream()
.filter(e -> walletFacade.getBalanceForAddress(e.getAddress()).isPositive())
.map(anAddressEntryList -> new WithdrawalListItem(anAddressEntryList, walletFacade, formatter))
.collect(Collectors.toList()));
}
///////////////////////////////////////////////////////////////////////////////////////////
// Cell factories

View File

@ -26,6 +26,6 @@
<Tab fx:id="offersTab" text="Open offers" closable="false"/>
<Tab fx:id="pendingTradesTab" text="Pending trades" closable="false"/>
<Tab fx:id="closedTradesTab" text="Closed trades" closable="false"/>
<Tab fx:id="closedTradesTab" text="History" closable="false"/>
</TabPane>

View File

@ -34,8 +34,8 @@ import javax.inject.Inject;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -127,7 +127,7 @@ public class OrdersViewCB extends CachedViewCB {
final ViewLoader loader = new ViewLoader(getClass().getResource(navigationItem.getFxmlUrl()));
try {
GridPane view = loader.load();
Parent view = loader.load();
Tab tab = null;
switch (navigationItem) {
case OFFERS:

View File

@ -18,8 +18,11 @@
package io.bitsquare.gui.main.orders.closed;
import io.bitsquare.gui.UIModel;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.Offer;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeManager;
import io.bitsquare.user.User;
import com.google.inject.Inject;
@ -34,6 +37,7 @@ class ClosedTradesModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(ClosedTradesModel.class);
private final TradeManager tradeManager;
private User user;
private final ObservableList<ClosedTradesListItem> list = FXCollections.observableArrayList();
private MapChangeListener<String, Trade> mapChangeListener;
@ -44,8 +48,9 @@ class ClosedTradesModel extends UIModel {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public ClosedTradesModel(TradeManager tradeManager) {
public ClosedTradesModel(TradeManager tradeManager, User user) {
this.tradeManager = tradeManager;
this.user = user;
}
@ -100,4 +105,9 @@ class ClosedTradesModel extends UIModel {
return list;
}
public Direction getDirection(Offer offer) {
return offer.getMessagePublicKey().equals(user.getMessagePublicKey()) ?
offer.getDirection() : offer.getMirroredDirection();
}
}

View File

@ -87,7 +87,7 @@ class ClosedTradesPM extends PresentationModel<ClosedTradesModel> {
}
String getAmount(ClosedTradesListItem item) {
return (item != null) ? formatter.formatAmountWithMinAmount(item.getTrade().getOffer()) : "";
return (item != null) ? formatter.formatCoinWithCode(item.getTrade().getTradeAmount()) : "";
}
String getPrice(ClosedTradesListItem item) {
@ -95,11 +95,11 @@ class ClosedTradesPM extends PresentationModel<ClosedTradesModel> {
}
String getVolume(ClosedTradesListItem item) {
return (item != null) ? formatter.formatVolumeWithMinVolume(item.getTrade().getOffer()) : "";
return (item != null) ? formatter.formatFiatWithCode(item.getTrade().getTradeVolume()) : "";
}
String getDirectionLabel(ClosedTradesListItem item) {
return (item != null) ? formatter.formatDirection(item.getTrade().getOffer().getMirroredDirection()) : "";
return (item != null) ? formatter.formatDirection(model.getDirection(item.getTrade().getOffer())) : "";
}
String getDate(ClosedTradesListItem item) {

View File

@ -18,8 +18,10 @@
package io.bitsquare.gui.main.orders.offer;
import io.bitsquare.gui.UIModel;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.Offer;
import io.bitsquare.trade.TradeManager;
import io.bitsquare.user.User;
import com.google.inject.Inject;
@ -36,6 +38,7 @@ class OffersModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(OffersModel.class);
private final TradeManager tradeManager;
private User user;
private final ObservableList<OfferListItem> list = FXCollections.observableArrayList();
private MapChangeListener<String, Offer> offerMapChangeListener;
@ -46,8 +49,9 @@ class OffersModel extends UIModel {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public OffersModel(TradeManager tradeManager) {
public OffersModel(TradeManager tradeManager, User user) {
this.tradeManager = tradeManager;
this.user = user;
}
@ -111,4 +115,8 @@ class OffersModel extends UIModel {
return list;
}
public Direction getDirection(Offer offer) {
return offer.getMessagePublicKey().equals(user.getMessagePublicKey()) ?
offer.getDirection() : offer.getMirroredDirection();
}
}

View File

@ -108,7 +108,7 @@ class OffersPM extends PresentationModel<OffersModel> {
}
String getDirectionLabel(OfferListItem item) {
return (item != null) ? formatter.formatDirection(item.getOffer().getMirroredDirection()) : "";
return (item != null) ? formatter.formatDirection(model.getDirection(item.getOffer())) : "";
}
String getDate(OfferListItem item) {

View File

@ -17,17 +17,25 @@
package io.bitsquare.gui.main.orders.pending;
import io.bitsquare.btc.AddressEntry;
import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.btc.listeners.TxConfidenceListener;
import io.bitsquare.gui.UIModel;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.Offer;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeManager;
import io.bitsquare.user.User;
import com.google.bitcoin.core.AddressFormatException;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.InsufficientMoneyException;
import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.TransactionConfidence;
import com.google.common.util.concurrent.FutureCallback;
import com.google.inject.Inject;
import java.util.Optional;
@ -41,6 +49,8 @@ import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableList;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -197,12 +207,68 @@ class PendingTradesModel extends UIModel {
tradeManager.fiatPaymentReceived(getTrade().getId());
}
void closeSummary() {
void removePendingTrade() {
if (closedTrade != null) {
list.removeIf(e -> e.getTrade().getId().equals(closedTrade.getId()));
}
}
void withdraw(String toAddress) {
FutureCallback<Transaction> callback = new FutureCallback<Transaction>() {
@Override
public void onSuccess(@javax.annotation.Nullable Transaction transaction) {
if (transaction != null) {
log.info("onWithdraw onSuccess tx ID:" + transaction.getHashAsString());
}
}
@Override
public void onFailure(@NotNull Throwable t) {
log.debug("onWithdraw onFailure");
}
};
AddressEntry addressEntry = walletFacade.getAddressInfoByTradeID(getTrade().getId());
String fromAddress = addressEntry.getAddressString();
try {
walletFacade.sendFunds(fromAddress, toAddress, getAmountToWithdraw(), callback);
} catch (AddressFormatException e) {
e.printStackTrace();
log.error(e.getMessage());
} catch (InsufficientMoneyException e) {
e.printStackTrace();
log.error(e.getMessage());
}
/*
Action response = Popups.openConfirmPopup(
"Withdrawal request", "Confirm your request",
"Your withdrawal request:\n\n" + "Amount: " + amountTextField.getText() + " BTC\n" + "Sending" +
" address: " + withdrawFromTextField.getText() + "\n" + "Receiving address: " +
withdrawToTextField.getText() + "\n" + "Transaction fee: " +
formatter.formatCoinWithCode(FeePolicy.TX_FEE) + "\n" +
"You receive in total: " +
formatter.formatCoinWithCode(amount.subtract(FeePolicy.TX_FEE)) + " BTC\n\n" +
"Are you sure you withdraw that amount?");
if (response == Dialog.Actions.OK) {
try {
walletFacade.sendFunds(
withdrawFromTextField.getText(), withdrawToTextField.getText(),
changeAddressTextField.getText(), amount, callback);
} catch (AddressFormatException e) {
Popups.openErrorPopup("Address invalid",
"The address is not correct. Please check the address format.");
} catch (InsufficientMoneyException e) {
Popups.openInsufficientMoneyPopup();
} catch (IllegalArgumentException e) {
Popups.openErrorPopup("Wrong inputs", "Please check the inputs.");
}
}*/
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
@ -236,6 +302,16 @@ class PendingTradesModel extends UIModel {
return selectedItem.getTrade().getOffer().getCurrency().getCurrencyCode();
}
public Direction getDirection(Offer offer) {
return offer.getMessagePublicKey().equals(user.getMessagePublicKey()) ?
offer.getDirection() : offer.getMirroredDirection();
}
Coin getAmountToWithdraw() {
AddressEntry addressEntry = walletFacade.getAddressInfoByTradeID(getTrade().getId());
return walletFacade.getBalanceForAddress(addressEntry.getAddress());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -19,13 +19,17 @@ package io.bitsquare.gui.main.orders.pending;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.gui.util.validation.BtcAddressValidator;
import io.bitsquare.locale.BSResources;
import com.google.inject.Inject;
import javafx.beans.InvalidationListener;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
@ -50,12 +54,13 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
}
private final BSFormatter formatter;
private InvalidationListener stateChangeListener;
private BtcAddressValidator btcAddressValidator;
final StringProperty txId = new SimpleStringProperty();
final ObjectProperty<State> state = new SimpleObjectProperty<>();
final ObjectProperty<Throwable> fault = new SimpleObjectProperty<>();
final BooleanProperty withdrawalButtonDisable = new SimpleBooleanProperty(true);
///////////////////////////////////////////////////////////////////////////////////////////
@ -63,10 +68,12 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
PendingTradesPM(PendingTradesModel model, BSFormatter formatter) {
PendingTradesPM(PendingTradesModel model, BSFormatter formatter,
BtcAddressValidator btcAddressValidator) {
super(model);
this.formatter = formatter;
this.btcAddressValidator = btcAddressValidator;
}
@ -126,10 +133,25 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
model.fiatPaymentReceived();
}
void closeSummary() {
model.closeSummary();
void removePendingTrade() {
model.removePendingTrade();
}
void withdraw(String withdrawToAddress) {
// TODO address validation
if (withdrawToAddress != null && withdrawToAddress.length() > 0)
model.withdraw(withdrawToAddress);
else
Popups.openWarningPopup("Please fill in a withdrawal address where you want to send your bitcoins.");
}
void withdrawAddressFocusOut(String text) {
withdrawalButtonDisable.set(!btcAddressValidator.validate(text).isValid);
}
String getAmountToWithdraw() {
return formatter.formatCoinWithCode(model.getAmountToWithdraw());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
@ -161,7 +183,7 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
}
String getAmount(PendingTradesListItem item) {
return (item != null) ? formatter.formatAmountWithMinAmount(item.getTrade().getOffer()) : "";
return (item != null) ? formatter.formatCoinWithCode(item.getTrade().getTradeAmount()) : "";
}
String getPrice(PendingTradesListItem item) {
@ -169,19 +191,11 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
}
String getVolume(PendingTradesListItem item) {
return (item != null) ? formatter.formatVolumeWithMinVolume(item.getTrade().getOffer()) : "";
return (item != null) ? formatter.formatFiatWithCode(item.getTrade().getTradeVolume()) : "";
}
String getDirectionLabel(PendingTradesListItem item) {
if (item != null) {
if (model.isOfferer())
return formatter.formatDirection(item.getTrade().getOffer().getDirection()) + " Bitcoin";
else
return formatter.formatDirection(item.getTrade().getOffer().getMirroredDirection()) + " Bitcoin";
}
else {
return "";
}
return (item != null) ? formatter.formatDirection(model.getDirection(item.getTrade().getOffer())) : "";
}
String getDate(PendingTradesListItem item) {
@ -193,6 +207,10 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
return BSResources.get(model.getTrade().getContract().getTakerBankAccount().getBankAccountType().toString());
}
String getFiatAmount() {
return formatter.formatFiatWithCode(model.getTrade().getTradeVolume());
}
String getHolderName() {
return model.getTrade().getContract().getTakerBankAccount().getAccountHolderName();
}
@ -222,6 +240,9 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
return formatter.formatCoinWithCode(model.getTrade().getCollateralAmount());
}
BtcAddressValidator getBtcAddressValidator() {
return btcAddressValidator;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private

View File

@ -18,6 +18,7 @@
-->
<?import io.bitsquare.gui.components.InfoDisplay?>
<?import io.bitsquare.gui.components.InputTextField?>
<?import io.bitsquare.gui.components.processbar.ProcessStepBar?>
<?import io.bitsquare.gui.components.TextFieldWithCopyIcon?>
<?import io.bitsquare.gui.components.TitledGroupBg?>
@ -26,169 +27,227 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.orders.pending.PendingTradesViewCB"
hgap="5.0" vgap="5"
xmlns:fx="http://javafx.com/fxml">
<padding>
<Insets bottom="20.0" left="25.0" top="30.0" right="25"/>
</padding>
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.orders.pending.PendingTradesViewCB"
xmlns:fx="http://javafx.com/fxml">
<TitledSeparator text="Pending trades" GridPane.rowIndex="0" GridPane.columnIndex="0" GridPane.columnSpan="2"/>
<ScrollPane fx:id="scrollPane" fitToWidth="true" fitToHeight="true"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
AnchorPane.bottomAnchor="0.0">
<TableView fx:id="table" GridPane.rowIndex="0" GridPane.columnIndex="0" GridPane.columnSpan="2"
minHeight="120" prefHeight="120">
<GridPane.margin>
<Insets top="10.0" left="-10" right="-10" bottom="-15"/>
</GridPane.margin>
<columns>
<TableColumn text="Trade ID" fx:id="tradeIdColumn" minWidth="100" sortable="false"/>
<TableColumn text="Date" fx:id="dateColumn" minWidth="130"/>
<TableColumn text="Amount in BTC (Min.)" fx:id="amountColumn" minWidth="130" sortable="false"/>
<TableColumn text="Price" fx:id="priceColumn" minWidth="100" sortable="false"/>
<TableColumn text="Amount in EUR (Min.)" fx:id="volumeColumn" minWidth="130" sortable="false"/>
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="80" sortable="false"/>
<TableColumn text="" fx:id="selectColumn" minWidth="60" sortable="false"/>
</columns>
</TableView>
<GridPane fx:id="gridPane" hgap="5.0" vgap="5" minWidth="980">
<padding>
<Insets bottom="-10.0" left="25.0" top="30.0" right="25"/>
</padding>
<TitledGroupBg fx:id="titledGroupBg" text="Trade status" GridPane.rowIndex="1" GridPane.rowSpan="4"
GridPane.columnSpan="2" visible="false">
<GridPane.margin>
<Insets top="40.0" bottom="-10" left="-10" right="-10"/>
</GridPane.margin>
</TitledGroupBg>
<TitledSeparator text="Pending trades" GridPane.rowIndex="0" GridPane.columnIndex="0"
GridPane.columnSpan="2"/>
<ProcessStepBar fx:id="processBar" GridPane.rowIndex="1" GridPane.columnSpan="2" snapToPixel="true" visible="false">
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</ProcessStepBar>
<TableView fx:id="table" GridPane.rowIndex="0" GridPane.columnIndex="0" GridPane.columnSpan="2"
minHeight="120" prefHeight="120">
<GridPane.margin>
<Insets top="10.0" left="-10" right="-10" bottom="-15"/>
</GridPane.margin>
<columns>
<TableColumn text="Trade ID" fx:id="tradeIdColumn" minWidth="100" sortable="false"/>
<TableColumn text="Date" fx:id="dateColumn" minWidth="130"/>
<TableColumn text="Trade amount in BTC" fx:id="amountColumn" minWidth="130" sortable="false"/>
<TableColumn text="Price" fx:id="priceColumn" minWidth="100" sortable="false"/>
<TableColumn text="Trade amount in EUR" fx:id="volumeColumn" minWidth="130" sortable="false"/>
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="80" sortable="false"/>
</columns>
</TableView>
<TitledGroupBg fx:id="titledGroupBg" text="Trade status" GridPane.rowIndex="1" GridPane.rowSpan="4"
GridPane.columnSpan="2" managed="false" visible="false">
<GridPane.margin>
<Insets top="40.0" bottom="-10" left="-10" right="-10"/>
</GridPane.margin>
</TitledGroupBg>
<ProcessStepBar fx:id="processBar" GridPane.rowIndex="1" GridPane.columnSpan="2" snapToPixel="true"
managed="false" visible="false">
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</ProcessStepBar>
<Label fx:id="statusLabel" text="Status:" GridPane.rowIndex="2" visible="false">
<GridPane.margin>
<Insets top="20.0"/>
</GridPane.margin>
</Label>
<TextField fx:id="statusTextField" GridPane.rowIndex="2" GridPane.columnIndex="1" editable="false" visible="false">
<GridPane.margin>
<Insets top="20.0"/>
</GridPane.margin>
</TextField>
<Label fx:id="statusLabel" text="Status:" GridPane.rowIndex="2" managed="false" visible="false">
<GridPane.margin>
<Insets top="20.0"/>
</GridPane.margin>
</Label>
<TextField fx:id="statusTextField" GridPane.rowIndex="2" GridPane.columnIndex="1" editable="false"
focusTraversable="false" mouseTransparent="true" managed="false" visible="false">
<GridPane.margin>
<Insets top="20.0"/>
</GridPane.margin>
</TextField>
<Label fx:id="txIdLabel" text="Deposit transaction ID:" GridPane.rowIndex="3" visible="false"/>
<TxIdTextField fx:id="txIdTextField" GridPane.rowIndex="3" GridPane.columnIndex="1" visible="false"/>
<Label fx:id="txIdLabel" text="Deposit transaction ID:" GridPane.rowIndex="3" managed="false"
visible="false"/>
<TxIdTextField fx:id="txIdTextField" GridPane.rowIndex="3" GridPane.columnIndex="1" managed="false"
visible="false"/>
<InfoDisplay fx:id="infoDisplay" onAction="#onOpenHelp" rowIndex="4" gridPane="$root" visible="false"/>
<InfoDisplay fx:id="infoDisplay" onAction="#onOpenHelp" rowIndex="4" gridPane="$gridPane" managed="false"
visible="false"/>
<Button fx:id="confirmPaymentReceiptButton" text="Confirm payment receipt" onAction="#onConfirmPaymentReceipt"
GridPane.rowIndex="5" GridPane.columnIndex="1" defaultButton="true" visible="false">
<GridPane.margin>
<Insets top="-5"/>
</GridPane.margin>
</Button>
<Button fx:id="confirmPaymentReceiptButton" text="Confirm payment receipt"
onAction="#onConfirmPaymentReceipt" GridPane.rowIndex="5" GridPane.columnIndex="1"
defaultButton="true" managed="false" visible="false">
<GridPane.margin>
<Insets top="15"/>
</GridPane.margin>
</Button>
<!--
Payments
-->
<TitledGroupBg fx:id="paymentsGroupBg" text="Payments details" GridPane.rowIndex="5" GridPane.rowSpan="5"
GridPane.columnSpan="2" visible="false">
<GridPane.margin>
<Insets top="40.0" bottom="-10" left="-10" right="-10"/>
</GridPane.margin>
</TitledGroupBg>
<!--
Payments
-->
<TitledGroupBg fx:id="paymentsGroupBg" text="Payments details" GridPane.rowIndex="5" GridPane.rowSpan="6"
GridPane.columnSpan="2" managed="false" visible="false">
<GridPane.margin>
<Insets top="40.0" bottom="-10" left="-10" right="-10"/>
</GridPane.margin>
</TitledGroupBg>
<Label fx:id="paymentMethodLabel" text="Payments method:" GridPane.rowIndex="5" visible="false">
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</Label>
<TextField fx:id="paymentMethodTextField" GridPane.rowIndex="5" GridPane.columnIndex="1" editable="false"
visible="false">
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</TextField>
<Label fx:id="fiatAmountLabel" text="Amount to transfer:" GridPane.rowIndex="5" managed="false"
visible="false">
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</Label>
<TextFieldWithCopyIcon fx:id="fiatAmountTextField" GridPane.rowIndex="5" GridPane.columnIndex="1"
managed="false" visible="false">
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</TextFieldWithCopyIcon>
<Label fx:id="holderNameLabel" text="Holder name:" GridPane.rowIndex="6" visible="false"/>
<TextFieldWithCopyIcon fx:id="holderNameTextField" GridPane.rowIndex="6" GridPane.columnIndex="1" visible="false"/>
<Label fx:id="paymentMethodLabel" text="Payments method:" GridPane.rowIndex="6" managed="false"
visible="false"/>
<Label fx:id="primaryIdLabel" text="Primary ID:" GridPane.rowIndex="7" visible="false"/>
<TextFieldWithCopyIcon fx:id="primaryIdTextField" GridPane.rowIndex="7" GridPane.columnIndex="1" visible="false"/>
<TextField fx:id="paymentMethodTextField" GridPane.rowIndex="6" GridPane.columnIndex="1" editable="false"
focusTraversable="false" mouseTransparent="true" managed="false" visible="false"/>
<Label fx:id="secondaryIdLabel" text="Secondary ID:" GridPane.rowIndex="8" visible="false"/>
<TextFieldWithCopyIcon fx:id="secondaryIdTextField" GridPane.rowIndex="8" GridPane.columnIndex="1" visible="false"/>
<Label fx:id="holderNameLabel" text="Receiver name:" GridPane.rowIndex="7" managed="false" visible="false"/>
<TextFieldWithCopyIcon fx:id="holderNameTextField" GridPane.rowIndex="7" GridPane.columnIndex="1"
managed="false" visible="false"/>
<InfoDisplay fx:id="paymentsInfoDisplay" onAction="#onOpenPaymentsHelp" rowIndex="9" gridPane="$root"
visible="false"/>
<Label fx:id="primaryIdLabel" text="IBAN:" GridPane.rowIndex="8" managed="false" visible="false"/>
<TextFieldWithCopyIcon fx:id="primaryIdTextField" GridPane.rowIndex="8" GridPane.columnIndex="1"
managed="false" visible="false"/>
<Button fx:id="paymentsButton" text="Payment started" onAction="#onPaymentStarted" GridPane.rowIndex="10"
GridPane.columnIndex="1" defaultButton="true" visible="false">
<GridPane.margin>
<Insets top="15"/>
</GridPane.margin>
</Button>
<Label fx:id="secondaryIdLabel" text="BIC:" GridPane.rowIndex="9" managed="false" visible="false"/>
<TextFieldWithCopyIcon fx:id="secondaryIdTextField" GridPane.rowIndex="9" GridPane.columnIndex="1"
managed="false" visible="false"/>
<!--
Summary
-->
<TitledGroupBg fx:id="summaryGroupBg" text="Summary" GridPane.rowIndex="5" GridPane.rowSpan="5"
GridPane.columnSpan="2" visible="false">
<GridPane.margin>
<Insets top="40.0" bottom="-10" left="-10" right="-10"/>
</GridPane.margin>
</TitledGroupBg>
<InfoDisplay fx:id="paymentsInfoDisplay" onAction="#onOpenPaymentsHelp" rowIndex="10" gridPane="$gridPane"
managed="false" visible="false"/>
<Label fx:id="btcLabel" GridPane.rowIndex="5" visible="false">
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</Label>
<TextField fx:id="btcTextField" GridPane.rowIndex="5" GridPane.columnIndex="1" editable="false"
visible="false">
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</TextField>
<Button fx:id="paymentsButton" text="Payment started" onAction="#onPaymentStarted" GridPane.rowIndex="11"
GridPane.columnIndex="1" defaultButton="true" managed="false" visible="false">
<GridPane.margin>
<Insets top="15" bottom="40"/>
</GridPane.margin>
</Button>
<Label fx:id="fiatLabel" GridPane.rowIndex="6" visible="false"/>
<TextField fx:id="fiatTextField" GridPane.rowIndex="6" GridPane.columnIndex="1" editable="false" visible="false"/>
<!--
Summary
-->
<TitledGroupBg fx:id="summaryGroupBg" text="Summary" GridPane.rowIndex="5" GridPane.rowSpan="5"
GridPane.columnSpan="2" managed="false" visible="false">
<GridPane.margin>
<Insets top="40.0" bottom="-10" left="-10" right="-10"/>
</GridPane.margin>
</TitledGroupBg>
<Label fx:id="feesLabel" text="Total fees paid:" GridPane.rowIndex="7" visible="false"/>
<TextField fx:id="feesTextField" GridPane.rowIndex="7" GridPane.columnIndex="1" editable="false" visible="false"/>
<Label fx:id="btcTradeAmountLabel" GridPane.rowIndex="5" managed="false" visible="false">
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</Label>
<TextField fx:id="btcTradeAmountTextField" GridPane.rowIndex="5" GridPane.columnIndex="1" editable="false"
focusTraversable="false" mouseTransparent="true" managed="false" visible="false">
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</TextField>
<Label fx:id="collateralLabel" text="Refunded collateral:" GridPane.rowIndex="8" visible="false"/>
<TextField fx:id="collateralTextField" GridPane.rowIndex="8" GridPane.columnIndex="1" editable="false"
visible="false"/>
<Label fx:id="fiatTradeAmountLabel" GridPane.rowIndex="6" managed="false" visible="false"/>
<TextField fx:id="fiatTradeAmountTextField" GridPane.rowIndex="6" GridPane.columnIndex="1" editable="false"
focusTraversable="false" mouseTransparent="true" managed="false" visible="false"/>
<InfoDisplay fx:id="summaryInfoDisplay" onAction="#onOpenSummaryHelp" rowIndex="9" gridPane="$root"
visible="false"/>
<Label fx:id="feesLabel" text="Total fees paid:" GridPane.rowIndex="7" managed="false" visible="false"/>
<TextField fx:id="feesTextField" GridPane.rowIndex="7" GridPane.columnIndex="1" editable="false"
focusTraversable="false" mouseTransparent="true" managed="false" visible="false"/>
<Button fx:id="openWithdrawalButton" text="Open withdrawal screen" onAction="#onOpenWithdrawal"
GridPane.rowIndex="10"
GridPane.columnIndex="1" defaultButton="true" visible="false">
<GridPane.margin>
<Insets top="15"/>
</GridPane.margin>
</Button>
<Label fx:id="collateralLabel" text="Refunded collateral:" GridPane.rowIndex="8" managed="false"
visible="false"/>
<TextField fx:id="collateralTextField" GridPane.rowIndex="8" GridPane.columnIndex="1" editable="false"
focusTraversable="false" mouseTransparent="true" managed="false" visible="false"/>
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/>
<ColumnConstraints hgrow="ALWAYS"/>
</columnConstraints>
<InfoDisplay fx:id="summaryInfoDisplay" onAction="#onOpenSummaryHelp" rowIndex="9" gridPane="$gridPane"
managed="false" visible="false"/>
<rowConstraints>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
</rowConstraints>
<!--
Withdraw
-->
<TitledGroupBg fx:id="withdrawGroupBg" text="Withdraw your bitcoins" GridPane.rowIndex="10"
GridPane.rowSpan="2"
GridPane.columnSpan="2" managed="false" visible="false">
<GridPane.margin>
<Insets top="40.0" bottom="-10" left="-10" right="-10"/>
</GridPane.margin>
</TitledGroupBg>
</GridPane>
<Label fx:id="withdrawAmountLabel" text="Amount to withdraw:" GridPane.rowIndex="10"
managed="false" visible="false">
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</Label>
<TextField fx:id="withdrawAmountTextField" GridPane.rowIndex="10" GridPane.columnIndex="1" editable="false"
focusTraversable="false" mouseTransparent="true" managed="false" visible="false">
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</TextField>
<Label fx:id="withdrawAddressLabel" text="Withdraw to address:" GridPane.rowIndex="11" managed="false"
visible="false"/>
<InputTextField fx:id="withdrawAddressTextField" GridPane.rowIndex="11" GridPane.columnIndex="1"
managed="false" visible="false"/>
<Button fx:id="withdrawButton" text="Withdrawal to external wallet" onAction="#onWithdraw"
GridPane.rowIndex="12" GridPane.columnIndex="1" defaultButton="true" managed="false"
visible="false">
<GridPane.margin>
<Insets top="15" bottom="40"/>
</GridPane.margin>
</Button>
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/>
<ColumnConstraints hgrow="ALWAYS"/>
</columnConstraints>
<rowConstraints>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
</rowConstraints>
</GridPane>
</ScrollPane>
</AnchorPane>

View File

@ -20,6 +20,7 @@ package io.bitsquare.gui.main.orders.pending;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.components.InfoDisplay;
import io.bitsquare.gui.components.InputTextField;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.components.TextFieldWithCopyIcon;
import io.bitsquare.gui.components.TitledGroupBg;
@ -44,6 +45,7 @@ import javafx.beans.value.ChangeListener;
import javafx.collections.ListChangeListener;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.util.Callback;
import org.slf4j.Logger;
@ -52,27 +54,32 @@ import org.slf4j.LoggerFactory;
public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
private static final Logger log = LoggerFactory.getLogger(PendingTradesViewCB.class);
private ChangeListener<PendingTradesListItem> selectedItemChangeListener;
private ListChangeListener<PendingTradesListItem> listChangeListener;
private ChangeListener<String> txIdChangeListener;
private ChangeListener<PendingTradesPM.State> offererStateChangeListener;
private ChangeListener<PendingTradesPM.State> takerStateChangeListener;
private ChangeListener<Throwable> faultChangeListener;
private Navigation navigation;
@FXML TitledGroupBg titledGroupBg, paymentsGroupBg, summaryGroupBg;
@FXML ScrollPane scrollPane;
@FXML GridPane gridPane;
@FXML TitledGroupBg titledGroupBg, paymentsGroupBg, summaryGroupBg, withdrawGroupBg;
@FXML ProcessStepBar processBar;
@FXML Label statusLabel, txIdLabel, paymentMethodLabel, holderNameLabel, primaryIdLabel, secondaryIdLabel,
btcLabel, fiatLabel, feesLabel, collateralLabel;
@FXML TextField statusTextField, paymentMethodTextField, btcTextField, fiatTextField, feesTextField,
collateralTextField;
@FXML Label statusLabel, txIdLabel, paymentMethodLabel, fiatAmountLabel, holderNameLabel, primaryIdLabel,
secondaryIdLabel, btcTradeAmountLabel, fiatTradeAmountLabel, feesLabel, collateralLabel,
withdrawAmountLabel, withdrawAddressLabel;
@FXML TextField statusTextField, paymentMethodTextField, btcTradeAmountTextField, fiatTradeAmountTextField,
feesTextField, collateralTextField, withdrawAmountTextField;
@FXML InputTextField withdrawAddressTextField;
@FXML TxIdTextField txIdTextField;
@FXML InfoDisplay infoDisplay, paymentsInfoDisplay, summaryInfoDisplay;
@FXML Button confirmPaymentReceiptButton, paymentsButton, openWithdrawalButton;
@FXML TextFieldWithCopyIcon holderNameTextField, secondaryIdTextField, primaryIdTextField;
@FXML Button confirmPaymentReceiptButton, paymentsButton, withdrawButton;
@FXML TextFieldWithCopyIcon fiatAmountTextField, holderNameTextField, secondaryIdTextField, primaryIdTextField;
@FXML TableView<PendingTradesListItem> table;
@FXML TableColumn<PendingTradesListItem, PendingTradesListItem> priceColumn, amountColumn, volumeColumn,
directionColumn, dateColumn, tradeIdColumn, selectColumn;
private Navigation navigation;
directionColumn, dateColumn, tradeIdColumn;
///////////////////////////////////////////////////////////////////////////////////////////
@ -99,7 +106,13 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
setPriceColumnCellFactory();
setVolumeColumnCellFactory();
setDateColumnCellFactory();
setSelectColumnCellFactory();
scrollPane.vvalueProperty().addListener((ov, oldValue, newValue) -> {
log.debug("#### vvalueProperty " + newValue);
});
scrollPane.viewportBoundsProperty().addListener((ov, oldValue, newValue) -> {
log.debug("#### viewportBoundsProperty " + newValue);
});
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
table.setPlaceholder(new Label("No pending trades available"));
@ -125,6 +138,8 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
takerStateChangeListener = (ov, oldValue, newValue) -> applyTakerState(newValue);
faultChangeListener = (ov, oldValue, newValue) -> onFault(newValue);
withdrawAddressTextField.setValidator(presentationModel.getBtcAddressValidator());
withdrawButton.disableProperty().bind(presentationModel.withdrawalButtonDisable);
super.initialize(url, rb);
}
@ -146,6 +161,10 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
/* table.requestFocus();
table.getFocusModel().focus( table.getSelectionModel().getSelectedIndex());*/
withdrawAddressTextField.focusedProperty().addListener((ov, oldValue, newValue) -> {
if (oldValue && !newValue)
presentationModel.withdrawAddressFocusOut(withdrawAddressTextField.getText());
});
updateScreen();
}
@ -184,12 +203,12 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
}
@FXML
void onOpenWithdrawal() {
public void onWithdraw() {
setSummaryControlsVisible(false);
presentationModel.closeSummary();
presentationModel.removePendingTrade();
presentationModel.withdraw(withdrawAddressTextField.getText());
Platform.runLater(() ->
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.FUNDS, Navigation.Item.WITHDRAWAL));
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ORDERS, Navigation.Item.CLOSED_TRADES));
}
@FXML
@ -228,6 +247,14 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
txIdTextField.setVisible(dataAvailable);
infoDisplay.setVisible(dataAvailable);
titledGroupBg.setManaged(dataAvailable);
processBar.setManaged(dataAvailable);
statusLabel.setManaged(dataAvailable);
statusTextField.setManaged(dataAvailable);
txIdLabel.setManaged(dataAvailable);
txIdTextField.setManaged(dataAvailable);
infoDisplay.setManaged(dataAvailable);
if (dataAvailable) {
if (presentationModel.isOfferer())
setupScreenForOfferer();
@ -293,6 +320,7 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
"confirmations if you want more security.");
paymentMethodTextField.setText(presentationModel.getPaymentMethod());
fiatAmountTextField.setText(presentationModel.getFiatAmount());
holderNameTextField.setText(presentationModel.getHolderName());
primaryIdTextField.setText(presentationModel.getPrimaryId());
secondaryIdTextField.setText(presentationModel.getSecondaryId());
@ -314,7 +342,6 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
break;
case OFFERER_BUYER_COMPLETED:
processBar.setSelectedIndex(3);
setSummaryControlsVisible(true);
statusTextField.setText("Congratulations! Trade has successfully completed.");
@ -322,16 +349,17 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
"wallet. To protect your privacy you should take care that your trades are not merged " +
"in " +
"that external wallet. For more information about privacy see our help pages.");
infoDisplay.layout();
btcLabel.setText("You have bought:");
fiatLabel.setText("You have paid:");
btcTextField.setText(presentationModel.getTradeVolume());
fiatTextField.setText(presentationModel.getFiatVolume());
btcTradeAmountLabel.setText("You have bought:");
fiatTradeAmountLabel.setText("You have paid:");
btcTradeAmountTextField.setText(presentationModel.getTradeVolume());
fiatTradeAmountTextField.setText(presentationModel.getFiatVolume());
feesTextField.setText(presentationModel.getTotalFees());
collateralTextField.setText(presentationModel.getCollateral());
summaryInfoDisplay.setText("Your security deposit has been refunded to you. " +
"You can review the details to that trade any time in the closed trades section.");
withdrawAmountTextField.setText(presentationModel.getAmountToWithdraw());
break;
}
}
@ -340,6 +368,7 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
private void applyTakerState(PendingTradesPM.State state) {
confirmPaymentReceiptButton.setVisible(false);
confirmPaymentReceiptButton.setManaged(false);
setSummaryControlsVisible(false);
@ -374,6 +403,7 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
processBar.setSelectedIndex(2);
confirmPaymentReceiptButton.setVisible(true);
confirmPaymentReceiptButton.setManaged(true);
statusTextField.setText(BSResources.get("The Bitcoin buyer has started the {0} payment." +
"Check your payments account and confirm when you have received the payment.",
@ -389,21 +419,22 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
setSummaryControlsVisible(true);
statusTextField.setText("Congratulations! Trade has successfully completed.");
infoDisplay.setText("The trade is now completed and you can withdraw the refunded Bitcoin from " +
"the security deposit to any external wallet. " +
"To protect your privacy you should take care that your coins are not merged in " +
"that external wallet. For more information about privacy see our help pages.");
btcLabel.setText("You have sold:");
fiatLabel.setText("You have received:");
btcTextField.setText(presentationModel.getTradeVolume());
fiatTextField.setText(presentationModel.getFiatVolume());
btcTradeAmountLabel.setText("You have sold:");
fiatTradeAmountLabel.setText("You have received:");
btcTradeAmountTextField.setText(presentationModel.getTradeVolume());
fiatTradeAmountTextField.setText(presentationModel.getFiatVolume());
feesTextField.setText(presentationModel.getTotalFees());
collateralTextField.setText(presentationModel.getCollateral());
summaryInfoDisplay.setText("Your security deposit has been refunded to you. " +
"You can review the details to that trade any time in the closed trades section.");
withdrawAmountTextField.setText(presentationModel.getAmountToWithdraw());
break;
}
}
@ -418,29 +449,85 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
private void setPaymentsControlsVisible(boolean visible) {
paymentsGroupBg.setVisible(visible);
paymentMethodLabel.setVisible(visible);
fiatAmountLabel.setVisible(visible);
holderNameLabel.setVisible(visible);
primaryIdLabel.setVisible(visible);
secondaryIdLabel.setVisible(visible);
paymentMethodTextField.setVisible(visible);
paymentsInfoDisplay.setVisible(visible);
paymentsButton.setVisible(visible);
fiatAmountTextField.setVisible(visible);
holderNameTextField.setVisible(visible);
primaryIdTextField.setVisible(visible);
secondaryIdTextField.setVisible(visible);
paymentsGroupBg.setManaged(visible);
paymentMethodLabel.setManaged(visible);
fiatAmountLabel.setManaged(visible);
holderNameLabel.setManaged(visible);
primaryIdLabel.setManaged(visible);
secondaryIdLabel.setManaged(visible);
paymentMethodTextField.setManaged(visible);
paymentsInfoDisplay.setManaged(visible);
paymentsButton.setManaged(visible);
fiatAmountTextField.setManaged(visible);
holderNameTextField.setManaged(visible);
primaryIdTextField.setManaged(visible);
secondaryIdTextField.setManaged(visible);
if (visible)
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
else
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scrollPane.layout();
}
private void setSummaryControlsVisible(boolean visible) {
summaryGroupBg.setVisible(visible);
btcLabel.setVisible(visible);
btcTextField.setVisible(visible);
fiatLabel.setVisible(visible);
fiatTextField.setVisible(visible);
btcTradeAmountLabel.setVisible(visible);
btcTradeAmountTextField.setVisible(visible);
fiatTradeAmountLabel.setVisible(visible);
fiatTradeAmountTextField.setVisible(visible);
feesLabel.setVisible(visible);
feesTextField.setVisible(visible);
collateralLabel.setVisible(visible);
collateralTextField.setVisible(visible);
summaryInfoDisplay.setVisible(visible);
openWithdrawalButton.setVisible(visible);
withdrawGroupBg.setVisible(visible);
withdrawAmountLabel.setVisible(visible);
withdrawAmountTextField.setVisible(visible);
withdrawAddressLabel.setVisible(visible);
withdrawAddressTextField.setVisible(visible);
withdrawButton.setVisible(visible);
summaryGroupBg.setManaged(visible);
btcTradeAmountLabel.setManaged(visible);
btcTradeAmountTextField.setManaged(visible);
fiatTradeAmountLabel.setManaged(visible);
fiatTradeAmountTextField.setManaged(visible);
feesLabel.setManaged(visible);
feesTextField.setManaged(visible);
collateralLabel.setManaged(visible);
collateralTextField.setManaged(visible);
summaryInfoDisplay.setManaged(visible);
withdrawGroupBg.setManaged(visible);
withdrawAmountLabel.setManaged(visible);
withdrawAmountTextField.setManaged(visible);
withdrawAddressLabel.setManaged(visible);
withdrawAddressTextField.setManaged(visible);
withdrawButton.setManaged(visible);
if (visible) {
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
withdrawAddressTextField.requestFocus();
scrollPane.setVvalue(scrollPane.getVmax());
}
else {
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
}
scrollPane.layout();
}
@ -583,35 +670,5 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
});
}
private void setSelectColumnCellFactory() {
selectColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
selectColumn.setCellFactory(new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>,
TableCell<PendingTradesListItem, PendingTradesListItem>>() {
@Override
public TableCell<PendingTradesListItem, PendingTradesListItem> call(
TableColumn<PendingTradesListItem, PendingTradesListItem> column) {
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
final Button button = new Button("Select");
@Override
public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
button.setOnAction(event -> showTradeDetails(item));
setGraphic(button);
}
else {
setGraphic(null);
}
}
};
}
private void showTradeDetails(PendingTradesListItem item) {
table.getSelectionModel().select(item);
}
});
}
}

View File

@ -28,8 +28,6 @@
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.trade.createoffer.CreateOfferViewCB"
AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0"
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"
xmlns:fx="http://javafx.com/fxml">
<ScrollPane fx:id="scrollPane" hbarPolicy="NEVER" vbarPolicy="NEVER" fitToWidth="true" fitToHeight="true"
@ -152,9 +150,8 @@
</GridPane.margin>
</HBox>
<TextField fx:id="totalToPayTextField" promptText="%createOffer.fundsBox.totalsNeeded.prompt"
GridPane.columnIndex="1"
GridPane.rowIndex="4"
editable="false" focusTraversable="false" visible="false">
GridPane.columnIndex="1" GridPane.rowIndex="4"
mouseTransparent="true" editable="false" focusTraversable="false" visible="false">
<GridPane.margin>
<Insets top="10.0"/>
</GridPane.margin>
@ -205,31 +202,31 @@
</HBox>
<TextField fx:id="acceptedCountriesTextField" GridPane.columnIndex="1" GridPane.rowIndex="9"
visible="false"
editable="false" focusTraversable="false"/>
mouseTransparent="true" editable="false" focusTraversable="false"/>
<HBox GridPane.rowIndex="10" spacing="4" alignment="CENTER_RIGHT">
<Label fx:id="acceptedLanguagesLabel" text="%createOffer.advancedBox.languages" visible="false"/>
<Label fx:id="acceptedLanguagesLabelIcon" visible="false"/>
</HBox>
<TextField fx:id="acceptedLanguagesTextField" GridPane.columnIndex="1" GridPane.rowIndex="10"
editable="false" focusTraversable="false" visible="false"/>
mouseTransparent="true" editable="false" focusTraversable="false" visible="false"/>
<HBox GridPane.rowIndex="11" spacing="4" alignment="CENTER_RIGHT">
<Label fx:id="acceptedArbitratorsLabel" text="%createOffer.advancedBox.arbitrators" visible="false"/>
<Label fx:id="acceptedArbitratorsLabelIcon" visible="false"/>
</HBox>
<TextField fx:id="acceptedArbitratorsTextField" GridPane.columnIndex="1" GridPane.rowIndex="11"
editable="false" focusTraversable="false" visible="false"/>
mouseTransparent="true" editable="false" focusTraversable="false" visible="false"/>
<Label fx:id="bankAccountTypeLabel" text="%createOffer.advancedBox.txType" GridPane.rowIndex="12"
visible="false"/>
<TextField fx:id="bankAccountTypeTextField" GridPane.columnIndex="1" GridPane.rowIndex="12" editable="false"
focusTraversable="false" visible="false"/>
<TextField fx:id="bankAccountTypeTextField" GridPane.columnIndex="1" GridPane.rowIndex="12"
mouseTransparent="true" editable="false" focusTraversable="false" visible="false"/>
<Label fx:id="bankAccountCurrencyLabel" text="%createOffer.advancedBox.currency" GridPane.rowIndex="13"
visible="false"/>
<TextField fx:id="bankAccountCurrencyTextField" GridPane.rowIndex="13" GridPane.columnIndex="1"
editable="false" focusTraversable="false" visible="false"/>
mouseTransparent="true" editable="false" focusTraversable="false" visible="false"/>
<Label fx:id="bankAccountCountyLabel" text="%createOffer.advancedBox.county" GridPane.rowIndex="14"
visible="false">
@ -238,7 +235,7 @@
</GridPane.margin>
</Label>
<TextField fx:id="bankAccountCountyTextField" GridPane.rowIndex="14" GridPane.columnIndex="1"
editable="false" focusTraversable="false" visible="false">
mouseTransparent="true" editable="false" focusTraversable="false" visible="false">
<GridPane.margin>
<Insets bottom="5.0"/>
</GridPane.margin>

View File

@ -185,6 +185,17 @@ public class CreateOfferViewCB extends CachedViewCB<CreateOfferPM> {
@FXML
void onShowPayFundsScreen() {
Popups.openInfo("To ensure that both traders are behaving fair you need to put in a security deposit to an " +
"offer. That will be refunded to you after the trade has successful completed.");
/*
Popups.openInfo("To ensure that both traders are behaving fair you need to put in a security deposit to an " +
"offer. That will be refunded to you after the trade has successful completed. In case of a " +
"dispute and the arbitrator will take the security deposit from the dishonest trader as his payment " +
"for the dispute resolution. The security deposit will be included in the deposit transaction at the " +
"moment when a trader accept your offer. As long as your offer is not taken by another trader, " +
"the security deposit will not leave your trading wallet, and will be refunded when you cancel your " +
"offer.");
*/
priceAmountPane.setInactive();
showPaymentInfoScreenButton.setVisible(false);

View File

@ -87,7 +87,8 @@
<VBox spacing="4">
<Label fx:id="priceDescriptionLabel" id="input-description-label" prefWidth="170"/>
<TextField fx:id="priceTextField" id="text-input-with-currency-text-field"
prefWidth="170" alignment="CENTER_RIGHT" editable="false"/>
prefWidth="170" alignment="CENTER_RIGHT" mouseTransparent="true" editable="false"
focusTraversable="false"/>
</VBox>
<Label text="=">
@ -102,7 +103,8 @@
<VBox spacing="4">
<Label fx:id="volumeDescriptionLabel" id="input-description-label" prefWidth="170"/>
<TextField fx:id="volumeTextField" id="text-input-with-currency-text-field"
prefWidth="170" alignment="CENTER_RIGHT" editable="false"/>
prefWidth="170" alignment="CENTER_RIGHT" mouseTransparent="true" editable="false"
focusTraversable="false"/>
</VBox>
</HBox>
@ -141,9 +143,8 @@
</GridPane.margin>
</HBox>
<TextField fx:id="totalToPayTextField" promptText="%takeOffer.fundsBox.totalsNeeded.prompt"
GridPane.columnIndex="1"
GridPane.rowIndex="4"
editable="false" focusTraversable="false" visible="false">
GridPane.columnIndex="1" GridPane.rowIndex="4" mouseTransparent="true" editable="false"
focusTraversable="false" visible="false">
<GridPane.margin>
<Insets top="10.0"/>
</GridPane.margin>
@ -192,28 +193,27 @@
</GridPane.margin>
</Label>
<TextField fx:id="acceptedCountriesTextField" GridPane.columnIndex="1" GridPane.rowIndex="9"
visible="false"
editable="false" focusTraversable="false"/>
mouseTransparent="true" visible="false" editable="false" focusTraversable="false"/>
<Label fx:id="acceptedLanguagesLabel" text="%takeOffer.advancedBox.languages" GridPane.rowIndex="10"
visible="false"/>
<TextField fx:id="acceptedLanguagesTextField" GridPane.columnIndex="1" GridPane.rowIndex="10"
editable="false" focusTraversable="false" visible="false"/>
mouseTransparent="true" editable="false" focusTraversable="false" visible="false"/>
<Label fx:id="acceptedArbitratorsLabel" text="%takeOffer.advancedBox.arbitrators" GridPane.rowIndex="11"
visible="false"/>
<TextField fx:id="acceptedArbitratorsTextField" GridPane.columnIndex="1" GridPane.rowIndex="11"
editable="false" focusTraversable="false" visible="false"/>
mouseTransparent="true" editable="false" focusTraversable="false" visible="false"/>
<Label fx:id="bankAccountTypeLabel" text="%takeOffer.advancedBox.txType" GridPane.rowIndex="12"
visible="false"/>
<TextField fx:id="bankAccountTypeTextField" GridPane.columnIndex="1" GridPane.rowIndex="12" editable="false"
focusTraversable="false" visible="false"/>
mouseTransparent="true" focusTraversable="false" visible="false"/>
<Label fx:id="bankAccountCurrencyLabel" text="%takeOffer.advancedBox.currency" GridPane.rowIndex="13"
visible="false"/>
<TextField fx:id="bankAccountCurrencyTextField" GridPane.rowIndex="13" GridPane.columnIndex="1"
editable="false" focusTraversable="false" visible="false"/>
mouseTransparent="true" editable="false" focusTraversable="false" visible="false"/>
<Label fx:id="bankAccountCountyLabel" text="%takeOffer.advancedBox.county" GridPane.rowIndex="14"
visible="false">
@ -222,7 +222,7 @@
</GridPane.margin>
</Label>
<TextField fx:id="bankAccountCountyTextField" GridPane.rowIndex="14" GridPane.columnIndex="1"
editable="false" focusTraversable="false" visible="false">
mouseTransparent="true" editable="false" focusTraversable="false" visible="false">
<GridPane.margin>
<Insets bottom="5.0"/>
</GridPane.margin>

View File

@ -48,7 +48,7 @@ public class Profiler {
@Override
public void handle(long l) {
long elapsed = (System.currentTimeMillis() - lastFPSTime);
if (elapsed > 19)
if (elapsed > 50)
log.trace("Profiler: last frame used {}ms", elapsed);
lastFPSTime = System.currentTimeMillis();

View File

@ -0,0 +1,76 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.util.validation;
import com.google.bitcoin.core.Address;
import com.google.bitcoin.core.AddressFormatException;
import com.google.bitcoin.core.NetworkParameters;
import javax.inject.Inject;
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 final class BtcAddressValidator extends InputValidator {
private static final Logger log = LoggerFactory.getLogger(BtcAddressValidator.class);
private NetworkParameters networkParameters;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public BtcAddressValidator(NetworkParameters networkParameters) {
this.networkParameters = networkParameters;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public ValidationResult validate(String input) {
ValidationResult result = validateIfNotEmpty(input);
if (result.isValid)
return validateBtcAddress(input);
else
return result;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private ValidationResult validateBtcAddress(String input) {
try {
new Address(networkParameters, input);
return new ValidationResult(true);
} catch (AddressFormatException e) {
return new ValidationResult(false, "Bitcoin address is a valid format");
}
}
}

View File

@ -33,7 +33,6 @@ import org.slf4j.LoggerFactory;
*/
public final class BtcValidator extends NumberValidator {
private static final Logger log = LoggerFactory.getLogger(BtcValidator.class);
private ValidationResult externalValidationResult;
///////////////////////////////////////////////////////////////////////////////////////////
@ -42,9 +41,6 @@ public final class BtcValidator extends NumberValidator {
@Override
public ValidationResult validate(String input) {
if (externalValidationResult != null)
return externalValidationResult;
ValidationResult result = validateIfNotEmpty(input);
if (result.isValid) {
input = cleanInput(input);
@ -61,16 +57,6 @@ public final class BtcValidator extends NumberValidator {
return result;
}
/**
* Used to integrate external validation (e.g. for MinAmount/Amount)
* TODO To be improved but does the job for now...
*
* @param externalValidationResult
*/
public void overrideResult(ValidationResult externalValidationResult) {
this.externalValidationResult = externalValidationResult;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods