mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 15:10:44 +01:00
Handle views for trade process
This commit is contained in:
parent
3a95e51bc9
commit
a2aa0b40b4
18 changed files with 273 additions and 296 deletions
|
@ -61,14 +61,7 @@ public class TaskRunner<T extends Model> {
|
|||
try {
|
||||
currentTask = tasks.poll();
|
||||
log.trace("Run task: " + currentTask.getSimpleName());
|
||||
log.debug("sharedModel.getClass() " + sharedModel.getClass());
|
||||
log.debug("sharedModel.getClass().getSuperclass() " + sharedModel.getClass().getSuperclass());
|
||||
/* Object c = currentTask.getDeclaredConstructor(TaskRunner.class, sharedModel.getClass());
|
||||
log.debug("c " + c);
|
||||
Object c2 = currentTask.getDeclaredConstructor(TaskRunner.class, sharedModel.getClass().getSuperclass());
|
||||
log.debug("c getSuperclass " + c2);
|
||||
Object o = currentTask.getDeclaredConstructor(TaskRunner.class, sharedModel.getClass()).newInstance(this, sharedModel);*/
|
||||
//TODO solve in tasks problem with superclasses
|
||||
// We use also super class as type ein tasks, so we need to support both variants
|
||||
try {
|
||||
currentTask.getDeclaredConstructor(TaskRunner.class, sharedModel.getClass()).newInstance(this, sharedModel).run();
|
||||
} catch (Throwable throwable) {
|
||||
|
|
|
@ -79,8 +79,11 @@ public class BuyerSubView extends TradeSubView {
|
|||
waitFiatReceived.inactive();
|
||||
completed.inactive();
|
||||
|
||||
if (tradeStepDetailsView != null)
|
||||
tradeStepDetailsView.deactivate();
|
||||
|
||||
switch (viewState) {
|
||||
case EMPTY:
|
||||
case UNDEFINED:
|
||||
break;
|
||||
case BUYER_WAIT_TX_CONF:
|
||||
showItem(waitTxInBlockchain);
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pending;
|
||||
|
||||
// That is used if trade is null but must not be null in that state
|
||||
public class MissingTradeException extends RuntimeException {
|
||||
|
||||
public MissingTradeException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public MissingTradeException() {
|
||||
super("Trade is null.That must not happen.");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pending;
|
||||
|
||||
// That is used if trade is null and it is a valid state
|
||||
public class NoTradeFoundException extends Throwable {
|
||||
|
||||
public NoTradeFoundException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public NoTradeFoundException() {
|
||||
super("Trade is null");
|
||||
}
|
||||
}
|
|
@ -21,7 +21,11 @@ import io.bitsquare.btc.FeePolicy;
|
|||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.common.viewfx.model.Activatable;
|
||||
import io.bitsquare.common.viewfx.model.DataModel;
|
||||
import io.bitsquare.gui.Navigation;
|
||||
import io.bitsquare.gui.components.Popups;
|
||||
import io.bitsquare.gui.main.MainView;
|
||||
import io.bitsquare.gui.main.portfolio.PortfolioView;
|
||||
import io.bitsquare.gui.main.portfolio.closed.ClosedTradesView;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.trade.BuyerTrade;
|
||||
import io.bitsquare.trade.Contract;
|
||||
|
@ -37,9 +41,8 @@ import com.google.inject.Inject;
|
|||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
|
@ -56,6 +59,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
private final TradeManager tradeManager;
|
||||
private final WalletService walletService;
|
||||
private final User user;
|
||||
private Navigation navigation;
|
||||
|
||||
private final ObservableList<PendingTradesListItem> list = FXCollections.observableArrayList();
|
||||
|
||||
|
@ -65,7 +69,6 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
private final ListChangeListener<Trade> tradesListChangeListener;
|
||||
|
||||
final StringProperty txId = new SimpleStringProperty();
|
||||
final IntegerProperty selectedIndex = new SimpleIntegerProperty(-1);
|
||||
|
||||
final ObjectProperty<TradeState.ProcessState> sellerProcessState = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<TradeState.ProcessState> buyerProcessState = new SimpleObjectProperty<>();
|
||||
|
@ -73,23 +76,19 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
final ObjectProperty<Trade> currentTrade = new SimpleObjectProperty<>();
|
||||
|
||||
@Inject
|
||||
public PendingTradesDataModel(TradeManager tradeManager, WalletService walletService, User user) {
|
||||
public PendingTradesDataModel(TradeManager tradeManager, WalletService walletService, User user, Navigation navigation) {
|
||||
this.tradeManager = tradeManager;
|
||||
this.walletService = walletService;
|
||||
this.user = user;
|
||||
this.navigation = navigation;
|
||||
|
||||
tradesListChangeListener = change -> onListChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
onListChanged();
|
||||
tradeManager.getPendingTrades().addListener(tradesListChangeListener);
|
||||
|
||||
if (list.size() > 0) {
|
||||
selectTrade(list.get(0));
|
||||
selectedIndex.set(0);
|
||||
}
|
||||
onListChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -105,20 +104,22 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
// we sort by date, earliest first
|
||||
list.sort((o1, o2) -> o2.getTrade().getDate().compareTo(o1.getTrade().getDate()));
|
||||
|
||||
if (list.size() > 0) {
|
||||
log.debug("onListChanged {}", list.size());
|
||||
if (list.size() > 0)
|
||||
selectTrade(list.get(0));
|
||||
selectedIndex.set(0);
|
||||
}
|
||||
else if (list.size() == 0)
|
||||
selectTrade(null);
|
||||
}
|
||||
|
||||
boolean isBuyOffer() {
|
||||
boolean isBuyOffer() throws NoTradeFoundException {
|
||||
if (getTrade() != null)
|
||||
return getTrade().getOffer().getDirection() == Offer.Direction.BUY;
|
||||
else
|
||||
return false;
|
||||
throw new NoTradeFoundException();
|
||||
}
|
||||
|
||||
void selectTrade(PendingTradesListItem item) {
|
||||
log.debug("selectTrade {} {}", item != null, item != null ? item.getTrade().getId() : "null");
|
||||
// clean up previous selectedItem
|
||||
unbindStates();
|
||||
|
||||
|
@ -144,52 +145,67 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
}
|
||||
|
||||
void fiatPaymentStarted() {
|
||||
if (getTrade() instanceof BuyerTrade)
|
||||
((BuyerTrade) getTrade()).onFiatPaymentStarted();
|
||||
try {
|
||||
if (getTrade() instanceof BuyerTrade)
|
||||
((BuyerTrade) getTrade()).onFiatPaymentStarted();
|
||||
} catch (NoTradeFoundException e) {
|
||||
throw new MissingTradeException();
|
||||
}
|
||||
}
|
||||
|
||||
void fiatPaymentReceived() {
|
||||
if (getTrade() instanceof SellerTrade)
|
||||
((SellerTrade) getTrade()).onFiatPaymentReceived();
|
||||
try {
|
||||
if (getTrade() instanceof SellerTrade)
|
||||
((SellerTrade) getTrade()).onFiatPaymentReceived();
|
||||
} catch (NoTradeFoundException e) {
|
||||
throw new MissingTradeException();
|
||||
}
|
||||
}
|
||||
|
||||
void withdraw(String toAddress) {
|
||||
if (getTrade() != null) {
|
||||
tradeManager.requestWithdraw(toAddress,
|
||||
getTrade(),
|
||||
() -> log.debug("requestWithdraw was successful"),
|
||||
(errorMessage, throwable) -> {
|
||||
log.error(errorMessage);
|
||||
Popups.openExceptionPopup(throwable);
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
Action response = Popups.openConfirmPopup(
|
||||
"Withdrawal request", "Confirm your request",
|
||||
"Your withdrawal request:\n\n" + "Amount: " + amountTextField.getText() + " BTC\n" + "Sending" +
|
||||
" address: " + withdrawFromTextField.getText() + "\n" + "Receiving address: " +
|
||||
withdrawToTextField.getText() + "\n" + "Transaction fee: " +
|
||||
formatter.formatCoinWithCode(FeePolicy.TX_FEE) + "\n" +
|
||||
"You receive in total: " +
|
||||
formatter.formatCoinWithCode(amount.subtract(FeePolicy.TX_FEE)) + " BTC\n\n" +
|
||||
"Are you sure you withdraw that amount?");
|
||||
|
||||
if (Popups.isOK(response)) {
|
||||
try {
|
||||
walletService.sendFunds(
|
||||
withdrawFromTextField.getText(), withdrawToTextField.getText(),
|
||||
changeAddressTextField.getText(), amount, callback);
|
||||
} catch (AddressFormatException e) {
|
||||
Popups.openErrorPopup("Address invalid",
|
||||
"The address is not correct. Please check the address format.");
|
||||
|
||||
} catch (InsufficientMoneyException e) {
|
||||
Popups.openInsufficientMoneyPopup();
|
||||
} catch (IllegalArgumentException e) {
|
||||
Popups.openErrorPopup("Wrong inputs", "Please check the inputs.");
|
||||
try {
|
||||
if (getTrade() != null) {
|
||||
tradeManager.requestWithdraw(toAddress,
|
||||
getTrade(),
|
||||
() -> {
|
||||
log.debug("requestWithdraw was successful");
|
||||
Platform.runLater(() -> navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class));
|
||||
},
|
||||
(errorMessage, throwable) -> {
|
||||
log.error(errorMessage);
|
||||
Popups.openExceptionPopup(throwable);
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
Action response = Popups.openConfirmPopup(
|
||||
"Withdrawal request", "Confirm your request",
|
||||
"Your withdrawal request:\n\n" + "Amount: " + amountTextField.getText() + " BTC\n" + "Sending" +
|
||||
" address: " + withdrawFromTextField.getText() + "\n" + "Receiving address: " +
|
||||
withdrawToTextField.getText() + "\n" + "Transaction fee: " +
|
||||
formatter.formatCoinWithCode(FeePolicy.TX_FEE) + "\n" +
|
||||
"You receive in total: " +
|
||||
formatter.formatCoinWithCode(amount.subtract(FeePolicy.TX_FEE)) + " BTC\n\n" +
|
||||
"Are you sure you withdraw that amount?");
|
||||
|
||||
if (Popups.isOK(response)) {
|
||||
try {
|
||||
walletService.sendFunds(
|
||||
withdrawFromTextField.getText(), withdrawToTextField.getText(),
|
||||
changeAddressTextField.getText(), amount, callback);
|
||||
} catch (AddressFormatException e) {
|
||||
Popups.openErrorPopup("Address invalid",
|
||||
"The address is not correct. Please check the address format.");
|
||||
|
||||
} catch (InsufficientMoneyException e) {
|
||||
Popups.openInsufficientMoneyPopup();
|
||||
} catch (IllegalArgumentException e) {
|
||||
Popups.openErrorPopup("Wrong inputs", "Please check the inputs.");
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}*/
|
||||
} catch (NoTradeFoundException e) {
|
||||
throw new MissingTradeException();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,17 +239,19 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
}
|
||||
|
||||
Throwable getTradeException() {
|
||||
if (getTrade() != null)
|
||||
try {
|
||||
return getTrade().getThrowable();
|
||||
else
|
||||
} catch (NoTradeFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String getErrorMessage() {
|
||||
if (getTrade() != null)
|
||||
try {
|
||||
return getTrade().getErrorMessage();
|
||||
else
|
||||
} catch (NoTradeFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Offer.Direction getDirection(Offer offer) {
|
||||
|
@ -247,21 +265,26 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
}
|
||||
|
||||
public Coin getPayoutAmount() {
|
||||
return getTrade().getPayoutAmount();
|
||||
try {
|
||||
return getTrade().getPayoutAmount();
|
||||
} catch (NoTradeFoundException e) {
|
||||
return Coin.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
public Contract getContract() {
|
||||
if (getTrade() != null)
|
||||
try {
|
||||
return getTrade().getContract();
|
||||
else
|
||||
return null;
|
||||
} catch (NoTradeFoundException e) {
|
||||
throw new MissingTradeException();
|
||||
}
|
||||
}
|
||||
|
||||
public Trade getTrade() {
|
||||
public Trade getTrade() throws NoTradeFoundException {
|
||||
if (currentTrade.get() != null)
|
||||
return currentTrade.get();
|
||||
else
|
||||
return null;
|
||||
throw new NoTradeFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ 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.components.Popups;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.util.Utilities;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
@ -30,6 +31,7 @@ import java.util.Date;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.fxml.FXML;
|
||||
|
@ -55,7 +57,9 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
|||
|
||||
private ChangeListener<PendingTradesListItem> selectedItemChangeListener;
|
||||
private TradeSubView currentSubView;
|
||||
|
||||
private ChangeListener<Boolean> appFocusChangeListener;
|
||||
private ReadOnlyBooleanProperty appFocusProperty;
|
||||
private ChangeListener<Trade> currentTradeChangeListener;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
|
@ -79,17 +83,43 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
|||
table.setPlaceholder(new Label("No pending trades available"));
|
||||
|
||||
selectedItemChangeListener = (ov, oldValue, newValue) -> {
|
||||
log.debug("selectedItemChangeListener {}", newValue);
|
||||
model.selectTrade(newValue);
|
||||
|
||||
if (newValue != null)
|
||||
addSubView();
|
||||
else
|
||||
removeSubView();
|
||||
};
|
||||
|
||||
model.selectTrade(newValue);
|
||||
appFocusChangeListener = (observable, oldValue, newValue) -> {
|
||||
log.debug("appFocusChangeListener {}", newValue);
|
||||
if (newValue && model.getSelectedItem() != null) {
|
||||
// Focus selectedItem from model
|
||||
int index = table.getItems().indexOf(model.getSelectedItem());
|
||||
Platform.runLater(() -> {
|
||||
table.requestFocus();
|
||||
Platform.runLater(() -> table.getFocusModel().focus(index));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
currentTradeChangeListener = (observable, oldValue, newValue) -> {
|
||||
log.debug("currentTradeChangeListener {} {}", newValue, model.getList().size());
|
||||
if (newValue != null)
|
||||
addSubView();
|
||||
else
|
||||
removeSubView();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void doActivate() {
|
||||
appFocusProperty = root.getScene().getWindow().focusedProperty();
|
||||
appFocusProperty.addListener(appFocusChangeListener);
|
||||
model.currentTrade().addListener(currentTradeChangeListener);
|
||||
table.setItems(model.getList());
|
||||
|
||||
table.getSelectionModel().selectedItemProperty().addListener(selectedItemChangeListener);
|
||||
PendingTradesListItem selectedItem = model.getSelectedItem();
|
||||
if (selectedItem != null) {
|
||||
|
@ -117,6 +147,9 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
|||
|
||||
if (currentSubView != null)
|
||||
currentSubView.deactivate();
|
||||
|
||||
appFocusProperty.removeListener(appFocusChangeListener);
|
||||
model.currentTrade().removeListener(currentTradeChangeListener);
|
||||
}
|
||||
|
||||
|
||||
|
@ -125,31 +158,48 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void addSubView() {
|
||||
log.debug("addSubView");
|
||||
removeSubView();
|
||||
|
||||
if (model.isOfferer()) {
|
||||
if (model.isBuyOffer())
|
||||
currentSubView = new BuyerSubView(model);
|
||||
else
|
||||
currentSubView = new SellerSubView(model);
|
||||
try {
|
||||
if (model.isBuyOffer())
|
||||
currentSubView = new BuyerSubView(model);
|
||||
else
|
||||
currentSubView = new SellerSubView(model);
|
||||
} catch (NoTradeFoundException e) {
|
||||
log.warn("No trade selected");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (model.isBuyOffer())
|
||||
currentSubView = new SellerSubView(model);
|
||||
else
|
||||
currentSubView = new BuyerSubView(model);
|
||||
try {
|
||||
if (model.isBuyOffer())
|
||||
currentSubView = new SellerSubView(model);
|
||||
else
|
||||
currentSubView = new BuyerSubView(model);
|
||||
} catch (NoTradeFoundException e) {
|
||||
log.warn("No trade selected");
|
||||
}
|
||||
}
|
||||
currentSubView.activate();
|
||||
if (currentSubView != null) {
|
||||
currentSubView.activate();
|
||||
|
||||
AnchorPane.setTopAnchor(currentSubView, 0d);
|
||||
AnchorPane.setRightAnchor(currentSubView, 0d);
|
||||
AnchorPane.setBottomAnchor(currentSubView, 0d);
|
||||
AnchorPane.setLeftAnchor(currentSubView, 0d);
|
||||
tradeStepPane.getChildren().setAll(currentSubView);
|
||||
AnchorPane.setTopAnchor(currentSubView, 0d);
|
||||
AnchorPane.setRightAnchor(currentSubView, 0d);
|
||||
AnchorPane.setBottomAnchor(currentSubView, 0d);
|
||||
AnchorPane.setLeftAnchor(currentSubView, 0d);
|
||||
tradeStepPane.getChildren().setAll(currentSubView);
|
||||
log.warn("currentSubView added");
|
||||
}
|
||||
else {
|
||||
log.warn("currentSubView=null");
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSubView() {
|
||||
log.debug("removeSubView called");
|
||||
if (currentSubView != null) {
|
||||
log.debug("remove currentSubView");
|
||||
currentSubView.deactivate();
|
||||
tradeStepPane.getChildren().remove(currentSubView);
|
||||
currentSubView = null;
|
||||
|
|
|
@ -20,13 +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;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.states.OffererTradeState;
|
||||
import io.bitsquare.trade.states.TakerTradeState;
|
||||
|
||||
|
@ -37,13 +34,10 @@ 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;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
|
@ -56,7 +50,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
|||
private static final Logger log = LoggerFactory.getLogger(PendingTradesViewModel.class);
|
||||
|
||||
enum ViewState {
|
||||
EMPTY,
|
||||
UNDEFINED,
|
||||
SELLER_WAIT_TX_CONF,
|
||||
SELLER_WAIT_PAYMENT_STARTED,
|
||||
SELLER_CONFIRM_RECEIVE_PAYMENT,
|
||||
|
@ -71,25 +65,22 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
|||
EXCEPTION
|
||||
}
|
||||
|
||||
private Navigation navigation;
|
||||
|
||||
private final BSFormatter formatter;
|
||||
private final InvalidationListener sellerStateListener;
|
||||
private final InvalidationListener buyerStateListener;
|
||||
|
||||
|
||||
private final BtcAddressValidator btcAddressValidator;
|
||||
|
||||
public final StringProperty txId = new SimpleStringProperty();
|
||||
public final BooleanProperty withdrawalButtonDisable = new SimpleBooleanProperty(true);
|
||||
final IntegerProperty selectedIndex = new SimpleIntegerProperty(-1);
|
||||
final ObjectProperty<ViewState> viewState = new SimpleObjectProperty<>(ViewState.EMPTY);
|
||||
final ObjectProperty<ViewState> viewState = new SimpleObjectProperty<>(ViewState.UNDEFINED);
|
||||
|
||||
|
||||
@Inject
|
||||
public PendingTradesViewModel(PendingTradesDataModel dataModel, Navigation navigation, BSFormatter formatter,
|
||||
public PendingTradesViewModel(PendingTradesDataModel dataModel, BSFormatter formatter,
|
||||
BtcAddressValidator btcAddressValidator) {
|
||||
super(dataModel);
|
||||
this.navigation = navigation;
|
||||
|
||||
this.formatter = formatter;
|
||||
this.btcAddressValidator = btcAddressValidator;
|
||||
|
@ -100,7 +91,6 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
|||
@Override
|
||||
public void doActivate() {
|
||||
txId.bind(dataModel.txId);
|
||||
selectedIndex.bind(dataModel.selectedIndex);
|
||||
|
||||
dataModel.sellerProcessState.addListener(sellerStateListener);
|
||||
dataModel.buyerProcessState.addListener(buyerStateListener);
|
||||
|
@ -112,7 +102,6 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
|||
@Override
|
||||
public void doDeactivate() {
|
||||
txId.unbind();
|
||||
selectedIndex.unbind();
|
||||
|
||||
dataModel.sellerProcessState.removeListener(sellerStateListener);
|
||||
dataModel.buyerProcessState.removeListener(buyerStateListener);
|
||||
|
@ -123,10 +112,13 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
|||
dataModel.selectTrade(item);
|
||||
}
|
||||
|
||||
boolean isBuyOffer() {
|
||||
boolean isBuyOffer() throws NoTradeFoundException {
|
||||
return dataModel.isBuyOffer();
|
||||
}
|
||||
|
||||
ObjectProperty<Trade> currentTrade() {
|
||||
return dataModel.currentTrade;
|
||||
}
|
||||
|
||||
public void fiatPaymentStarted() {
|
||||
dataModel.fiatPaymentStarted();
|
||||
|
@ -138,7 +130,6 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
|||
|
||||
public void withdraw(String withdrawToAddress) {
|
||||
dataModel.withdraw(withdrawToAddress);
|
||||
Platform.runLater(() -> navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class));
|
||||
}
|
||||
|
||||
public void withdrawAddressFocusOut(String text) {
|
||||
|
@ -201,7 +192,11 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
|||
}
|
||||
|
||||
public String getFiatAmount() {
|
||||
return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume());
|
||||
try {
|
||||
return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume());
|
||||
} catch (NoTradeFoundException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String getHolderName() {
|
||||
|
@ -221,11 +216,19 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
|||
|
||||
// summary
|
||||
public String getTradeVolume() {
|
||||
return dataModel.getTrade() != null ? formatter.formatCoinWithCode(dataModel.getTrade().getTradeAmount()) : "";
|
||||
try {
|
||||
return formatter.formatCoinWithCode(dataModel.getTrade().getTradeAmount());
|
||||
} catch (NoTradeFoundException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String getFiatVolume() {
|
||||
return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume());
|
||||
try {
|
||||
return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume());
|
||||
} catch (NoTradeFoundException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String getTotalFees() {
|
||||
|
@ -235,10 +238,15 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
|||
public String getSecurityDeposit() {
|
||||
// securityDeposit is handled different for offerer and taker.
|
||||
// Offerer have paid in the max amount, but taker might have taken less so also paid in less securityDeposit
|
||||
if (dataModel.isOfferer())
|
||||
return formatter.formatCoinWithCode(dataModel.getTrade().getOffer().getSecurityDeposit());
|
||||
else
|
||||
return formatter.formatCoinWithCode(dataModel.getTrade().getSecurityDeposit());
|
||||
try {
|
||||
if (dataModel.isOfferer())
|
||||
return formatter.formatCoinWithCode(dataModel.getTrade().getOffer().getSecurityDeposit());
|
||||
else
|
||||
return formatter.formatCoinWithCode(dataModel.getTrade().getSecurityDeposit());
|
||||
|
||||
} catch (NoTradeFoundException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public BtcAddressValidator getBtcAddressValidator() {
|
||||
|
|
|
@ -78,8 +78,11 @@ public class SellerSubView extends TradeSubView {
|
|||
confirmFiatReceived.inactive();
|
||||
completed.inactive();
|
||||
|
||||
if (tradeStepDetailsView != null)
|
||||
tradeStepDetailsView.deactivate();
|
||||
|
||||
switch (viewState) {
|
||||
case EMPTY:
|
||||
case UNDEFINED:
|
||||
break;
|
||||
case SELLER_WAIT_TX_CONF:
|
||||
showItem(waitTxInBlockchain);
|
||||
|
|
|
@ -33,8 +33,8 @@ public abstract class TradeSubView extends HBox {
|
|||
protected VBox leftVBox;
|
||||
protected AnchorPane contentPane;
|
||||
protected PendingTradesViewModel model;
|
||||
protected ChangeListener<PendingTradesViewModel.ViewState> offererStateChangeListener;
|
||||
protected TradeStepDetailsView tradeStepDetailsView;
|
||||
protected ChangeListener<PendingTradesViewModel.ViewState> offererStateChangeListener;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -24,7 +24,6 @@ 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.*;
|
||||
|
@ -84,7 +83,7 @@ public class StartFiatView extends TradeStepDetailsView {
|
|||
super.activate();
|
||||
|
||||
model.txId.addListener(txIdChangeListener);
|
||||
Platform.runLater(() -> txIdTextField.setup(model.getWalletService(), model.txId.get()));
|
||||
txIdTextField.setup(model.getWalletService(), model.txId.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -54,6 +54,7 @@ public abstract class TradeStepDetailsView extends AnchorPane {
|
|||
buildGridEntries();
|
||||
}
|
||||
|
||||
// That is called at every state change!
|
||||
public void activate() {
|
||||
log.debug("activate");
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ 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.offer.OffersView;
|
||||
import io.bitsquare.gui.main.portfolio.pending.PendingTradesView;
|
||||
import io.bitsquare.gui.main.trade.TradeView;
|
||||
import io.bitsquare.gui.util.ImageUtil;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
|
@ -295,7 +294,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
|||
// TODO temp just for testing
|
||||
newValue = false;
|
||||
close();
|
||||
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class, OffersView.class);
|
||||
navigation.navigateTo(MainView.class, PortfolioView.class, OffersView.class);
|
||||
|
||||
if (newValue) {
|
||||
overlayManager.blurContent();
|
||||
|
|
|
@ -282,7 +282,7 @@ public class Offer implements Serializable {
|
|||
", fiatPrice=" + fiatPrice +
|
||||
", amount=" + amount +
|
||||
", minAmount=" + minAmount +
|
||||
", p2pSigPubKey=" + p2pSigPubKey +
|
||||
/* ", p2pSigPubKey=" + p2pSigPubKey +*/
|
||||
", fiatAccountType=" + fiatAccountType +
|
||||
", bankAccountCountry=" + bankAccountCountry +
|
||||
", securityDeposit=" + securityDeposit +
|
||||
|
@ -292,6 +292,7 @@ public class Offer implements Serializable {
|
|||
", arbitratorIds=" + arbitratorIds +
|
||||
", offerFeePaymentTxID='" + offerFeePaymentTxID + '\'' +
|
||||
", state=" + state +
|
||||
", stateProperty=" + stateProperty +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
*/
|
||||
public class FileManager<T> {
|
||||
private static final Logger log = LoggerFactory.getLogger(FileManager.class);
|
||||
private static final ReentrantLock lock = Threading.lock("FileUtil");
|
||||
private static final ReentrantLock lock = Threading.lock("FileManager");
|
||||
|
||||
private final File dir;
|
||||
private final File storageFile;
|
||||
|
@ -164,6 +164,7 @@ public class FileManager<T> {
|
|||
}
|
||||
|
||||
public T read(File file) throws IOException, ClassNotFoundException {
|
||||
log.debug("read" + file);
|
||||
lock.lock();
|
||||
try (final FileInputStream fileInputStream = new FileInputStream(file);
|
||||
final ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
|
||||
|
@ -256,6 +257,9 @@ public class FileManager<T> {
|
|||
fileOutputStream = new FileOutputStream(tempFile);
|
||||
objectOutputStream = new ObjectOutputStream(fileOutputStream);
|
||||
|
||||
// TODO ConcurrentModificationException happens sometimes at that line
|
||||
//log.debug("serializable " + serializable.toString());
|
||||
log.debug("storageFile " + storageFile.toString());
|
||||
objectOutputStream.writeObject(serializable);
|
||||
|
||||
// Attempt to force the bits to hit the disk. In reality the OS or hard disk itself may still decide
|
||||
|
@ -271,6 +275,7 @@ public class FileManager<T> {
|
|||
renameTempFileToFile(tempFile, storageFile);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
log.error("Error at saveToFile: " + t.getMessage());
|
||||
} finally {
|
||||
if (tempFile != null && tempFile.exists()) {
|
||||
log.warn("Temp file still exists after failed save. storageFile=" + storageFile);
|
||||
|
@ -286,7 +291,7 @@ public class FileManager<T> {
|
|||
} catch (IOException e) {
|
||||
// We swallow that
|
||||
e.printStackTrace();
|
||||
log.error("Cannot close resources.");
|
||||
log.error("Cannot close resources." + e.getMessage());
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
|
|
@ -427,7 +427,6 @@ abstract public class Trade implements Model, Serializable {
|
|||
|
||||
abstract protected void initStates();
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Trade{" +
|
||||
|
@ -446,10 +445,10 @@ abstract public class Trade implements Model, Serializable {
|
|||
", lifeCycleState=" + lifeCycleState +
|
||||
", mailboxMessage=" + mailboxMessage +
|
||||
", depositTx=" + depositTx +
|
||||
", contract=" + contract +
|
||||
", contractAsJson='" + contractAsJson + '\'' +
|
||||
", sellerContractSignature='" + sellerContractSignature + '\'' +
|
||||
", buyerContractSignature='" + buyerContractSignature + '\'' +
|
||||
/* ", contract=" + contract +
|
||||
", contractAsJson='" + contractAsJson + '\'' +*/
|
||||
/* ", sellerContractSignature='" + sellerContractSignature + '\'' +
|
||||
", buyerContractSignature='" + buyerContractSignature + '\'' +*/
|
||||
", payoutTx=" + payoutTx +
|
||||
", errorMessage='" + errorMessage + '\'' +
|
||||
", throwable=" + throwable +
|
||||
|
|
|
@ -167,14 +167,6 @@ public class ProcessModel implements Model, Serializable {
|
|||
return mailboxMessage;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ProcessModel{" +
|
||||
"offer=" + offer +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Transaction getPayoutTx() {
|
||||
return payoutTx;
|
||||
|
@ -280,11 +272,9 @@ public class ProcessModel implements Model, Serializable {
|
|||
|
||||
@Override
|
||||
public void persist() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import java.io.Serializable;
|
|||
|
||||
import java.security.PublicKey;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
@ -178,24 +177,4 @@ public class TradingPeer implements Serializable {
|
|||
public void setContractSignature(String contractSignature) {
|
||||
this.contractSignature = contractSignature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TradingPeer{" +
|
||||
"accountId='" + accountId + '\'' +
|
||||
", p2pSigPubKey=" + p2pSigPubKey +
|
||||
", p2pEncryptPubKey=" + p2pEncryptPubKey +
|
||||
", tradeWalletPubKey=" + Arrays.toString(tradeWalletPubKey) +
|
||||
", fiatAccount=" + fiatAccount +
|
||||
", preparedDepositTx=" + preparedDepositTx +
|
||||
", connectedOutputsForAllInputs=" + connectedOutputsForAllInputs +
|
||||
", outputs=" + outputs +
|
||||
", payoutAmount=" + payoutAmount +
|
||||
", payoutAddressString='" + payoutAddressString + '\'' +
|
||||
", signature=" + Arrays.toString(signature) +
|
||||
", contractAsJson='" + contractAsJson + '\'' +
|
||||
", contractSignature='" + contractSignature + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,136 +0,0 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.trade.protocol.placeoffer;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TaskRunner {
|
||||
private static final Logger log = LoggerFactory.getLogger(TaskRunner.class);
|
||||
|
||||
private Queue<Class> tasks;
|
||||
private SharedModel sharedModel = new SharedModel();
|
||||
private FaultHandler faultHandler;
|
||||
private ResultHandler taskCompleted;
|
||||
private final boolean[] failed = {false};
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
// Task1.run();
|
||||
//Task2.run();
|
||||
|
||||
tasks = new LinkedBlockingQueue<>();
|
||||
tasks.add(Task1.class);
|
||||
tasks.add(Task2.class);
|
||||
|
||||
faultHandler = (throwable) -> {
|
||||
log.debug(throwable.getMessage());
|
||||
failed[0] = true;
|
||||
};
|
||||
taskCompleted = () -> {
|
||||
next();
|
||||
};
|
||||
next();
|
||||
/* ResultHandler handleResult = () -> {
|
||||
Class task = tasks.poll();
|
||||
try {
|
||||
if (!failed[0])
|
||||
((Task) task.newInstance()).run(sharedModel, taskCompleted, faultHandler);
|
||||
} catch (InstantiationException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (IllegalAccessException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
};*/
|
||||
|
||||
|
||||
|
||||
/* tasks.stream().forEach((e) -> {
|
||||
try {
|
||||
((Task) e.newInstance()).run(sharedModel, faultHandler);
|
||||
} catch (InstantiationException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (IllegalAccessException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
});*/
|
||||
}
|
||||
|
||||
private void next() {
|
||||
Class task = tasks.poll();
|
||||
if (task != null) {
|
||||
try {
|
||||
if (!failed[0])
|
||||
((Task) task.newInstance()).run(sharedModel, taskCompleted, faultHandler);
|
||||
} catch (InstantiationException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (IllegalAccessException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ResultHandler {
|
||||
void handleResult();
|
||||
}
|
||||
|
||||
interface FaultHandler {
|
||||
void handleFault(Throwable throwable);
|
||||
}
|
||||
|
||||
class SharedModel {
|
||||
public int data = 42;
|
||||
}
|
||||
|
||||
class Task {
|
||||
|
||||
protected void run(SharedModel sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Task1 extends Task {
|
||||
private static final Logger log = LoggerFactory.getLogger(Task1.class);
|
||||
|
||||
@Override
|
||||
public void run(SharedModel sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) {
|
||||
log.debug("run " + Task1.class);
|
||||
log.debug("data " + sharedModel.data);
|
||||
// faultHandler.handleFault(new Exception("test"));
|
||||
sharedModel.data++;
|
||||
resultHandler.handleResult();
|
||||
}
|
||||
}
|
||||
|
||||
class Task2 extends Task {
|
||||
private static final Logger log = LoggerFactory.getLogger(Task2.class);
|
||||
|
||||
@Override
|
||||
public void run(SharedModel sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) {
|
||||
log.debug("run " + Task2.class);
|
||||
log.debug("data " + sharedModel.data);
|
||||
resultHandler.handleResult();
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue