mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 18:03:12 +01:00
Fix intermittent blank price cells in offer book view
Replace faulty cell update logic, which uses a ChangeListener<Scene>, added in July 2017 (#73f21399) to keep the price column in the offer book table up to date, as it appears to occasionally result in blank cells. Also it seems only the prices, not the volumes, were being kept in sync with the market price feed. Make the price and volume cells stateless and keep them in sync with the market feed by adding it as a dependency of each OfferBookListItem Observable generated by the cell value factory, instead of directly attaching listeners to it. In this way, TableCell::updateItem will be called by the framework whenever the price/volume needs updating. (This does have the disadvantage that if the price feed is unavailable, causing Offer::getPrice to return null, then the cells will reflect that immediately instead of showing any old, stale values, but that is necessary for the UI to behave consistently anyway.)
This commit is contained in:
parent
894d2be5db
commit
23688db18c
@ -71,7 +71,6 @@ import javax.inject.Named;
|
||||
import de.jensd.fx.glyphs.GlyphIcons;
|
||||
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;
|
||||
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.canvas.Canvas;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
@ -731,6 +730,12 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
return column;
|
||||
}
|
||||
|
||||
private ObservableValue<OfferBookListItem> asPriceDependentObservable(OfferBookListItem item) {
|
||||
return item.getOffer().isUseMarketBasedPrice()
|
||||
? EasyBind.map(model.priceFeedService.updateCounterProperty(), n -> item)
|
||||
: new ReadOnlyObjectWrapper<>(item);
|
||||
}
|
||||
|
||||
private AutoTooltipTableColumn<OfferBookListItem, OfferBookListItem> getPriceColumn() {
|
||||
AutoTooltipTableColumn<OfferBookListItem, OfferBookListItem> column = new AutoTooltipTableColumn<>("") {
|
||||
{
|
||||
@ -738,59 +743,20 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
}
|
||||
};
|
||||
column.getStyleClass().add("number-column");
|
||||
column.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||
column.setCellValueFactory(offer -> asPriceDependentObservable(offer.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<OfferBookListItem, OfferBookListItem> call(
|
||||
TableColumn<OfferBookListItem, OfferBookListItem> column) {
|
||||
return new TableCell<>() {
|
||||
private OfferBookListItem offerBookListItem;
|
||||
private ChangeListener<Number> priceChangedListener;
|
||||
ChangeListener<Scene> sceneChangeListener;
|
||||
|
||||
@Override
|
||||
public void updateItem(final OfferBookListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
if (getTableView().getScene() != null && sceneChangeListener == null) {
|
||||
sceneChangeListener = (observable, oldValue, newValue) -> {
|
||||
if (newValue == null) {
|
||||
if (priceChangedListener != null) {
|
||||
model.priceFeedService.updateCounterProperty().removeListener(priceChangedListener);
|
||||
priceChangedListener = null;
|
||||
}
|
||||
offerBookListItem = null;
|
||||
setGraphic(null);
|
||||
getTableView().sceneProperty().removeListener(sceneChangeListener);
|
||||
sceneChangeListener = null;
|
||||
}
|
||||
};
|
||||
getTableView().sceneProperty().addListener(sceneChangeListener);
|
||||
}
|
||||
|
||||
this.offerBookListItem = item;
|
||||
|
||||
if (priceChangedListener == null) {
|
||||
priceChangedListener = (observable, oldValue, newValue) -> {
|
||||
if (offerBookListItem != null && offerBookListItem.getOffer().getPrice() != null) {
|
||||
setGraphic(getPriceLabel(model.getPrice(offerBookListItem), offerBookListItem));
|
||||
}
|
||||
};
|
||||
model.priceFeedService.updateCounterProperty().addListener(priceChangedListener);
|
||||
}
|
||||
setGraphic(getPriceLabel(item.getOffer().getPrice() == null ? Res.get("shared.na") : model.getPrice(item), item));
|
||||
setGraphic(getPriceLabel(model.getPrice(item), item));
|
||||
} else {
|
||||
if (priceChangedListener != null) {
|
||||
model.priceFeedService.updateCounterProperty().removeListener(priceChangedListener);
|
||||
priceChangedListener = null;
|
||||
}
|
||||
if (sceneChangeListener != null) {
|
||||
getTableView().sceneProperty().removeListener(sceneChangeListener);
|
||||
sceneChangeListener = null;
|
||||
}
|
||||
this.offerBookListItem = null;
|
||||
setGraphic(null);
|
||||
}
|
||||
}
|
||||
@ -845,35 +811,19 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
}
|
||||
};
|
||||
column.getStyleClass().add("number-column");
|
||||
column.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||
column.setCellValueFactory(offer -> asPriceDependentObservable(offer.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<OfferBookListItem, OfferBookListItem> call(
|
||||
TableColumn<OfferBookListItem, OfferBookListItem> column) {
|
||||
return new TableCell<>() {
|
||||
private OfferBookListItem offerBookListItem;
|
||||
final ChangeListener<Number> listener = new ChangeListener<>() {
|
||||
@Override
|
||||
public void changed(ObservableValue<? extends Number> observable,
|
||||
Number oldValue,
|
||||
Number newValue) {
|
||||
if (offerBookListItem != null && offerBookListItem.getOffer().getVolume() != null) {
|
||||
setText("");
|
||||
setGraphic(new ColoredDecimalPlacesWithZerosText(model.getVolume(offerBookListItem),
|
||||
model.getNumberOfDecimalsForVolume(offerBookListItem)));
|
||||
model.priceFeedService.updateCounterProperty().removeListener(listener);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void updateItem(final OfferBookListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
if (item.getOffer().getPrice() == null) {
|
||||
this.offerBookListItem = item;
|
||||
model.priceFeedService.updateCounterProperty().addListener(listener);
|
||||
setText(Res.get("shared.na"));
|
||||
setGraphic(null);
|
||||
} else {
|
||||
@ -882,8 +832,6 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
model.getNumberOfDecimalsForVolume(item)));
|
||||
}
|
||||
} else {
|
||||
model.priceFeedService.updateCounterProperty().removeListener(listener);
|
||||
this.offerBookListItem = null;
|
||||
setText("");
|
||||
setGraphic(null);
|
||||
}
|
||||
@ -1015,7 +963,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
public void updateItem(final OfferBookListItem newItem, boolean empty) {
|
||||
super.updateItem(newItem, empty);
|
||||
|
||||
TableRow tableRow = getTableRow();
|
||||
TableRow<OfferBookListItem> tableRow = getTableRow();
|
||||
if (newItem != null && !empty) {
|
||||
final Offer offer = newItem.getOffer();
|
||||
boolean myOffer = model.isMyOffer(offer);
|
||||
|
Loading…
Reference in New Issue
Block a user