Fix missing update in open trades table (part of #239)

This commit is contained in:
Manfred Karrer 2014-11-13 00:28:33 +01:00
parent d657763596
commit 57faf40759
5 changed files with 156 additions and 144 deletions

View file

@ -19,13 +19,20 @@ package io.bitsquare.gui.main.portfolio.pending;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.Fiat;
import java.util.Date;
import javafx.beans.property.ObjectProperty;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* We could remove that wrapper if it is not needed for additional UI only fields. * We could remove that wrapper if it is not needed for additional UI only fields.
*/ */
class PendingTradesListItem { public class PendingTradesListItem {
private static final Logger log = LoggerFactory.getLogger(PendingTradesListItem.class); private static final Logger log = LoggerFactory.getLogger(PendingTradesListItem.class);
private final Trade trade; private final Trade trade;
@ -35,16 +42,35 @@ class PendingTradesListItem {
// Constructor // Constructor
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
PendingTradesListItem(Trade trade) { public PendingTradesListItem(Trade trade) {
this.trade = trade; this.trade = trade;
} }
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Getters // Getters
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
Trade getTrade() { public Trade getTrade() {
return trade; return trade;
} }
public ObjectProperty<Coin> tradeAmountProperty() {
return trade.tradeAmountProperty();
}
public ObjectProperty<Fiat> tradeVolumeProperty() {
return trade.tradeVolumeProperty();
}
public Date getDate() {
return trade.getDate();
}
public String getId() {
return trade.getId();
}
public Fiat getPrice() {
return trade.getOffer().getPrice();
}
} }

View file

@ -24,8 +24,13 @@ import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.gui.util.validation.BtcAddressValidator; import io.bitsquare.gui.util.validation.BtcAddressValidator;
import io.bitsquare.locale.BSResources; import io.bitsquare.locale.BSResources;
import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.Fiat;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.util.Date;
import javafx.beans.InvalidationListener; import javafx.beans.InvalidationListener;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
@ -174,28 +179,28 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
} }
// columns // columns
String getTradeId(PendingTradesListItem item) { String formatTradeId(String value) {
return item.getTrade().getId(); return value;
} }
String getAmount(PendingTradesListItem item) { String formatTradeAmount(Coin value) {
return (item != null) ? formatter.formatCoinWithCode(item.getTrade().getTradeAmount()) : ""; return formatter.formatCoinWithCode(value);
} }
String getPrice(PendingTradesListItem item) { String formatPrice(Fiat value) {
return (item != null) ? formatter.formatFiat(item.getTrade().getOffer().getPrice()) : ""; return formatter.formatFiat(value);
} }
String getVolume(PendingTradesListItem item) { String formatTradeVolume(Fiat value) {
return (item != null) ? formatter.formatFiatWithCode(item.getTrade().getTradeVolume()) : ""; return formatter.formatFiatWithCode(value);
} }
String getDirectionLabel(PendingTradesListItem item) { String evaluateDirection(PendingTradesListItem item) {
return (item != null) ? formatter.formatDirection(model.getDirection(item.getTrade().getOffer())) : ""; return (item != null) ? formatter.formatDirection(model.getDirection(item.getTrade().getOffer())) : "";
} }
String getDate(PendingTradesListItem item) { String formatDate(Date value) {
return formatter.formatDateTime(item.getTrade().getDate()); return formatter.formatDateTime(value);
} }
// payment // payment

View file

