New UI for Second trade process (WIP)

This commit is contained in:
Manfred Karrer 2015-03-31 23:53:21 +02:00
parent 0700a53561
commit 37a358b716
23 changed files with 1266 additions and 1154 deletions

View file

@ -84,7 +84,7 @@ public class BitsquareApp extends Application {
CachingViewLoader viewLoader = injector.getInstance(CachingViewLoader.class);
View view = viewLoader.load(MainView.class);
scene = new Scene((Parent) view.getRoot(), 1000, 600);
scene = new Scene((Parent) view.getRoot(), 1000, 620);
scene.getStylesheets().setAll(
"/io/bitsquare/gui/bitsquare.css",
"/io/bitsquare/gui/images.css");
@ -114,7 +114,7 @@ public class BitsquareApp extends Application {
primaryStage.setTitle(env.getRequiredProperty(APP_NAME_KEY));
primaryStage.setScene(scene);
primaryStage.setMinWidth(750);
primaryStage.setMinHeight(500);
primaryStage.setMinHeight(620);
// on windows the title icon is also used as task bar icon in a larger size
// on Linux no title icon is supported but also a large task bar icon is derived form that title icon

View file

@ -186,6 +186,11 @@ textfield */
/*-fx-background-color: transparent;*/
}
/* horizontal scrollbars are never needed and are flickering at scaling so lets turn them off */
.table-view > .scroll-bar:horizontal {
-fx-opacity: 0;
}
.table-view:focused {
-fx-background-color: -fx-box-border, -fx-control-inner-background;
-fx-background-insets: 0, 1;
@ -481,6 +486,7 @@ textfield */
}
#trade-wizard-item-background-active {
-fx-font-weight: bold;
-fx-body-color: linear-gradient(to bottom, #f1f6f7, #e7f5f9);
-fx-outer-border: linear-gradient(to bottom, #b5e1ef, #6aa4b6);
-fx-background-color: -fx-shadow-highlight-color,

View file

@ -41,6 +41,7 @@ public class TxIdTextField extends AnchorPane {
private final ConfidenceProgressIndicator progressIndicator;
private final Label copyIcon;
private TxConfidenceListener txConfidenceListener;
private WalletService walletService;
///////////////////////////////////////////////////////////////////////////////////////////
@ -79,6 +80,7 @@ public class TxIdTextField extends AnchorPane {
}
public void setup(WalletService walletService, String txID) {
this.walletService = walletService;
if (txConfidenceListener != null)
walletService.removeTxConfidenceListener(txConfidenceListener);
@ -107,6 +109,11 @@ public class TxIdTextField extends AnchorPane {
copyIcon.setOnMouseClicked(e -> Utilities.copyToClipboard(txID));
}
public void cleanup() {
if (walletService != null && txConfidenceListener != null)
walletService.removeTxConfidenceListener(txConfidenceListener);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters/Setters

View file

@ -0,0 +1,139 @@
/*
* 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.main.portfolio.pending;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.main.portfolio.pending.steps.CompletedView;
import io.bitsquare.gui.main.portfolio.pending.steps.StartFiatView;
import io.bitsquare.gui.main.portfolio.pending.steps.TradeWizardItem;
import io.bitsquare.gui.main.portfolio.pending.steps.WaitFiatReceivedView;
import io.bitsquare.gui.main.portfolio.pending.steps.WaitTxInBlockchainView;
import io.bitsquare.locale.BSResources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OffererAsBuyerSubView extends TradeSubView {
private static final Logger log = LoggerFactory.getLogger(OffererAsBuyerSubView.class);
private TradeWizardItem waitTxInBlockchain;
private TradeWizardItem startFiat;
private TradeWizardItem waitFiatReceived;
private TradeWizardItem completed;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
///////////////////////////////////////////////////////////////////////////////////////////
public OffererAsBuyerSubView(PendingTradesViewModel model) {
super(model);
}
@Override
public void activate() {
super.activate();
}
@Override
public void deactivate() {
super.deactivate();
}
@Override
protected void addWizards() {
waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation");
startFiat = new TradeWizardItem(StartFiatView.class, "Start payment");
waitFiatReceived = new TradeWizardItem(WaitFiatReceivedView.class, "Wait until payment has arrived");
completed = new TradeWizardItem(CompletedView.class, "Completed");
leftVBox.getChildren().addAll(waitTxInBlockchain, startFiat, waitFiatReceived, completed);
}
///////////////////////////////////////////////////////////////////////////////////////////
// State
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void applyState(PendingTradesViewModel.ViewState viewState) {
log.debug("applyState " + viewState);
waitTxInBlockchain.inactive();
startFiat.inactive();
waitFiatReceived.inactive();
completed.inactive();
switch (viewState) {
case OFFERER_BUYER_WAIT_TX_CONF:
showItem(waitTxInBlockchain);
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText("Deposit transaction has been published. You need to wait for at least " +
"one block chain confirmation.");
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoDisplayField("You need to wait for at least one block chain confirmation to" +
" be sure that the deposit funding has not been double spent. For higher trade volumes we" +
" recommend to wait up to 6 confirmations.");
break;
case OFFERER_BUYER_START_PAYMENT:
waitTxInBlockchain.done();
showItem(startFiat);
break;
case OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED:
waitTxInBlockchain.done();
startFiat.done();
showItem(waitFiatReceived);
((WaitFiatReceivedView) tradeStepDetailsView).setInfoLabelText(BSResources.get("Waiting for the Bitcoin sellers confirmation " +
"that the {0} payment has arrived.",
model.getCurrencyCode()));
((WaitFiatReceivedView) tradeStepDetailsView).setInfoDisplayField(BSResources.get("When the confirmation that the {0} payment arrived at " +
"the Bitcoin sellers payment account, the payout transaction will be published.",
model.getCurrencyCode()));
break;
case OFFERER_BUYER_COMPLETED:
waitTxInBlockchain.done();
startFiat.done();
waitFiatReceived.done();
showItem(completed);
CompletedView completedView = (CompletedView) tradeStepDetailsView;
completedView.setBtcTradeAmountLabelText("You have bought:");
completedView.setFiatTradeAmountLabelText("You have paid:");
completedView.setBtcTradeAmountTextFieldText(model.getTradeVolume());
completedView.setFiatTradeAmountTextFieldText(model.getFiatVolume());
completedView.setFeesTextFieldText(model.getTotalFees());
completedView.setSecurityDepositTextFieldText(model.getSecurityDeposit());
completedView.setSummaryInfoDisplayText("Your security deposit has been refunded to you. " +
"You can review the details to that trade any time in the closed trades screen.");
completedView.setWithdrawAmountTextFieldText(model.getAmountToWithdraw());
break;
case MESSAGE_SENDING_FAILED:
Popups.openWarningPopup("Sending message to trading peer failed.", model.getErrorMessage());
break;
case EXCEPTION:
Popups.openExceptionPopup(model.getTradeException());
break;
}
if (tradeStepDetailsView != null)
tradeStepDetailsView.activate();
}
}

View file

@ -23,6 +23,7 @@ import io.bitsquare.common.viewfx.model.Activatable;
import io.bitsquare.common.viewfx.model.DataModel;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.offer.Offer;
import io.bitsquare.trade.Contract;
import io.bitsquare.trade.OffererAsBuyerTrade;
import io.bitsquare.trade.OffererTrade;
import io.bitsquare.trade.TakerAsSellerTrade;
@ -37,8 +38,6 @@ import com.google.inject.Inject;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
@ -71,6 +70,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
final ObjectProperty<Trade.ProcessState> takerProcessState = new SimpleObjectProperty<>();
final ObjectProperty<Trade.ProcessState> offererProcessState = new SimpleObjectProperty<>();
final ObjectProperty<Trade> currentTrade = new SimpleObjectProperty<>();
@Inject
public PendingTradesDataModel(TradeManager tradeManager, WalletService walletService, User user) {
@ -116,36 +116,48 @@ class PendingTradesDataModel implements Activatable, DataModel {
removeListenerFromSelectedTrade();
selectedItem = item;
isOfferer = getTrade().getOffer().getP2PSigPubKey().equals(user.getP2PSigPubKey());
Trade trade = getTrade();
if (trade instanceof TakerAsSellerTrade)
takerProcessState.bind(trade.processStateProperty());
else
offererProcessState.bind(trade.processStateProperty());
if (item == null) {
if (currentTrade != null) {
takerProcessState.unbind();
offererProcessState.unbind();
}
currentTrade.set(null);
}
else {
currentTrade.set(item.getTrade());
log.trace("selectTrade trade.stateProperty().get() " + trade.processStateProperty().get());
Trade trade = item.getTrade();
isOfferer = trade.getOffer().getP2PSigPubKey().equals(user.getP2PSigPubKey());
if (trade instanceof TakerAsSellerTrade)
takerProcessState.bind(trade.processStateProperty());
else
offererProcessState.bind(trade.processStateProperty());
if (trade.getDepositTx() != null)
txId.set(trade.getDepositTx().getHashAsString());
if (trade.getDepositTx() != null)
txId.set(trade.getDepositTx().getHashAsString());
}
}
void fiatPaymentStarted() {
((OffererAsBuyerTrade) getTrade()).onFiatPaymentStarted();
if (getTrade() != null)
((OffererAsBuyerTrade) getTrade()).onFiatPaymentStarted();
}
void fiatPaymentReceived() {
((TakerAsSellerTrade) getTrade()).onFiatPaymentReceived();
if (getTrade() != null)
((TakerAsSellerTrade) getTrade()).onFiatPaymentReceived();
}
void withdraw(String toAddress) {
tradeManager.requestWithdraw(toAddress,
getTrade(),
() -> log.debug("requestWithdraw was successful"),
(errorMessage, throwable) -> {
log.error(errorMessage);
Popups.openExceptionPopup(throwable);
});
if (getTrade() != null) {
tradeManager.requestWithdraw(toAddress,
getTrade(),
() -> log.debug("requestWithdraw was successful"),
(errorMessage, throwable) -> {
log.error(errorMessage);
Popups.openExceptionPopup(throwable);
});
/*
@ -174,6 +186,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
Popups.openErrorPopup("Wrong inputs", "Please check the inputs.");
}
}*/
}
}
ObservableList<PendingTradesListItem> getList() {
@ -184,10 +197,10 @@ class PendingTradesDataModel implements Activatable, DataModel {
return isOfferer;
}
@Nullable
/* @Nullable
Trade getTrade() {
return selectedItem != null ? selectedItem.getTrade() : null;
}
}*/
Coin getTotalFees() {
return FeePolicy.TX_FEE.add(isOfferer() ? FeePolicy.CREATE_OFFER_FEE : FeePolicy.TAKE_OFFER_FEE);
@ -206,11 +219,17 @@ class PendingTradesDataModel implements Activatable, DataModel {
}
Throwable getTradeException() {
return getTrade().getThrowable();
if (getTrade() != null)
return getTrade().getThrowable();
else
return null;
}
String getErrorMessage() {
return getTrade().getErrorMessage();
if (getTrade() != null)
return getTrade().getErrorMessage();
else
return null;
}
public Offer.Direction getDirection(Offer offer) {
@ -237,5 +256,18 @@ class PendingTradesDataModel implements Activatable, DataModel {
return amountToWithdraw;
}
public Contract getContract() {
if (getTrade() != null)
return getTrade().getContract();
else
return null;
}
public Trade getTrade() {
if (currentTrade.get() != null)
return currentTrade.get();
else
return null;
}
}

View file

@ -1,75 +0,0 @@
/*
* 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.main.portfolio.pending;
import io.bitsquare.gui.main.portfolio.pending.steps.CompletedView;
import io.bitsquare.gui.main.portfolio.pending.steps.StartFiatView;
import io.bitsquare.gui.main.portfolio.pending.steps.WaitView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PendingTradesOffererAsBuyerView extends PendingTradesStepsView {
private static final Logger log = LoggerFactory.getLogger(PendingTradesOffererAsBuyerView.class);
private TradeWizardItem waitTxConfirm;
private TradeWizardItem startFiat;
private TradeWizardItem waitFiatReceived;
private TradeWizardItem completed;
public PendingTradesOffererAsBuyerView() {
super();
}
public void activate() {
showWaitTxConfirm();
}
public void deactivate() {
}
public void showWaitTxConfirm() {
showItem(waitTxConfirm);
}
public void showStartFiat() {
showItem(startFiat);
}
public void showWaitFiatReceived() {
showItem(waitFiatReceived);
}
public void showCompleted() {
showItem(completed);
}
@Override
protected void addWizards() {
waitTxConfirm = new TradeWizardItem(WaitView.class, "Wait for blockchain confirmation");
startFiat = new TradeWizardItem(StartFiatView.class, "Start payment");
waitFiatReceived = new TradeWizardItem(WaitView.class, "Wait until payment has arrived");
completed = new TradeWizardItem(CompletedView.class, "Completed");
leftVBox.getChildren().addAll(waitTxConfirm, startFiat, waitFiatReceived, completed);
}
}

View file

@ -1,91 +0,0 @@
/*
* 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.main.portfolio.pending;
import io.bitsquare.gui.util.Layout;
import javafx.scene.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class PendingTradesStepsView extends HBox {
private static final Logger log = LoggerFactory.getLogger(PendingTradesStepsView.class);
protected VBox leftVBox;
protected AnchorPane contentPane;
protected TradeWizardItem current;
public PendingTradesStepsView() {
setSpacing(Layout.PADDING_WINDOW);
buildViews();
}
public void activate() {
}
public void deactivate() {
}
protected void buildViews() {
addLeftBox();
addContentPane();
addWizards();
activate();
}
abstract protected void addWizards();
protected void showItem(TradeWizardItem item) {
if (current != null)
current.onCompleted();
current = item;
current.show();
loadView(item.getViewClass());
}
protected void loadView(Class<? extends Node> viewClass) {
Node view = null;
try {
view = viewClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
contentPane.getChildren().setAll(view);
}
private void addLeftBox() {
leftVBox = new VBox();
leftVBox.setSpacing(Layout.SPACING_VBOX);
getChildren().add(leftVBox);
}
private void addContentPane() {
contentPane = new AnchorPane();
HBox.setHgrow(contentPane, Priority.SOMETIMES);
getChildren().add(contentPane);
}
}

View file

@ -17,258 +17,58 @@
~ along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
-->
<?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?>
<?import io.bitsquare.gui.components.TitledSeparator?>
<?import io.bitsquare.gui.components.TxIdTextField?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.portfolio.pending.PendingTradesView"
xmlns:fx="http://javafx.com/fxml">
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.portfolio.pending.PendingTradesView"
xmlns:fx="http://javafx.com/fxml">
<ScrollPane fx:id="scrollPane" fitToWidth="true" fitToHeight="true"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
AnchorPane.bottomAnchor="0.0">
<AnchorPane minHeight="145" VBox.vgrow="SOMETIMES">
<VBox.margin>
<Insets top="20.0" left="20" right="20" bottom="0"/>
</VBox.margin>
<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>
<TitledSeparator text="Open trades" AnchorPane.topAnchor="0" AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0"/>
<TitledSeparator text="Open trades" GridPane.rowIndex="0" GridPane.columnIndex="0"
GridPane.columnSpan="2"/>
<TableView fx:id="table" AnchorPane.topAnchor="20" AnchorPane.bottomAnchor="20" AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="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="idColumn" minWidth="100" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="id"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Date" fx:id="dateColumn" minWidth="130">
<cellValueFactory>
<PropertyValueFactory property="date"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Trade amount in BTC" fx:id="tradeAmountColumn" minWidth="130" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="tradeAmount"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Price" fx:id="priceColumn" minWidth="100" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="price"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Trade amount in EUR" fx:id="tradeVolumeColumn" minWidth="130" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="tradeVolume"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="80" sortable="false"/>
</columns>
</TableView>
<columns>
<TableColumn text="Trade ID" fx:id="idColumn" minWidth="100" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="id"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Date" fx:id="dateColumn" minWidth="130">
<cellValueFactory>
<PropertyValueFactory property="date"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Trade amount in BTC" fx:id="tradeAmountColumn" minWidth="130" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="tradeAmount"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Price" fx:id="priceColumn" minWidth="100" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="price"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Trade amount in EUR" fx:id="tradeVolumeColumn" minWidth="130" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="tradeVolume"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="80" sortable="false"/>
</columns>
</TableView>
</AnchorPane>
<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>
<AnchorPane fx:id="tradeStepPane" minHeight="320" VBox.vgrow="SOMETIMES">
<VBox.margin>
<Insets top="0.0" left="20" right="20" bottom="20"/>
</VBox.margin>
<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" 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" 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="$gridPane" managed="false"
visible="false"/>
<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="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="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="paymentMethodLabel" text="Payments method:" GridPane.rowIndex="6" managed="false"
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="holderNameLabel" text="Receiver:" GridPane.rowIndex="7" managed="false"
visible="false"/>
<TextFieldWithCopyIcon fx:id="holderNameTextField" GridPane.rowIndex="7" GridPane.columnIndex="1"
managed="false" 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"/>
<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"/>
<InfoDisplay fx:id="paymentsInfoDisplay" onAction="#onOpenPaymentsHelp" rowIndex="10" gridPane="$gridPane"
managed="false" visible="false"/>
<Button fx:id="paymentStartedButton" 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>
<!--
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="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="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"/>
<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"/>
<Label fx:id="securityDepositLabel" text="Refunded security deposit:" GridPane.rowIndex="8" managed="false"
visible="false"/>
<TextField fx:id="securityDepositTextField" GridPane.rowIndex="8" GridPane.columnIndex="1" editable="false"
focusTraversable="false" mouseTransparent="true" managed="false" visible="false"/>
<InfoDisplay fx:id="summaryInfoDisplay" onAction="#onOpenSummaryHelp" rowIndex="9" gridPane="$gridPane"
managed="false" visible="false"/>
<!--
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>
<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" 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>
</AnchorPane>
</VBox>

View file

@ -19,36 +19,19 @@ package io.bitsquare.gui.main.portfolio.pending;
import io.bitsquare.common.viewfx.view.ActivatableViewAndModel;
import io.bitsquare.common.viewfx.view.FxmlView;
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;
import io.bitsquare.gui.components.TxIdTextField;
import io.bitsquare.gui.components.processbar.ProcessStepBar;
import io.bitsquare.gui.components.processbar.ProcessStepItem;
import io.bitsquare.gui.main.MainView;
import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import io.bitsquare.gui.main.portfolio.PortfolioView;
import io.bitsquare.gui.main.portfolio.closed.ClosedTradesView;
import io.bitsquare.locale.BSResources;
import io.bitsquare.util.Utilities;
import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.Fiat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.inject.Inject;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
import javafx.collections.ListChangeListener;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.cell.*;
@ -57,23 +40,11 @@ import javafx.util.Callback;
import javafx.util.StringConverter;
@FxmlView
public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, PendingTradesViewModel> {
public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTradesViewModel> {
@FXML AnchorPane tradeStepPane;
@FXML GridPane gridPane;
@FXML ScrollPane scrollPane;
@FXML ProcessStepBar processBar;
@FXML TxIdTextField txIdTextField;
@FXML TableView<PendingTradesListItem> table;
@FXML InputTextField withdrawAddressTextField;
@FXML InfoDisplay infoDisplay, paymentsInfoDisplay, summaryInfoDisplay;
@FXML Button confirmPaymentReceiptButton, paymentStartedButton, withdrawButton;
@FXML TitledGroupBg titledGroupBg, paymentsGroupBg, summaryGroupBg, withdrawGroupBg;
@FXML TextFieldWithCopyIcon fiatAmountTextField, holderNameTextField, secondaryIdTextField, primaryIdTextField;
@FXML TextField statusTextField, paymentMethodTextField, btcTradeAmountTextField, fiatTradeAmountTextField,
feesTextField, securityDepositTextField, withdrawAmountTextField;
@FXML Label statusLabel, txIdLabel, paymentMethodLabel, fiatAmountLabel, holderNameLabel, primaryIdLabel,
secondaryIdLabel, btcTradeAmountLabel, fiatTradeAmountLabel, feesLabel, securityDepositLabel,
withdrawAmountLabel, withdrawAddressLabel;
@FXML TableColumn<PendingTradesListItem, Fiat> priceColumn;
@FXML TableColumn<PendingTradesListItem, Fiat> tradeVolumeColumn;
@ -82,21 +53,17 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
@FXML TableColumn<PendingTradesListItem, Date> dateColumn;
@FXML TableColumn<PendingTradesListItem, Coin> tradeAmountColumn;
private ChangeListener<Number> selectedIndexChangeListener;
private ListChangeListener<PendingTradesListItem> listChangeListener;
private ChangeListener<String> txIdChangeListener;
private ChangeListener<PendingTradesViewModel.ViewState> offererStateChangeListener;
private ChangeListener<PendingTradesViewModel.ViewState> takerStateChangeListener;
private final Navigation navigation;
private ChangeListener<Boolean> focusedPropertyListener;
private ChangeListener<PendingTradesListItem> selectedItemChangeListener;
private TradeSubView currentSubView;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public PendingTradesView(PendingTradesViewModel model, Navigation navigation) {
public PendingTradesView(PendingTradesViewModel model) {
super(model);
this.navigation = navigation;
}
@Override
@ -108,109 +75,78 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
setVolumeColumnCellFactory();
setDateColumnCellFactory();
//TODO just temp for testing
withdrawAddressTextField.setText("mxmKZruv9x9JLcEj6rZx6Hnm4LLAcQHtcr");
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
table.setPlaceholder(new Label("No pending trades available"));
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(model.getWalletService(), newValue);
selectedIndexChangeListener = (ov, oldValue, newValue) -> {
if ((Integer) newValue > -1)
table.getSelectionModel().select((Integer) newValue);
updateScreen();
};
listChangeListener = change -> {
change.next();
if ((change.wasAdded() && change.getList().size() == 1) ||
(change.wasRemoved() && change.getList().size() == 0))
updateScreen();
};
offererStateChangeListener = (ov, oldValue, newValue) -> applyOffererState(newValue);
takerStateChangeListener = (ov, oldValue, newValue) -> applyTakerState(newValue);
focusedPropertyListener = (ov, oldValue, newValue) -> {
if (oldValue && !newValue)
model.withdrawAddressFocusOut(withdrawAddressTextField.getText());
};
selectedItemChangeListener = (ov, oldValue, newValue) -> {
if (newValue != null) {
model.selectTrade(newValue);
updateScreen();
}
};
if (newValue != null)
addSubView();
withdrawAddressTextField.setValidator(model.getBtcAddressValidator());
model.selectTrade(newValue);
};
}
@Override
public void doActivate() {
table.setItems(model.getList());
table.getSelectionModel().selectedItemProperty().addListener(selectedItemChangeListener);
model.getList().addListener(listChangeListener);
model.txId.addListener(txIdChangeListener);
model.selectedIndex.addListener(selectedIndexChangeListener);
withdrawAddressTextField.focusedProperty().addListener(focusedPropertyListener);
PendingTradesListItem selectedItem = model.getSelectedItem();
if (selectedItem != null) {
addSubView();
// TODO Set focus to row does not work yet...
Platform.runLater(table::requestFocus);
table.getFocusModel().focus(model.selectedIndex.get());
txIdTextField.setup(model.getWalletService(), model.txId.get());
selectedIndexChangeListener.changed(null, null, model.selectedIndex.get());
withdrawButton.disableProperty().bind(model.withdrawalButtonDisable);
updateScreen();
// Select and focus selectedItem from model
int index = table.getItems().indexOf(selectedItem);
Platform.runLater(() -> {
table.getSelectionModel().select(index);
table.requestFocus();
Platform.runLater(() -> table.getFocusModel().focus(index));
});
}
else {
removeSubView();
}
if (currentSubView != null)
currentSubView.activate();
}
@Override
public void doDeactivate() {
model.getList().removeListener(listChangeListener);
model.txId.removeListener(txIdChangeListener);
model.viewState.removeListener(offererStateChangeListener);
model.viewState.removeListener(takerStateChangeListener);
model.selectedIndex.removeListener(selectedIndexChangeListener);
table.getSelectionModel().selectedItemProperty().removeListener(selectedItemChangeListener);
withdrawButton.disableProperty().unbind();
if (currentSubView != null)
currentSubView.deactivate();
}
@FXML
void onPaymentStarted() {
model.fiatPaymentStarted();
paymentStartedButton.setDisable(true);
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void addSubView() {
removeSubView();
if (model.isOfferer())
currentSubView = new OffererAsBuyerSubView(model);
else
currentSubView = new TakerAsSellerSubView(model);
currentSubView.activate();
AnchorPane.setTopAnchor(currentSubView, 0d);
AnchorPane.setRightAnchor(currentSubView, 0d);
AnchorPane.setBottomAnchor(currentSubView, 0d);
AnchorPane.setLeftAnchor(currentSubView, 0d);
tradeStepPane.getChildren().setAll(currentSubView);
}
@FXML
void onConfirmPaymentReceipt() {
model.fiatPaymentReceived();
}
@FXML
public void onWithdraw() {
setSummaryControlsVisible(false);
model.withdraw(withdrawAddressTextField.getText());
Platform.runLater(() -> navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class));
}
@FXML
void onOpenHelp() {
Help.openWindow(model.isOfferer() ? HelpId.PENDING_TRADE_OFFERER : HelpId.PENDING_TRADE_TAKER);
}
@FXML
void onOpenPaymentsHelp() {
Help.openWindow(HelpId.PENDING_TRADE_PAYMENT);
}
@FXML
void onOpenSummaryHelp() {
Help.openWindow(HelpId.PENDING_TRADE_SUMMARY);
private void removeSubView() {
if (currentSubView != null) {
currentSubView.deactivate();
tradeStepPane.getChildren().remove(currentSubView);
currentSubView = null;
}
}
private void openOfferDetails(String id) {
@ -224,310 +160,9 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
}
private void updateScreen() {
boolean dataAvailable = !model.getList().isEmpty();
titledGroupBg.setVisible(dataAvailable);
processBar.setVisible(dataAvailable);
statusLabel.setVisible(dataAvailable);
statusTextField.setVisible(dataAvailable);
txIdLabel.setVisible(dataAvailable);
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 (model.isOfferer())
setupScreenForOfferer();
else
setupScreenForTaker();
}
}
private void setupScreenForOfferer() {
if (processBar.getProcessStepItems() == null) {
List<ProcessStepItem> items = new ArrayList<>();
items.add(new ProcessStepItem("Wait for block chain confirmation"));
items.add(new ProcessStepItem("Start payment"));
items.add(new ProcessStepItem("Wait for payment confirmation"));
items.add(new ProcessStepItem("Trade successful completed"));
processBar.setProcessStepItems(items);
}
model.viewState.addListener(offererStateChangeListener);
applyOffererState(model.viewState.get());
}
private void setupScreenForTaker() {
log.debug("setupScreenForTaker");
if (processBar.getProcessStepItems() == null) {
List<ProcessStepItem> items = new ArrayList<>();
items.add(new ProcessStepItem("Wait for block chain confirmation"));
items.add(new ProcessStepItem("Wait for payment started"));
items.add(new ProcessStepItem("Confirm payment"));
items.add(new ProcessStepItem("Trade successful completed"));
processBar.setProcessStepItems(items);
}
model.viewState.addListener(takerStateChangeListener);
applyTakerState(model.viewState.get());
}
private void applyOffererState(PendingTradesViewModel.ViewState viewState) {
setPaymentsControlsVisible(false);
setSummaryControlsVisible(false);
log.debug("applyOffererState " + viewState);
processBar.reset();
if (viewState != null) {
switch (viewState) {
case OFFERER_BUYER_WAIT_TX_CONF:
processBar.setSelectedIndex(0);
statusTextField.setText("Deposit transaction has been published. You need to wait for at least " +
"one block chain confirmation.");
infoDisplay.setText("You need to wait for at least one block chain confirmation to" +
" be sure that the deposit funding has not been double spent. For higher trade volumes we" +
" recommend to wait up to 6 confirmations.");
break;
case OFFERER_BUYER_START_PAYMENT:
processBar.setSelectedIndex(1);
paymentStartedButton.setDisable(false);
setPaymentsControlsVisible(true);
statusTextField.setText("Deposit transaction has at least one block chain confirmation. " +
"Please start now the payment.");
infoDisplay.setText("You are now safe to start the payment. You can wait for up to 6 block chain " +
"confirmations if you want more security.");
paymentMethodTextField.setText(model.getPaymentMethod());
fiatAmountTextField.setText(model.getFiatAmount());
holderNameTextField.setText(model.getHolderName());
primaryIdTextField.setText(model.getPrimaryId());
secondaryIdTextField.setText(model.getSecondaryId());
paymentsInfoDisplay.setText(BSResources.get("Copy and paste the payment account data to your " +
"internet banking web page and transfer the {0} amount to the other traders " +
"payment account. When the transfer is completed inform the other trader by " +
"clicking the button below.",
model.getCurrencyCode()));
break;
case OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED:
processBar.setSelectedIndex(2);
statusTextField.setText(BSResources.get("Waiting for the Bitcoin sellers confirmation " +
"that the {0} payment has arrived.",
model.getCurrencyCode()));
infoDisplay.setText(BSResources.get("When the confirmation that the {0} payment arrived at the " +
"Bitcoin sellers payment account, the payout transaction will be published.",
model.getCurrencyCode()));
break;
case OFFERER_BUYER_COMPLETED:
processBar.setSelectedIndex(3);
setSummaryControlsVisible(true);
statusTextField.setText("Congratulations! Trade has successfully completed.");
infoDisplay.setText("The trade is now completed and you can withdraw your Bitcoin to any external" +
"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.");
btcTradeAmountLabel.setText("You have bought:");
fiatTradeAmountLabel.setText("You have paid:");
btcTradeAmountTextField.setText(model.getTradeVolume());
fiatTradeAmountTextField.setText(model.getFiatVolume());
feesTextField.setText(model.getTotalFees());
securityDepositTextField.setText(model.getSecurityDeposit());
summaryInfoDisplay.setText("Your security deposit has been refunded to you. " +
"You can review the details to that trade any time in the closed trades screen.");
withdrawAmountTextField.setText(model.getAmountToWithdraw());
break;
case MESSAGE_SENDING_FAILED:
Popups.openWarningPopup("Sending message to trading peer failed.", model.getErrorMessage());
break;
case EXCEPTION:
Popups.openExceptionPopup(model.getTradeException());
break;
}
}
}
private void applyTakerState(PendingTradesViewModel.ViewState viewState) {
confirmPaymentReceiptButton.setVisible(false);
confirmPaymentReceiptButton.setManaged(false);
setSummaryControlsVisible(false);
processBar.reset();
log.debug("applyTakerState " + viewState);
if (viewState != null) {
switch (viewState) {
case TAKER_SELLER_WAIT_TX_CONF:
processBar.setSelectedIndex(0);
statusTextField.setText("Deposit transaction has been published. " +
"The Bitcoin buyer need to wait for at least one block chain confirmation.");
infoDisplay.setText(BSResources.get("The Bitcoin buyer needs to wait for at least one " +
"block chain confirmation before starting the {0} payment. " +
"That is needed to assure that the deposit input funding has not been " +
"double-spent. " +
"For higher trade volumes it is recommended to wait up to 6 confirmations.",
model.getCurrencyCode()));
break;
case TAKER_SELLER_WAIT_PAYMENT_STARTED:
processBar.setSelectedIndex(1);
statusTextField.setText(BSResources.get("Deposit transaction has at least one block chain " +
"confirmation. " +
"Waiting that other trader starts the {0} payment.",
model.getCurrencyCode()));
infoDisplay.setText(BSResources.get("You will get informed when the other trader has indicated " +
"the {0} payment has been started.",
model.getCurrencyCode()));
break;
case TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT:
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.",
model.getCurrencyCode()));
infoDisplay.setText(BSResources.get("It is important that you confirm when you have received the " +
"{0} payment as this will publish the payout transaction where you get returned " +
"your security deposit and the Bitcoin buyer receive the Bitcoin amount you sold.",
model.getCurrencyCode()));
break;
case TAKER_SELLER_COMPLETED:
processBar.setSelectedIndex(3);
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.");
btcTradeAmountLabel.setText("You have sold:");
fiatTradeAmountLabel.setText("You have received:");
btcTradeAmountTextField.setText(model.getTradeVolume());
fiatTradeAmountTextField.setText(model.getFiatVolume());
feesTextField.setText(model.getTotalFees());
securityDepositTextField.setText(model.getSecurityDeposit());
summaryInfoDisplay.setText("Your security deposit has been refunded to you. " +
"You can review the details to that trade any time in the closed trades screen.");
withdrawAmountTextField.setText(model.getAmountToWithdraw());
break;
case MESSAGE_SENDING_FAILED:
Popups.openWarningPopup("Sending message to trading peer failed.", model.getErrorMessage());
break;
case EXCEPTION:
Popups.openExceptionPopup(model.getTradeException());
break;
}
}
}
private void setPaymentsControlsVisible(boolean visible) {
paymentsGroupBg.setVisible(visible);
paymentMethodLabel.setVisible(visible);
fiatAmountLabel.setVisible(visible);
holderNameLabel.setVisible(visible);
// irc demo
primaryIdLabel.setVisible(visible);
secondaryIdLabel.setVisible(visible);
primaryIdTextField.setVisible(visible);
secondaryIdTextField.setVisible(visible);
paymentMethodTextField.setVisible(visible);
paymentsInfoDisplay.setVisible(visible);
paymentStartedButton.setVisible(visible);
fiatAmountTextField.setVisible(visible);
holderNameTextField.setVisible(visible);
paymentsGroupBg.setManaged(visible);
paymentMethodLabel.setManaged(visible);
fiatAmountLabel.setManaged(visible);
holderNameLabel.setManaged(visible);
primaryIdLabel.setManaged(visible);
secondaryIdLabel.setManaged(visible);
primaryIdLabel.setManaged(visible);
secondaryIdLabel.setManaged(visible);
primaryIdTextField.setManaged(visible);
secondaryIdTextField.setManaged(visible);
paymentMethodTextField.setManaged(visible);
paymentsInfoDisplay.setManaged(visible);
paymentStartedButton.setManaged(visible);
fiatAmountTextField.setManaged(visible);
holderNameTextField.setManaged(visible);
if (visible)
Platform.runLater(() -> scrollPane.setVvalue(scrollPane.getVmax()));
}
private void setSummaryControlsVisible(boolean visible) {
summaryGroupBg.setVisible(visible);
btcTradeAmountLabel.setVisible(visible);
btcTradeAmountTextField.setVisible(visible);
fiatTradeAmountLabel.setVisible(visible);
fiatTradeAmountTextField.setVisible(visible);
feesLabel.setVisible(visible);
feesTextField.setVisible(visible);
securityDepositLabel.setVisible(visible);
securityDepositTextField.setVisible(visible);
summaryInfoDisplay.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);
securityDepositLabel.setManaged(visible);
securityDepositTextField.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)
Platform.runLater(() -> {
withdrawAddressTextField.requestFocus();
// delay it once more as it does not get applied at first runLater
Platform.runLater(() -> scrollPane.setVvalue(scrollPane.getVmax()));
});
}
///////////////////////////////////////////////////////////////////////////////////////////
// CellFactories
///////////////////////////////////////////////////////////////////////////////////////////
private void setTradeIdColumnCellFactory() {
idColumn.setCellFactory(

View file

@ -20,6 +20,10 @@ package io.bitsquare.gui.main.portfolio.pending;
import io.bitsquare.btc.WalletService;
import io.bitsquare.common.viewfx.model.ActivatableWithDataModel;
import io.bitsquare.common.viewfx.model.ViewModel;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.main.MainView;
import io.bitsquare.gui.main.portfolio.PortfolioView;
import io.bitsquare.gui.main.portfolio.closed.ClosedTradesView;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.gui.util.validation.BtcAddressValidator;
import io.bitsquare.locale.BSResources;
@ -35,6 +39,7 @@ import com.google.inject.Inject;
import java.util.Date;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.IntegerProperty;
@ -49,7 +54,7 @@ import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataModel> implements ViewModel {
public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataModel> implements ViewModel {
private static final Logger log = LoggerFactory.getLogger(PendingTradesViewModel.class);
enum ViewState {
@ -67,21 +72,23 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
EXCEPTION
}
private Navigation navigation;
private final BSFormatter formatter;
private final InvalidationListener takerStateListener;
private final InvalidationListener offererStateListener;
private final BtcAddressValidator btcAddressValidator;
final StringProperty txId = new SimpleStringProperty();
final BooleanProperty withdrawalButtonDisable = new SimpleBooleanProperty(true);
public final StringProperty txId = new SimpleStringProperty();
public final BooleanProperty withdrawalButtonDisable = new SimpleBooleanProperty(true);
final IntegerProperty selectedIndex = new SimpleIntegerProperty(-1);
final ObjectProperty<ViewState> viewState = new SimpleObjectProperty<>();
@Inject
public PendingTradesViewModel(PendingTradesDataModel dataModel, BSFormatter formatter,
public PendingTradesViewModel(PendingTradesDataModel dataModel, Navigation navigation, BSFormatter formatter,
BtcAddressValidator btcAddressValidator) {
super(dataModel);
this.navigation = navigation;
this.formatter = formatter;
this.btcAddressValidator = btcAddressValidator;
@ -117,23 +124,24 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
updateOffererState();*/
}
void fiatPaymentStarted() {
public void fiatPaymentStarted() {
dataModel.fiatPaymentStarted();
}
void fiatPaymentReceived() {
public void fiatPaymentReceived() {
dataModel.fiatPaymentReceived();
}
void withdraw(String withdrawToAddress) {
public void withdraw(String withdrawToAddress) {
dataModel.withdraw(withdrawToAddress);
Platform.runLater(() -> navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class));
}
void withdrawAddressFocusOut(String text) {
public void withdrawAddressFocusOut(String text) {
withdrawalButtonDisable.set(!btcAddressValidator.validate(text).isValid);
}
String getAmountToWithdraw() {
public String getAmountToWithdraw() {
return formatter.formatCoinWithCode(dataModel.getAmountToWithdraw());
}
@ -141,11 +149,11 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
return dataModel.getList();
}
boolean isOfferer() {
public boolean isOfferer() {
return dataModel.isOfferer();
}
WalletService getWalletService() {
public WalletService getWalletService() {
return dataModel.getWalletService();
}
@ -153,7 +161,7 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
return dataModel.getSelectedItem();
}
String getCurrencyCode() {
public String getCurrencyCode() {
return dataModel.getCurrencyCode();
}
@ -183,44 +191,44 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
}
// payment
String getPaymentMethod() {
assert dataModel.getTrade().getContract() != null;
return BSResources.get(dataModel.getTrade().getContract().takerFiatAccount.type.toString());
public String getPaymentMethod() {
assert dataModel.getContract() != null;
return BSResources.get(dataModel.getContract().takerFiatAccount.type.toString());
}
String getFiatAmount() {
public String getFiatAmount() {
return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume());
}
String getHolderName() {
assert dataModel.getTrade().getContract() != null;
return dataModel.getTrade().getContract().takerFiatAccount.accountHolderName;
public String getHolderName() {
assert dataModel.getContract() != null;
return dataModel.getContract().takerFiatAccount.accountHolderName;
}
String getPrimaryId() {
assert dataModel.getTrade().getContract() != null;
return dataModel.getTrade().getContract().takerFiatAccount.accountPrimaryID;
public String getPrimaryId() {
assert dataModel.getContract() != null;
return dataModel.getContract().takerFiatAccount.accountPrimaryID;
}
String getSecondaryId() {
assert dataModel.getTrade().getContract() != null;
return dataModel.getTrade().getContract().takerFiatAccount.accountSecondaryID;
public String getSecondaryId() {
assert dataModel.getContract() != null;
return dataModel.getContract().takerFiatAccount.accountSecondaryID;
}
// summary
String getTradeVolume() {
public String getTradeVolume() {
return formatter.formatCoinWithCode(dataModel.getTrade().getTradeAmount());
}
String getFiatVolume() {
public String getFiatVolume() {
return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume());
}
String getTotalFees() {
public String getTotalFees() {
return formatter.formatCoinWithCode(dataModel.getTotalFees());
}
String getSecurityDeposit() {
public String getSecurityDeposit() {
// securityDeposit is handled different for offerer and taker.
// Offerer have paid in the max amount, but taker might have taken less so also paid in less securityDeposit
if (dataModel.isOfferer())
@ -229,7 +237,7 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
return formatter.formatCoinWithCode(dataModel.getTrade().getSecurityDeposit());
}
BtcAddressValidator getBtcAddressValidator() {
public BtcAddressValidator getBtcAddressValidator() {
return btcAddressValidator;
}
@ -266,9 +274,8 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
break;
case FIAT_PAYMENT_RECEIVED:
viewState.set(ViewState.TAKER_SELLER_COMPLETED);
break;
case PAYOUT_PUBLISHED:
viewState.set(ViewState.TAKER_SELLER_COMPLETED);
break;
case MESSAGE_SENDING_FAILED:

View file

@ -0,0 +1,154 @@
/*
* 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.main.portfolio.pending;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.main.portfolio.pending.steps.CompletedView;
import io.bitsquare.gui.main.portfolio.pending.steps.ConfirmFiatReceivedView;
import io.bitsquare.gui.main.portfolio.pending.steps.TradeWizardItem;
import io.bitsquare.gui.main.portfolio.pending.steps.WaitTxInBlockchainView;
import io.bitsquare.locale.BSResources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TakerAsSellerSubView extends TradeSubView {
private static final Logger log = LoggerFactory.getLogger(TakerAsSellerSubView.class);
private TradeWizardItem waitTxInBlockchain;
private TradeWizardItem waitFiatStarted;
private TradeWizardItem confirmFiatReceived;
private TradeWizardItem completed;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
///////////////////////////////////////////////////////////////////////////////////////////
public TakerAsSellerSubView(PendingTradesViewModel model) {
super(model);
}
@Override
public void activate() {
super.activate();
}
@Override
public void deactivate() {
super.deactivate();
}
@Override
protected void addWizards() {
waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation");
waitFiatStarted = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for payment started");
confirmFiatReceived = new TradeWizardItem(ConfirmFiatReceivedView.class, "Confirm payment received");
completed = new TradeWizardItem(CompletedView.class, "Completed");
leftVBox.getChildren().addAll(waitTxInBlockchain, waitFiatStarted, confirmFiatReceived, completed);
}
///////////////////////////////////////////////////////////////////////////////////////////
// State
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void applyState(PendingTradesViewModel.ViewState viewState) {
log.debug("applyState " + viewState);
waitTxInBlockchain.inactive();
waitFiatStarted.inactive();
confirmFiatReceived.inactive();
completed.inactive();
switch (viewState) {
case TAKER_SELLER_WAIT_TX_CONF:
showItem(waitTxInBlockchain);
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText("Deposit transaction has been published. " +
"The Bitcoin buyer need to wait for at least one block chain confirmation.");
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoDisplayField(BSResources.get("The Bitcoin buyer needs to wait for at least one " +
"block chain confirmation before starting the {0} payment. " +
"That is needed to assure that the deposit input funding has not been " +
"double-spent. " +
"For higher trade volumes it is recommended to wait up to 6 confirmations.",
model.getCurrencyCode()));
break;
case TAKER_SELLER_WAIT_PAYMENT_STARTED:
waitTxInBlockchain.done();
showItem(waitFiatStarted);
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText(BSResources.get("Deposit transaction has at least one block chain " +
"confirmation. " +
"Waiting that other trader starts the {0} payment.",
model.getCurrencyCode()));
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoDisplayField(BSResources.get("You will get informed when the other trader has " +
"indicated " +
"the {0} payment has been started.",
model.getCurrencyCode()));
break;
case TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT:
waitTxInBlockchain.done();
waitFiatStarted.done();
showItem(confirmFiatReceived);
((ConfirmFiatReceivedView) tradeStepDetailsView).setInfoLabelText(BSResources.get("The Bitcoin buyer has started the {0} payment." +
"Check your payments account and confirm when you have received the payment.",
model.getCurrencyCode()));
((ConfirmFiatReceivedView) tradeStepDetailsView).setInfoDisplayField(BSResources.get("It is important that you confirm when you have " +
"received the " +
"{0} payment as this will publish the payout transaction where you get returned " +
"your security deposit and the Bitcoin buyer receive the Bitcoin amount you sold.",
model.getCurrencyCode()));
break;
case TAKER_SELLER_COMPLETED:
waitTxInBlockchain.done();
waitFiatStarted.done();
confirmFiatReceived.done();
showItem(completed);
CompletedView completedView = (CompletedView) tradeStepDetailsView;
completedView.setBtcTradeAmountLabelText("You have sold:");
completedView.setFiatTradeAmountLabelText("You have received:");
completedView.setBtcTradeAmountTextFieldText(model.getTradeVolume());
completedView.setFiatTradeAmountTextFieldText(model.getFiatVolume());
completedView.setFeesTextFieldText(model.getTotalFees());
completedView.setSecurityDepositTextFieldText(model.getSecurityDeposit());
completedView.setSummaryInfoDisplayText("Your security deposit has been refunded to you. " +
"You can review the details to that trade any time in the closed trades screen.");
completedView.setWithdrawAmountTextFieldText(model.getAmountToWithdraw());
break;
case MESSAGE_SENDING_FAILED:
Popups.openWarningPopup("Sending message to trading peer failed.", model.getErrorMessage());
break;
case EXCEPTION:
Popups.openExceptionPopup(model.getTradeException());
break;
}
if (tradeStepDetailsView != null)
tradeStepDetailsView.activate();
}
}

View file

@ -0,0 +1,111 @@
/*
* 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.main.portfolio.pending;
import io.bitsquare.gui.main.portfolio.pending.steps.TradeStepDetailsView;
import io.bitsquare.gui.main.portfolio.pending.steps.TradeWizardItem;
import io.bitsquare.gui.util.Layout;
import javafx.beans.value.ChangeListener;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class TradeSubView extends HBox {
private static final Logger log = LoggerFactory.getLogger(TradeSubView.class);
protected VBox leftVBox;
protected AnchorPane contentPane;
protected PendingTradesViewModel model;
protected ChangeListener<PendingTradesViewModel.ViewState> offererStateChangeListener;
protected TradeStepDetailsView tradeStepDetailsView;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
///////////////////////////////////////////////////////////////////////////////////////////
public TradeSubView(PendingTradesViewModel model) {
this.model = model;
setSpacing(Layout.PADDING_WINDOW);
buildViews();
offererStateChangeListener = (ov, oldValue, newValue) -> applyState(newValue);
}
public void activate() {
log.debug("activate");
model.viewState.addListener(offererStateChangeListener);
applyState(model.viewState.get());
}
public void deactivate() { log.debug("deactivate");
model.viewState.removeListener(offererStateChangeListener);
if (tradeStepDetailsView != null)
tradeStepDetailsView.deactivate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Misc
///////////////////////////////////////////////////////////////////////////////////////////
protected abstract void applyState(PendingTradesViewModel.ViewState state);
protected void buildViews() {
addLeftBox();
addContentPane();
addWizards();
}
protected void showItem(TradeWizardItem item) {
item.active();
createAndAddTradeStepView(item.getViewClass());
}
abstract protected void addWizards();
protected void createAndAddTradeStepView(Class<? extends TradeStepDetailsView> viewClass) {
try {
tradeStepDetailsView = viewClass.getDeclaredConstructor(PendingTradesViewModel.class).newInstance(model);
} catch (Exception e) {
e.printStackTrace();
}
contentPane.getChildren().setAll(tradeStepDetailsView);
}
private void addLeftBox() {
leftVBox = new VBox();
leftVBox.setSpacing(Layout.SPACING_VBOX);
leftVBox.setMinWidth(290);
getChildren().add(leftVBox);
}
private void addContentPane() {
contentPane = new AnchorPane();
HBox.setHgrow(contentPane, Priority.SOMETIMES);
getChildren().add(contentPane);
}
}

View file

@ -1,53 +0,0 @@
/*
* 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.main.portfolio.pending.proto;
import io.bitsquare.gui.main.portfolio.pending.PendingTradesOffererAsBuyerView;
import io.bitsquare.gui.util.Layout;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PendingMain extends Application {
private static final Logger log = LoggerFactory.getLogger(PendingMain.class);
@Override
public void start(Stage primaryStage) {
AnchorPane root = new AnchorPane();
PendingTradesOffererAsBuyerView pendingTradesOffererAsBuyerView = new PendingTradesOffererAsBuyerView();
AnchorPane.setLeftAnchor(pendingTradesOffererAsBuyerView, Layout.PADDING_WINDOW);
AnchorPane.setRightAnchor(pendingTradesOffererAsBuyerView, Layout.PADDING_WINDOW);
AnchorPane.setTopAnchor(pendingTradesOffererAsBuyerView, Layout.PADDING_WINDOW);
AnchorPane.setBottomAnchor(pendingTradesOffererAsBuyerView, Layout.PADDING_WINDOW);
root.getChildren().add(pendingTradesOffererAsBuyerView);
Scene scene = new Scene(root, 1000, 600);
scene.getStylesheets().setAll(
"/io/bitsquare/gui/bitsquare.css",
"/io/bitsquare/gui/images.css");
primaryStage.setScene(scene);
primaryStage.show();
}
}

View file

@ -19,19 +19,21 @@ package io.bitsquare.gui.main.portfolio.pending.steps;
import io.bitsquare.gui.components.InfoDisplay;
import io.bitsquare.gui.components.InputTextField;
import io.bitsquare.gui.main.portfolio.pending.PendingTradesViewModel;
import io.bitsquare.gui.util.Layout;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.gui.util.ComponentBuilder.*;
public class CompletedView extends AnchorPane{
private static final Logger log = LoggerFactory.getLogger(WaitView.class);
public class CompletedView extends TradeStepDetailsView {
private static final Logger log = LoggerFactory.getLogger(WaitTxInBlockchainView.class);
private Label btcTradeAmountLabel;
private TextField btcTradeAmountTextField;
@ -41,55 +43,169 @@ public class CompletedView extends AnchorPane{
private TextField feesTextField;
private Label securityDepositLabel;
private TextField securityDepositTextField;
private InfoDisplay infoDisplay;
private InfoDisplay summaryInfoDisplay;
private InputTextField withdrawAddressTextField;
private TextField withdrawAmountTextField;
private Button withdrawButton;
public CompletedView() {
buildViews();
private ChangeListener<Boolean> focusedPropertyListener;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
///////////////////////////////////////////////////////////////////////////////////////////
public CompletedView(PendingTradesViewModel model) {
super(model);
focusedPropertyListener = (ov, oldValue, newValue) -> {
if (oldValue && !newValue)
model.withdrawAddressFocusOut(withdrawAddressTextField.getText());
};
/* statusTextField.setText("Congratulations! Trade has successfully completed.");
infoDisplay.setText("The trade is now completed and you can withdraw your Bitcoin to any external" +
"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.");*/
/* btcTradeAmountLabel.setText("You have bought:");
fiatTradeAmountLabel.setText("You have paid:");
btcTradeAmountTextField.setText(model.getTradeVolume());
fiatTradeAmountTextField.setText(model.getFiatVolume());
feesTextField.setText(model.getTotalFees());
securityDepositTextField.setText(model.getSecurityDeposit());
summaryInfoDisplay.setText("Your security deposit has been refunded to you. " +
"You can review the details to that trade any time in the closed trades screen.");*/
// withdrawAmountTextField.setText(model.getAmountToWithdraw());
}
private void buildViews() {
AnchorPane.setLeftAnchor(this, 0d);
AnchorPane.setRightAnchor(this, 0d);
AnchorPane.setTopAnchor(this, 0d);
AnchorPane.setBottomAnchor(this, 0d);
@Override
public void activate() {
super.activate();
withdrawAddressTextField.focusedProperty().addListener(focusedPropertyListener);
withdrawAddressTextField.setValidator(model.getBtcAddressValidator());
withdrawButton.disableProperty().bind(model.withdrawalButtonDisable);
int i = 0;
GridPane gridPane = getAndAddGridPane(this);
getAndAddTitledGroupBg(gridPane, i, 5, "Summary");
LabelTextFieldPair btcTradeAmountPair = getAndAddLabelTextFieldPair(gridPane, i++, "You have bought:", Layout.FIRST_ROW_DISTANCE);
btcTradeAmountLabel = btcTradeAmountPair.label;
btcTradeAmountTextField = btcTradeAmountPair.textField;
LabelTextFieldPair fiatTradeAmountPair = getAndAddLabelTextFieldPair(gridPane, i++, "You have paid:");
fiatTradeAmountLabel = fiatTradeAmountPair.label;
fiatTradeAmountTextField = fiatTradeAmountPair.textField;
LabelTextFieldPair feesPair = getAndAddLabelTextFieldPair(gridPane, i++, "Total fees paid:");
feesLabel = feesPair.label;
feesTextField = feesPair.textField;
LabelTextFieldPair securityDepositPair = getAndAddLabelTextFieldPair(gridPane, i++, "Refunded security deposit:");
securityDepositLabel = securityDepositPair.label;
securityDepositTextField = securityDepositPair.textField;
infoDisplay = getAndAddInfoDisplay(gridPane, i++, "infoDisplay", this::onOpenHelp);
getAndAddTitledGroupBg(gridPane, i, 2, "Withdraw your bitcoins", Layout.GROUP_DISTANCE);
withdrawAmountTextField = getAndAddLabelTextFieldPair(gridPane, i++, "Amount to withdraw:", Layout.FIRST_ROW_AND_GROUP_DISTANCE).textField;
withdrawAddressTextField = getAndAddLabelInputTextFieldPair(gridPane, i++, "Withdraw to address:").inputTextField;
getAndAddButton(gridPane, i++, "Withdraw to external wallet", this::onWithdraw);
// We need to handle both cases: Address not set and address already set (when returning from other view)
// We get address validation after focus out, so first make sure we loose focus and then set it again as hint for user to put address in
Platform.runLater(() -> {
withdrawAddressTextField.requestFocus();
Platform.runLater(() -> {
this.requestFocus();
Platform.runLater(() -> {
withdrawAddressTextField.requestFocus();
});
});
});
}
@Override
public void deactivate() {
super.deactivate();
withdrawAddressTextField.focusedProperty().removeListener(focusedPropertyListener);
withdrawButton.disableProperty().unbind();
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI Handlers
///////////////////////////////////////////////////////////////////////////////////////////
private void onWithdraw(ActionEvent actionEvent) {
log.debug("onWithdraw");
model.withdraw(withdrawAddressTextField.getText());
}
private void onOpenHelp(ActionEvent actionEvent) {
log.debug("onOpenHelp");
///////////////////////////////////////////////////////////////////////////////////////////
// Build view
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void buildGridEntries() {
getAndAddTitledGroupBg(gridPane, gridRow, 5, "Summary");
LabelTextFieldPair btcTradeAmountPair = getAndAddLabelTextFieldPair(gridPane, gridRow++, "You have bought:", Layout.FIRST_ROW_DISTANCE);
btcTradeAmountLabel = btcTradeAmountPair.label;
btcTradeAmountTextField = btcTradeAmountPair.textField;
LabelTextFieldPair fiatTradeAmountPair = getAndAddLabelTextFieldPair(gridPane, gridRow++, "You have paid:");
fiatTradeAmountLabel = fiatTradeAmountPair.label;
fiatTradeAmountTextField = fiatTradeAmountPair.textField;
LabelTextFieldPair feesPair = getAndAddLabelTextFieldPair(gridPane, gridRow++, "Total fees paid:");
feesLabel = feesPair.label;
feesTextField = feesPair.textField;
LabelTextFieldPair securityDepositPair = getAndAddLabelTextFieldPair(gridPane, gridRow++, "Refunded security deposit:");
securityDepositLabel = securityDepositPair.label;
securityDepositTextField = securityDepositPair.textField;
summaryInfoDisplay = getAndAddInfoDisplay(gridPane, gridRow++, "infoDisplay", this::onOpenHelp);
getAndAddTitledGroupBg(gridPane, gridRow, 2, "Withdraw your bitcoins", Layout.GROUP_DISTANCE);
withdrawAmountTextField = getAndAddLabelTextFieldPair(gridPane, gridRow++, "Amount to withdraw:", Layout.FIRST_ROW_AND_GROUP_DISTANCE).textField;
withdrawAddressTextField = getAndAddLabelInputTextFieldPair(gridPane, gridRow++, "Withdraw to address:").inputTextField;
withdrawButton = getAndAddButton(gridPane, gridRow++, "Withdraw to external wallet", this::onWithdraw);
//TODO just temp for testing
withdrawAddressTextField.setText("mxmKZruv9x9JLcEj6rZx6Hnm4LLAcQHtcr");
}
/* fiatTradeAmountLabel.setText("You have received:");
btcTradeAmountTextField.setText(model.getTradeVolume());
fiatTradeAmountTextField.setText(model.getFiatVolume());
feesTextField.setText(model.getTotalFees());
securityDepositTextField.setText(model.getSecurityDeposit());
summaryInfoDisplay.setText("Your security deposit has been refunded to you. "+
"You can review the details to that trade any time in the closed trades screen.");
withdrawAmountTextField.setText(model.getAmountToWithdraw());*/
public void setBtcTradeAmountLabelText(String text) {
btcTradeAmountLabel.setText(text);
}
public void setFiatTradeAmountLabelText(String text) {
fiatTradeAmountLabel.setText(text);
}
public void setBtcTradeAmountTextFieldText(String text) {
btcTradeAmountTextField.setText(text);
}
public void setFiatTradeAmountTextFieldText(String text) {
fiatTradeAmountTextField.setText(text);
}
public void setFeesTextFieldText(String text) {
feesTextField.setText(text);
}
public void setSecurityDepositTextFieldText(String text) {
securityDepositTextField.setText(text);
}
public void setSummaryInfoDisplayText(String text) {
summaryInfoDisplay.setText(text);
}
public void setWithdrawAmountTextFieldText(String text) {
withdrawAmountTextField.setText(text);
}
/* completedView.setBtcTradeAmountLabelText("You have sold:");
completedView.setFiatTradeAmountLabelText("You have received:");
completedView.setBtcTradeAmountTextFieldText(model.getTradeVolume());
completedView.setFiatTradeAmountTextFieldText(model.getFiatVolume());
completedView.setFeesTextFieldText(model.getTotalFees());
completedView.setSecurityDepositTextFieldText(model.getSecurityDeposit());
completedView.setSummaryInfoDisplayText("Your security deposit has been refunded to you. "+
"You can review the details to that trade any time in the closed trades screen.");
completedView.setWithdrawAmountTextFieldText(model.getAmountToWithdraw());*/
}

View file

@ -0,0 +1,111 @@
/*
* 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.main.portfolio.pending.steps;
import io.bitsquare.gui.components.InfoDisplay;
import io.bitsquare.gui.components.TxIdTextField;
import io.bitsquare.gui.main.portfolio.pending.PendingTradesViewModel;
import io.bitsquare.gui.util.Layout;
import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.gui.util.ComponentBuilder.*;
public class ConfirmFiatReceivedView extends TradeStepDetailsView {
private static final Logger log = LoggerFactory.getLogger(ConfirmFiatReceivedView.class);
private TxIdTextField txIdTextField;
private Label infoLabel;
private InfoDisplay infoDisplay;
private final ChangeListener<String> txIdChangeListener;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
///////////////////////////////////////////////////////////////////////////////////////////
public ConfirmFiatReceivedView(PendingTradesViewModel model) {
super(model);
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(model.getWalletService(), newValue);
}
@Override
public void activate() {
super.activate();
model.txId.addListener(txIdChangeListener);
txIdTextField.setup(model.getWalletService(), model.txId.get());
}
@Override
public void deactivate() {
super.deactivate();
model.txId.removeListener(txIdChangeListener);
txIdTextField.cleanup();
}
////////////////////////////////////////////////////////////////////////////////////////
// UI Handlers
///////////////////////////////////////////////////////////////////////////////////////////
private void onPaymentReceived(ActionEvent actionEvent) {
log.debug("onPaymentReceived");
model.fiatPaymentReceived();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
public void setInfoLabelText(String text) {
if (infoLabel != null)
infoLabel.setText(text);
}
public void setInfoDisplayField(String text) {
if (infoDisplay != null)
infoDisplay.setText(text);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Build view
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void buildGridEntries() {
getAndAddTitledGroupBg(gridPane, gridRow, 1, "Blockchain confirmation");
txIdTextField = getAndAddLabelTxIdTextFieldPair(gridPane, gridRow++, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).txIdTextField;
getAndAddTitledGroupBg(gridPane, gridRow, 1, "Information", Layout.GROUP_DISTANCE);
infoLabel = getAndAddInfoLabel(gridPane, gridRow++, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
getAndAddButton(gridPane, gridRow++, "Confirm payment receipt", this::onPaymentReceived);
}
}

View file

@ -1,69 +0,0 @@
/*
* 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.main.portfolio.pending.steps;
import io.bitsquare.gui.components.InfoDisplay;
import io.bitsquare.gui.components.TxIdTextField;
import io.bitsquare.gui.util.Layout;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.gui.util.ComponentBuilder.*;
public class ConfirmFiatView extends AnchorPane {
private static final Logger log = LoggerFactory.getLogger(ConfirmFiatView.class);
private TextField statusTextField;
private TxIdTextField txIdTextField;
private InfoDisplay infoDisplay;
public ConfirmFiatView() {
buildViews();
}
private void buildViews() {
AnchorPane.setLeftAnchor(this, 0d);
AnchorPane.setRightAnchor(this, 0d);
AnchorPane.setTopAnchor(this, 0d);
AnchorPane.setBottomAnchor(this, 0d);
int i = 0;
GridPane gridPane = getAndAddGridPane(this);
getAndAddTitledGroupBg(gridPane, i, 3, "Trade status");
statusTextField = getAndAddLabelTextFieldPair(gridPane, i++, "Status:", Layout.FIRST_ROW_DISTANCE).textField;
txIdTextField = getAndAddLabelTxIdTextFieldPair(gridPane, i++, "Deposit transaction ID:").txIdTextField;
infoDisplay = getAndAddInfoDisplay(gridPane, i++, "infoDisplay", this::onOpenHelp);
getAndAddButton(gridPane, i++, "Confirm payment receipt", this::onPaymentReceived);
}
private void onPaymentReceived(ActionEvent actionEvent) {
log.debug("onPaymentReceived");
}
private void onOpenHelp(ActionEvent actionEvent) {
log.debug("onOpenHelp");
}
}

View file

@ -19,55 +19,110 @@ package io.bitsquare.gui.main.portfolio.pending.steps;
import io.bitsquare.gui.components.InfoDisplay;
import io.bitsquare.gui.components.TextFieldWithCopyIcon;
import io.bitsquare.gui.components.TxIdTextField;
import io.bitsquare.gui.main.portfolio.pending.PendingTradesViewModel;
import io.bitsquare.gui.util.Layout;
import io.bitsquare.locale.BSResources;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.gui.util.ComponentBuilder.*;
public class StartFiatView extends AnchorPane {
private static final Logger log = LoggerFactory.getLogger(WaitView.class);
public class StartFiatView extends TradeStepDetailsView {
private static final Logger log = LoggerFactory.getLogger(WaitTxInBlockchainView.class);
private TxIdTextField txIdTextField;
private TextFieldWithCopyIcon fiatAmountTextField;
private TextField paymentMethodTextField;
private TextFieldWithCopyIcon holderNameTextField;
private TextFieldWithCopyIcon primarTextField;
private TextFieldWithCopyIcon primaryIdTextField;
private TextFieldWithCopyIcon secondaryIdTextField;
private InfoDisplay infoDisplay;
private InfoDisplay paymentsInfoDisplay;
private Button paymentStartedButton;
public StartFiatView() {
buildViews();
private final ChangeListener<String> txIdChangeListener;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
///////////////////////////////////////////////////////////////////////////////////////////
public StartFiatView(PendingTradesViewModel model) {
super(model);
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(model.getWalletService(), newValue);
paymentMethodTextField.setText(model.getPaymentMethod());
fiatAmountTextField.setText(model.getFiatAmount());
holderNameTextField.setText(model.getHolderName());
primaryIdTextField.setText(model.getPrimaryId());
secondaryIdTextField.setText(model.getSecondaryId());
paymentsInfoDisplay.setText(BSResources.get("Copy and paste the payment account data to your " +
"internet banking web page and transfer the {0} amount to the other traders " +
"payment account. When the transfer is completed inform the other trader by " +
"clicking the button below.",
model.getCurrencyCode()));
/*
statusTextField.setText("Deposit transaction has at least one block chain confirmation. " +
"Please start now the payment.");
infoDisplay.setText("You are now safe to start the payment. You can wait for up to 6 block chain " +
"confirmations if you want more security.");
*/
}
private void buildViews() {
AnchorPane.setLeftAnchor(this, 0d);
AnchorPane.setRightAnchor(this, 0d);
AnchorPane.setTopAnchor(this, 0d);
AnchorPane.setBottomAnchor(this, 0d);
@Override
public void activate() {
log.debug("activate ##");
super.activate();
int i = 0;
GridPane gridPane = getAndAddGridPane(this);
getAndAddTitledGroupBg(gridPane, i, 6, "Payments details");
fiatAmountTextField = getAndAddLabelTextFieldWithCopyIconPair(gridPane, i++, "Amount to transfer:", Layout.FIRST_ROW_DISTANCE).textFieldWithCopyIcon;
paymentMethodTextField = getAndAddLabelTextFieldPair(gridPane, i++, "Payment method:").textField;
holderNameTextField = getAndAddLabelTextFieldWithCopyIconPair(gridPane, i++, "Receiver:").textFieldWithCopyIcon;
primarTextField = getAndAddLabelTextFieldWithCopyIconPair(gridPane, i++, "IBAN:").textFieldWithCopyIcon;
secondaryIdTextField = getAndAddLabelTextFieldWithCopyIconPair(gridPane, i++, "BIC:").textFieldWithCopyIcon;
infoDisplay = getAndAddInfoDisplay(gridPane, i++, "infoDisplay", this::onOpenHelp);
getAndAddButton(gridPane, i++, "Payment started", this::onPaymentStarted);
model.txId.addListener(txIdChangeListener);
Platform.runLater(() -> txIdTextField.setup(model.getWalletService(), model.txId.get()));
}
@Override
public void deactivate() {
super.deactivate();
model.txId.removeListener(txIdChangeListener);
txIdTextField.cleanup();
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI Handlers
///////////////////////////////////////////////////////////////////////////////////////////
private void onPaymentStarted(ActionEvent actionEvent) {
log.debug("onPaymentStarted");
model.fiatPaymentStarted();
paymentStartedButton.setDisable(true);
}
private void onOpenHelp(ActionEvent actionEvent) {
log.debug("onOpenHelp");
}
///////////////////////////////////////////////////////////////////////////////////////////
// Build view
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void buildGridEntries() {
getAndAddTitledGroupBg(gridPane, gridRow, 1, "Blockchain confirmation");
txIdTextField = getAndAddLabelTxIdTextFieldPair(gridPane, gridRow++, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).txIdTextField;
getAndAddTitledGroupBg(gridPane, gridRow, 6, "Payments details", Layout.GROUP_DISTANCE);
fiatAmountTextField = getAndAddLabelTextFieldWithCopyIconPair(gridPane, gridRow++, "Amount to transfer:", Layout.FIRST_ROW_AND_GROUP_DISTANCE)
.textFieldWithCopyIcon;
paymentMethodTextField = getAndAddLabelTextFieldPair(gridPane, gridRow++, "Payment method:").textField;
holderNameTextField = getAndAddLabelTextFieldWithCopyIconPair(gridPane, gridRow++, "Receiver:").textFieldWithCopyIcon;
primaryIdTextField = getAndAddLabelTextFieldWithCopyIconPair(gridPane, gridRow++, "IBAN:").textFieldWithCopyIcon;
secondaryIdTextField = getAndAddLabelTextFieldWithCopyIconPair(gridPane, gridRow++, "BIC:").textFieldWithCopyIcon;
paymentsInfoDisplay = getAndAddInfoDisplay(gridPane, gridRow++, "infoDisplay", this::onOpenHelp);
paymentStartedButton = getAndAddButton(gridPane, gridRow++, "Payment started", this::onPaymentStarted);
}
}

View file

@ -0,0 +1,81 @@
/*
* 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.main.portfolio.pending.steps;
import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import io.bitsquare.gui.main.portfolio.pending.PendingTradesViewModel;
import javafx.event.ActionEvent;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.gui.util.ComponentBuilder.getAndAddGridPane;
public abstract class TradeStepDetailsView extends AnchorPane {
private static final Logger log = LoggerFactory.getLogger(TradeStepDetailsView.class);
protected final PendingTradesViewModel model;
protected final GridPane gridPane;
protected int gridRow = 0;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
///////////////////////////////////////////////////////////////////////////////////////////
public TradeStepDetailsView(PendingTradesViewModel model) {
this.model = model;
AnchorPane.setLeftAnchor(this, 0d);
AnchorPane.setRightAnchor(this, 0d);
AnchorPane.setTopAnchor(this, -10d);
AnchorPane.setBottomAnchor(this, 0d);
gridPane = getAndAddGridPane(this);
buildGridEntries();
}
public void activate() {
log.debug("activate");
}
public void deactivate() {
log.debug("deactivate");
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI Handlers
///////////////////////////////////////////////////////////////////////////////////////////
protected void onOpenHelp(ActionEvent actionEvent) {
log.debug("onOpenHelp");
Help.openWindow(model.isOfferer() ? HelpId.PENDING_TRADE_OFFERER : HelpId.PENDING_TRADE_TAKER);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Build view
///////////////////////////////////////////////////////////////////////////////////////////
abstract void buildGridEntries();
}

View file

@ -15,42 +15,45 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.main.portfolio.pending;
package io.bitsquare.gui.main.portfolio.pending.steps;
import io.bitsquare.gui.util.Colors;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.*;
import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon;
public class TradeWizardItem extends Button {
public Class<? extends Node> getViewClass() {
public Class<? extends TradeStepDetailsView> getViewClass() {
return viewClass;
}
private final Class<? extends Node> viewClass;
private final Class<? extends TradeStepDetailsView> viewClass;
public TradeWizardItem(Class<? extends Node> viewClass, String title) {
public TradeWizardItem(Class<? extends TradeStepDetailsView> viewClass, String title) {
this.viewClass = viewClass;
setMouseTransparent(true);
setText(title);
setId("trade-wizard-item-background-disabled");
setPrefHeight(40);
setPrefWidth(270);
setPadding(new Insets(0, 20, 0, 10));
setAlignment(Pos.CENTER_LEFT);
inactive();
}
public void inactive() {
setId("trade-wizard-item-background-disabled");
Label icon = new Label();
icon.setTextFill(Colors.MID_GREY);
AwesomeDude.setIcon(icon, AwesomeIcon.ANGLE_DOWN);
setGraphic(icon);
}
void show() {
public void active() {
setId("trade-wizard-item-background-active");
Label icon = new Label();
icon.setTextFill(Colors.BLUE);
@ -58,7 +61,7 @@ public class TradeWizardItem extends Button {
setGraphic(icon);
}
void onCompleted() {
public void done() {
setId("trade-wizard-item-background-completed");
Label icon = new Label();
icon.setTextFill(Colors.GREEN);

View file

@ -0,0 +1,98 @@
/*
* 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.main.portfolio.pending.steps;
import io.bitsquare.gui.components.InfoDisplay;
import io.bitsquare.gui.components.TxIdTextField;
import io.bitsquare.gui.main.portfolio.pending.PendingTradesViewModel;
import io.bitsquare.gui.util.Layout;
import javafx.beans.value.ChangeListener;
import javafx.scene.control.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.gui.util.ComponentBuilder.*;
public class WaitFiatReceivedView extends TradeStepDetailsView {
private static final Logger log = LoggerFactory.getLogger(WaitFiatReceivedView.class);
private TxIdTextField txIdTextField;
private Label infoLabel;
private InfoDisplay infoDisplay;
private final ChangeListener<String> txIdChangeListener;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
///////////////////////////////////////////////////////////////////////////////////////////
public WaitFiatReceivedView(PendingTradesViewModel model) {
super(model);
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(model.getWalletService(), newValue);
}
@Override
public void activate() {
super.activate();
model.txId.addListener(txIdChangeListener);
txIdTextField.setup(model.getWalletService(), model.txId.get());
}
@Override
public void deactivate() {
super.deactivate();
model.txId.removeListener(txIdChangeListener);
txIdTextField.cleanup();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
public void setInfoLabelText(String text) {
if (infoLabel != null)
infoLabel.setText(text);
}
public void setInfoDisplayField(String text) {
if (infoDisplay != null)
infoDisplay.setText(text);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Build view
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void buildGridEntries() {
getAndAddTitledGroupBg(gridPane, gridRow, 1, "Blockchain confirmation");
txIdTextField = getAndAddLabelTxIdTextFieldPair(gridPane, gridRow++, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).txIdTextField;
getAndAddTitledGroupBg(gridPane, gridRow, 1, "Information", Layout.GROUP_DISTANCE);
infoLabel = getAndAddInfoLabel(gridPane, gridRow++, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
}
}

View file

@ -0,0 +1,98 @@
/*
* 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.main.portfolio.pending.steps;
import io.bitsquare.gui.components.InfoDisplay;
import io.bitsquare.gui.components.TxIdTextField;
import io.bitsquare.gui.main.portfolio.pending.PendingTradesViewModel;
import io.bitsquare.gui.util.Layout;
import javafx.beans.value.ChangeListener;
import javafx.scene.control.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.gui.util.ComponentBuilder.*;
public class WaitTxInBlockchainView extends TradeStepDetailsView {
private static final Logger log = LoggerFactory.getLogger(WaitTxInBlockchainView.class);
private TxIdTextField txIdTextField;
private Label infoLabel;
private InfoDisplay infoDisplay;
private final ChangeListener<String> txIdChangeListener;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
///////////////////////////////////////////////////////////////////////////////////////////
public WaitTxInBlockchainView(PendingTradesViewModel model) {
super(model);
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(model.getWalletService(), newValue);
}
@Override
public void activate() {
super.activate();
model.txId.addListener(txIdChangeListener);
txIdTextField.setup(model.getWalletService(), model.txId.get());
}
@Override
public void deactivate() {
super.deactivate();
model.txId.removeListener(txIdChangeListener);
txIdTextField.cleanup();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
public void setInfoLabelText(String text) {
if (infoLabel != null)
infoLabel.setText(text);
}
public void setInfoDisplayField(String text) {
if (infoDisplay != null)
infoDisplay.setText(text);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Build view
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void buildGridEntries() {
getAndAddTitledGroupBg(gridPane, gridRow, 1, "Blockchain confirmation");
txIdTextField = getAndAddLabelTxIdTextFieldPair(gridPane, gridRow++, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).txIdTextField;
getAndAddTitledGroupBg(gridPane, gridRow, 1, "Information", Layout.GROUP_DISTANCE);
infoLabel = getAndAddInfoLabel(gridPane, gridRow++, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
}
}

View file

@ -1,64 +0,0 @@
/*
* 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.main.portfolio.pending.steps;
import io.bitsquare.gui.components.InfoDisplay;
import io.bitsquare.gui.components.TxIdTextField;
import io.bitsquare.gui.util.Layout;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.gui.util.ComponentBuilder.*;
public class WaitView extends AnchorPane {
private static final Logger log = LoggerFactory.getLogger(WaitView.class);
private TextField statusTextField;
private TxIdTextField txIdTextField;
private InfoDisplay infoDisplay;
public WaitView() {
buildViews();
}
private void buildViews() {
AnchorPane.setLeftAnchor(this, 0d);
AnchorPane.setRightAnchor(this, 0d);
AnchorPane.setTopAnchor(this, 0d);
AnchorPane.setBottomAnchor(this, 0d);
int i = 0;
GridPane gridPane = getAndAddGridPane(this);
getAndAddTitledGroupBg(gridPane, i, 3, "Trade status");
statusTextField = getAndAddLabelTextFieldPair(gridPane, i++, "Status:", Layout.FIRST_ROW_DISTANCE).textField;
txIdTextField = getAndAddLabelTxIdTextFieldPair(gridPane, i++, "Deposit transaction ID:").txIdTextField;
infoDisplay = getAndAddInfoDisplay(gridPane, i++, "infoDisplay", this::onOpenHelp);
}
private void onOpenHelp(ActionEvent actionEvent) {
log.debug("onOpenHelp");
}
}

View file

@ -81,6 +81,17 @@ public class ComponentBuilder {
return label;
}
public static Label getAndAddInfoLabel(GridPane gridPane, int rowIndex, double top) {
Label label = new Label();
label.setWrapText(true);
GridPane.setHalignment(label, HPos.LEFT);
GridPane.setRowIndex(label, rowIndex);
GridPane.setColumnSpan(label, 2);
GridPane.setMargin(label, new Insets(top, 0, 0, 0));
gridPane.getChildren().add(label);
return label;
}
public static LabelTextFieldPair getAndAddLabelTextFieldPair(GridPane gridPane, int rowIndex, String title) {
return getAndAddLabelTextFieldPair(gridPane, rowIndex, title, 0);
}