diff --git a/core/src/main/java/io/bitsquare/app/BitsquareApp.java b/core/src/main/java/io/bitsquare/app/BitsquareApp.java index 36f17f81a3..6e7f7290f5 100644 --- a/core/src/main/java/io/bitsquare/app/BitsquareApp.java +++ b/core/src/main/java/io/bitsquare/app/BitsquareApp.java @@ -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 diff --git a/core/src/main/java/io/bitsquare/gui/bitsquare.css b/core/src/main/java/io/bitsquare/gui/bitsquare.css index 5b56193a9a..8fb6f6c2f9 100644 --- a/core/src/main/java/io/bitsquare/gui/bitsquare.css +++ b/core/src/main/java/io/bitsquare/gui/bitsquare.css @@ -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, diff --git a/core/src/main/java/io/bitsquare/gui/components/TxIdTextField.java b/core/src/main/java/io/bitsquare/gui/components/TxIdTextField.java index 1994685d18..d9ed7f596f 100644 --- a/core/src/main/java/io/bitsquare/gui/components/TxIdTextField.java +++ b/core/src/main/java/io/bitsquare/gui/components/TxIdTextField.java @@ -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 diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/OffererAsBuyerSubView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/OffererAsBuyerSubView.java new file mode 100644 index 0000000000..2851de7e14 --- /dev/null +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/OffererAsBuyerSubView.java @@ -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 . + */ + +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(); + } +} + + + diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesDataModel.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesDataModel.java index 3dce902e6a..5b2c462e44 100644 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesDataModel.java +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesDataModel.java @@ -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 takerProcessState = new SimpleObjectProperty<>(); final ObjectProperty offererProcessState = new SimpleObjectProperty<>(); + final ObjectProperty 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 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; + } } diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesOffererAsBuyerView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesOffererAsBuyerView.java deleted file mode 100644 index 2669d2a84b..0000000000 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesOffererAsBuyerView.java +++ /dev/null @@ -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 . - */ - -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); - } -} - - - diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesStepsView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesStepsView.java deleted file mode 100644 index 7ee12db028..0000000000 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesStepsView.java +++ /dev/null @@ -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 . - */ - -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 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); - } - - -} - - - diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.fxml b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.fxml index bff2fcf70f..50a2d485eb 100644 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.fxml +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.fxml @@ -17,258 +17,58 @@ ~ along with Bitsquare. If not, see . --> - - - - - - - + - + - + + + + - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + - - - - - - - - - - - - - - - - + + diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.java index 7cefd5ccb9..fc53fe32d2 100644 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.java +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesView.java @@ -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 { +public class PendingTradesView extends ActivatableViewAndModel { + + @FXML AnchorPane tradeStepPane; - @FXML GridPane gridPane; - @FXML ScrollPane scrollPane; - @FXML ProcessStepBar processBar; - @FXML TxIdTextField txIdTextField; @FXML TableView 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 priceColumn; @FXML TableColumn tradeVolumeColumn; @@ -82,21 +53,17 @@ public class PendingTradesView extends ActivatableViewAndModel dateColumn; @FXML TableColumn tradeAmountColumn; - private ChangeListener selectedIndexChangeListener; - private ListChangeListener listChangeListener; - private ChangeListener txIdChangeListener; - private ChangeListener offererStateChangeListener; - private ChangeListener takerStateChangeListener; - - private final Navigation navigation; - private ChangeListener focusedPropertyListener; private ChangeListener 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 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 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 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( diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesViewModel.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesViewModel.java index 5ef1da70fa..7c200c4e2d 100644 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesViewModel.java +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesViewModel.java @@ -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 implements ViewModel { +public class PendingTradesViewModel extends ActivatableWithDataModel implements ViewModel { private static final Logger log = LoggerFactory.getLogger(PendingTradesViewModel.class); enum ViewState { @@ -67,21 +72,23 @@ class PendingTradesViewModel extends ActivatableWithDataModel 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 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. + */ + +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(); + } +} + + + diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/TradeSubView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/TradeSubView.java new file mode 100644 index 0000000000..501e96f000 --- /dev/null +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/TradeSubView.java @@ -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 . + */ + +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 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 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); + } +} + + + diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/proto/PendingMain.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/proto/PendingMain.java deleted file mode 100644 index b63ade789a..0000000000 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/proto/PendingMain.java +++ /dev/null @@ -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 . - */ - -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(); - - } -} diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/CompletedView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/CompletedView.java index ea86eb3c1f..7be104fb07 100644 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/CompletedView.java +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/CompletedView.java @@ -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 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());*/ } diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/ConfirmFiatReceivedView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/ConfirmFiatReceivedView.java new file mode 100644 index 0000000000..81fc337fcd --- /dev/null +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/ConfirmFiatReceivedView.java @@ -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 . + */ + +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 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); + } +} + + diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/ConfirmFiatView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/ConfirmFiatView.java deleted file mode 100644 index 3d4574da60..0000000000 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/ConfirmFiatView.java +++ /dev/null @@ -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 . - */ - -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"); - } - -} - - diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/StartFiatView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/StartFiatView.java index d8e833f07d..3b878dfeda 100644 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/StartFiatView.java +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/StartFiatView.java @@ -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 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); + } } diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/TradeStepDetailsView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/TradeStepDetailsView.java new file mode 100644 index 0000000000..32b550d3cb --- /dev/null +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/TradeStepDetailsView.java @@ -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 . + */ + +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(); +} diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/TradeWizardItem.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/TradeWizardItem.java similarity index 81% rename from core/src/main/java/io/bitsquare/gui/main/portfolio/pending/TradeWizardItem.java rename to core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/TradeWizardItem.java index 89912b43c0..83563cb6db 100644 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/TradeWizardItem.java +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/TradeWizardItem.java @@ -15,42 +15,45 @@ * along with Bitsquare. If not, see . */ -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 getViewClass() { + public Class getViewClass() { return viewClass; } - private final Class viewClass; + private final Class viewClass; - public TradeWizardItem(Class viewClass, String title) { + public TradeWizardItem(Class 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); diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/WaitFiatReceivedView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/WaitFiatReceivedView.java new file mode 100644 index 0000000000..0f693204bf --- /dev/null +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/WaitFiatReceivedView.java @@ -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 . + */ + +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 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); + } +} + + diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/WaitTxInBlockchainView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/WaitTxInBlockchainView.java new file mode 100644 index 0000000000..fa232db9b5 --- /dev/null +++ b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/WaitTxInBlockchainView.java @@ -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 . + */ + +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 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); + } +} + + diff --git a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/WaitView.java b/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/WaitView.java deleted file mode 100644 index cb6b2fb4f7..0000000000 --- a/core/src/main/java/io/bitsquare/gui/main/portfolio/pending/steps/WaitView.java +++ /dev/null @@ -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 . - */ - -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"); - } -} - - diff --git a/core/src/main/java/io/bitsquare/gui/util/ComponentBuilder.java b/core/src/main/java/io/bitsquare/gui/util/ComponentBuilder.java index c709fb5a01..772e17b493 100644 --- a/core/src/main/java/io/bitsquare/gui/util/ComponentBuilder.java +++ b/core/src/main/java/io/bitsquare/gui/util/ComponentBuilder.java @@ -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); }