@ -26,6 +26,7 @@
<?import io.bitsquare.gui.components.TxIdTextField?> <?import io.bitsquare.gui.components.TxIdTextField?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.portfolio.pending.PendingTradesViewCB" <AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.portfolio.pending.PendingTradesViewCB"
xmlns:fx="http://javafx.com/fxml"> xmlns:fx="http://javafx.com/fxml">
@ -48,11 +49,31 @@
<Insets top="10.0" left="-10" right="-10" bottom="-15"/> <Insets top="10.0" left="-10" right="-10" bottom="-15"/>
</GridPane.margin> </GridPane.margin>
<columns> <columns>
<TableColumn text="Trade ID" fx:id="tradeIdColumn" minWidth="100" sortable="false"/> <TableColumn text="Trade ID" fx:id="idColumn" minWidth="100" sortable="false">
<TableColumn text="Date" fx:id="dateColumn" minWidth="130"/> <cellValueFactory>
<TableColumn text="Trade amount in BTC" fx:id="amountColumn" minWidth="130" sortable="false"/> <PropertyValueFactory property="id"/>
<TableColumn text="Price" fx:id="priceColumn" minWidth="100" sortable="false"/> </cellValueFactory>
<TableColumn text="Trade amount in EUR" fx:id="volumeColumn" minWidth="130" sortable="false"/> </TableColumn>
<TableColumn text="Date" fx:id="dateColumn" minWidth="130">
<cellValueFactory>
<PropertyValueFactory property="date"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Trade amount in BTC" fx:id="tradeAmountColumn" minWidth="130" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="tradeAmount"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Price" fx:id="priceColumn" minWidth="100" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="price"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Trade amount in EUR" fx:id="tradeVolumeColumn" minWidth="130" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="tradeVolume"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="80" sortable="false"/> <TableColumn text="Trade type" fx:id="directionColumn" minWidth="80" sortable="false"/>
</columns> </columns>
</TableView> </TableView>

View file

@ -31,9 +31,13 @@ import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId; import io.bitsquare.gui.main.help.HelpId;
import io.bitsquare.locale.BSResources; import io.bitsquare.locale.BSResources;
import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.Fiat;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.ResourceBundle; import java.util.ResourceBundle;
@ -45,8 +49,10 @@ import javafx.beans.value.ChangeListener;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.control.cell.*;
import javafx.scene.layout.*; import javafx.scene.layout.*;
import javafx.util.Callback; import javafx.util.Callback;
import javafx.util.StringConverter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -78,8 +84,13 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
@FXML Button confirmPaymentReceiptButton, paymentsButton, withdrawButton; @FXML Button confirmPaymentReceiptButton, paymentsButton, withdrawButton;
@FXML TextFieldWithCopyIcon fiatAmountTextField, holderNameTextField, secondaryIdTextField, primaryIdTextField; @FXML TextFieldWithCopyIcon fiatAmountTextField, holderNameTextField, secondaryIdTextField, primaryIdTextField;
@FXML TableView<PendingTradesListItem> table; @FXML TableView<PendingTradesListItem> table;
@FXML TableColumn<PendingTradesListItem, PendingTradesListItem> priceColumn, amountColumn, volumeColumn,
directionColumn, dateColumn, tradeIdColumn; @FXML TableColumn<PendingTradesListItem, Fiat> priceColumn;
@FXML TableColumn<PendingTradesListItem, Fiat> tradeVolumeColumn;
@FXML TableColumn<PendingTradesListItem, PendingTradesListItem> directionColumn;
@FXML TableColumn<PendingTradesListItem, String> idColumn;
@FXML TableColumn<PendingTradesListItem, Date> dateColumn;
@FXML TableColumn<PendingTradesListItem, Coin> tradeAmountColumn;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -547,119 +558,79 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
private void setTradeIdColumnCellFactory() { private void setTradeIdColumnCellFactory() {
tradeIdColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper<>(offerListItem.getValue())); idColumn.setCellFactory(TextFieldTableCell.<PendingTradesListItem, String>forTableColumn(
tradeIdColumn.setCellFactory( new StringConverter<String>() {
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>, @Override
TableCell<PendingTradesListItem, PendingTradesListItem>>() { public String toString(String value) {
return presentationModel.formatTradeId(value);
}
@Override @Override
public TableCell<PendingTradesListItem, PendingTradesListItem> call public String fromString(String string) {
(TableColumn<PendingTradesListItem, return null;
PendingTradesListItem> column) {
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
private Hyperlink hyperlink;
@Override
public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
hyperlink = new Hyperlink(presentationModel.getTradeId(item));
hyperlink.setId("id-link");
Tooltip.install(hyperlink, new Tooltip(presentationModel.getTradeId(item)));
hyperlink.setOnAction(event -> openOfferDetails(item));
setGraphic(hyperlink);
}
else {
setGraphic(null);
setId(null);
}
}
};
} }
}); }));
} }
private void setDateColumnCellFactory() { private void setDateColumnCellFactory() {
dateColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); dateColumn.setCellFactory(TextFieldTableCell.<PendingTradesListItem, Date>forTableColumn(
dateColumn.setCellFactory( new StringConverter<Date>() {
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>, TableCell<PendingTradesListItem,
PendingTradesListItem>>() {
@Override @Override
public TableCell<PendingTradesListItem, PendingTradesListItem> call( public String toString(Date value) {
TableColumn<PendingTradesListItem, PendingTradesListItem> column) { return presentationModel.formatDate(value);
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
@Override
public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null)
setText(presentationModel.getDate(item));
else
setText("");
}
};
} }
});
@Override
public Date fromString(String string) {
return null;
}
}));
} }
private void setAmountColumnCellFactory() { private void setAmountColumnCellFactory() {
amountColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); tradeAmountColumn.setCellFactory(TextFieldTableCell.<PendingTradesListItem, Coin>forTableColumn(
amountColumn.setCellFactory( new StringConverter<Coin>() {
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>, TableCell<PendingTradesListItem,
PendingTradesListItem>>() {
@Override @Override
public TableCell<PendingTradesListItem, PendingTradesListItem> call( public String toString(Coin value) {
TableColumn<PendingTradesListItem, PendingTradesListItem> column) { return presentationModel.formatTradeAmount(value);
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
@Override
public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty);
setText(presentationModel.getAmount(item));
}
};
} }
});
@Override
public Coin fromString(String string) {
return null;
}
}));
} }
private void setPriceColumnCellFactory() { private void setPriceColumnCellFactory() {
priceColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); priceColumn.setCellFactory(TextFieldTableCell.<PendingTradesListItem, Fiat>forTableColumn(
priceColumn.setCellFactory( new StringConverter<Fiat>() {
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>, TableCell<PendingTradesListItem,
PendingTradesListItem>>() {
@Override @Override
public TableCell<PendingTradesListItem, PendingTradesListItem> call( public String toString(Fiat value) {
TableColumn<PendingTradesListItem, PendingTradesListItem> column) { return presentationModel.formatPrice(value);
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
@Override
public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty);
setText(presentationModel.getPrice(item));
}
};
} }
});
@Override
public Fiat fromString(String string) {
return null;
}
}));
} }
private void setVolumeColumnCellFactory() { private void setVolumeColumnCellFactory() {
volumeColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); tradeVolumeColumn.setCellFactory(TextFieldTableCell.<PendingTradesListItem, Fiat>forTableColumn(
volumeColumn.setCellFactory( new StringConverter<Fiat>() {
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>, TableCell<PendingTradesListItem,
PendingTradesListItem>>() {
@Override @Override
public TableCell<PendingTradesListItem, PendingTradesListItem> call( public String toString(Fiat value) {
TableColumn<PendingTradesListItem, PendingTradesListItem> column) { return presentationModel.formatTradeVolume(value);
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
@Override
public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null)
setText(presentationModel.getVolume(item));
else
setText("");
}
};
} }
});
@Override
public Fiat fromString(String string) {
return null;
}
}));
} }
private void setDirectionColumnCellFactory() { private void setDirectionColumnCellFactory() {
@ -674,12 +645,14 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
@Override @Override
public void updateItem(final PendingTradesListItem item, boolean empty) { public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty); super.updateItem(item, empty);
setText(presentationModel.getDirectionLabel(item)); if (item != null && !empty)
setText(presentationModel.evaluateDirection(item));
else
setText(null);
} }
}; };
} }
}); });
} }
} }

View file

@ -27,13 +27,9 @@ import java.io.Serializable;
import java.util.Date; import java.util.Date;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
//TODO flatten down?
public class Trade implements Serializable { public class Trade implements Serializable {
private static final long serialVersionUID = -8275323072940974077L; private static final long serialVersionUID = -8275323072940974077L;
@ -52,28 +48,28 @@ public class Trade implements Serializable {
COMPLETED COMPLETED
} }
private final Offer offer; private final Offer offer;
private final Date date; private final Date date;
private String takeOfferFeeTxID; private String takeOfferFeeTxID;
private Coin tradeAmount;
private Contract contract; private Contract contract;
private String contractAsJson; private String contractAsJson;
private String takerSignature; private String takerSignature;
private Transaction depositTx; private Transaction depositTx;
private Transaction payoutTx; private Transaction payoutTx;
private Coin tradeAmount;
private State state; private State state;
private Throwable fault; private Throwable fault;
// For changing values we use properties to get binding support in the UI (table)
// When serialized those transient properties are not instantiated, so we instantiate them in the getters at first // When serialized those transient properties are not instantiated, so we instantiate them in the getters at first
// access. Only use the accessor not the private field. // access. Only use the accessor not the private field.
// TODO use ObjectProperties instead of BooleanProperty transient private ObjectProperty<Coin> _tradeAmount;
transient private BooleanProperty _payoutTxChanged; transient private ObjectProperty<Fiat> _tradeVolume;
transient private BooleanProperty _contractChanged;
transient private ObjectProperty<Transaction> _depositTx;
transient private ObjectProperty<State> _state; transient private ObjectProperty<State> _state;
transient private ObjectProperty<Throwable> _fault; transient private ObjectProperty<Throwable> _fault;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Constructor // Constructor
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -81,6 +77,7 @@ public class Trade implements Serializable {
public Trade(Offer offer) { public Trade(Offer offer) {
this.offer = offer; this.offer = offer;
date = new Date(); date = new Date();
state = State.OPEN; state = State.OPEN;
} }
@ -103,6 +100,8 @@ public class Trade implements Serializable {
public void setTradeAmount(Coin tradeAmount) { public void setTradeAmount(Coin tradeAmount) {
this.tradeAmount = tradeAmount; this.tradeAmount = tradeAmount;
tradeAmountProperty().set(tradeAmount);
tradeVolumeProperty().set(getTradeVolume());
} }
public Contract getContract() { public Contract getContract() {
@ -115,17 +114,14 @@ public class Trade implements Serializable {
public void setContract(Contract contract) { public void setContract(Contract contract) {
this.contract = contract; this.contract = contract;
contractChangedProperty().set(!contractChangedProperty().get());
} }
public void setDepositTx(Transaction tx) { public void setDepositTx(Transaction tx) {
this.depositTx = tx; this.depositTx = tx;
depositTxProperty().set(tx);
} }
public void setPayoutTx(Transaction tx) { public void setPayoutTx(Transaction tx) {
this.payoutTx = tx; this.payoutTx = tx;
payoutTxChangedProperty().set(!payoutTxChangedProperty().get());
} }
public void setState(State state) { public void setState(State state) {
@ -192,25 +188,18 @@ public class Trade implements Serializable {
} }
// When serialized those transient properties are not instantiated, so we need to instantiate them at first access // When serialized those transient properties are not instantiated, so we need to instantiate them at first access
public ObjectProperty<Transaction> depositTxProperty() { public ObjectProperty<Coin> tradeAmountProperty() {
if (_depositTx == null) if (_tradeAmount == null)
_depositTx = new SimpleObjectProperty<>(depositTx); _tradeAmount = new SimpleObjectProperty<>();
return _depositTx; return _tradeAmount;
} }
public BooleanProperty contractChangedProperty() { public ObjectProperty<Fiat> tradeVolumeProperty() {
if (_contractChanged == null) if (_tradeVolume == null)
_contractChanged = new SimpleBooleanProperty(); _tradeVolume = new SimpleObjectProperty<>();
return _contractChanged; return _tradeVolume;
}
public BooleanProperty payoutTxChangedProperty() {
if (_payoutTxChanged == null)
_payoutTxChanged = new SimpleBooleanProperty();
return _payoutTxChanged;
} }
public ObjectProperty<State> stateProperty() { public ObjectProperty<State> stateProperty() {
@ -225,6 +214,4 @@ public class Trade implements Serializable {
_fault = new SimpleObjectProperty<>(fault); _fault = new SimpleObjectProperty<>(fault);
return _fault; return _fault;
} }
} }