Add visual icon for duplicate offer functionality

This commit is contained in:
Christoph Atteneder 2021-12-03 12:02:10 +01:00
parent 7d7a9ecfc8
commit f41203858c
No known key found for this signature in database
GPG Key ID: CD5DC1C529CDFD3B
5 changed files with 116 additions and 32 deletions

View File

@ -97,6 +97,7 @@ shared.BTCMinMax=BTC (min - max)
shared.removeOffer=Remove offer shared.removeOffer=Remove offer
shared.dontRemoveOffer=Don't remove offer shared.dontRemoveOffer=Don't remove offer
shared.editOffer=Edit offer shared.editOffer=Edit offer
shared.duplicateOffer=Duplicate offer
shared.openLargeQRWindow=Open large QR code window shared.openLargeQRWindow=Open large QR code window
shared.tradingAccount=Trading account shared.tradingAccount=Trading account
shared.faq=Visit FAQ page shared.faq=Visit FAQ page

View File

@ -55,6 +55,7 @@
<TableColumn fx:id="sellerSecurityDepositColumn" visible="false" minWidth="75"/> <TableColumn fx:id="sellerSecurityDepositColumn" visible="false" minWidth="75"/>
<TableColumn fx:id="directionColumn" minWidth="70"/> <TableColumn fx:id="directionColumn" minWidth="70"/>
<TableColumn fx:id="stateColumn" minWidth="80"/> <TableColumn fx:id="stateColumn" minWidth="80"/>
<TableColumn fx:id="duplicateColumn" minWidth="30" maxWidth="30" sortable="false"/>
<TableColumn fx:id="avatarColumn" minWidth="40" maxWidth="40"/> <TableColumn fx:id="avatarColumn" minWidth="40" maxWidth="40"/>
</columns> </columns>
</TableView> </TableView>

View File

@ -60,11 +60,14 @@ import com.googlecode.jcsv.writer.CSVEntryConverter;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ContextMenu; import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.MenuItem; import javafx.scene.control.MenuItem;
@ -85,6 +88,8 @@ import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.collections.transformation.FilteredList; import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList; import javafx.collections.transformation.SortedList;
@ -94,6 +99,8 @@ import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.function.Function; import java.util.function.Function;
import static bisq.desktop.util.FormBuilder.getRegularIconButton;
@FxmlView @FxmlView
public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTradesViewModel> { public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTradesViewModel> {
private final boolean useDevPrivilegeKeys; private final boolean useDevPrivilegeKeys;
@ -132,7 +139,8 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
@FXML @FXML
TableColumn<Tradable, Tradable> priceColumn, deviationColumn, amountColumn, volumeColumn, TableColumn<Tradable, Tradable> priceColumn, deviationColumn, amountColumn, volumeColumn,
txFeeColumn, tradeFeeColumn, buyerSecurityDepositColumn, sellerSecurityDepositColumn, txFeeColumn, tradeFeeColumn, buyerSecurityDepositColumn, sellerSecurityDepositColumn,
marketColumn, directionColumn, dateColumn, tradeIdColumn, stateColumn, avatarColumn; marketColumn, directionColumn, dateColumn, tradeIdColumn, stateColumn,
duplicateColumn, avatarColumn;
@FXML @FXML
HBox searchBox; HBox searchBox;
@FXML @FXML
@ -198,6 +206,7 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
dateColumn.setGraphic(new AutoTooltipLabel(ColumnNames.DATE.toString())); dateColumn.setGraphic(new AutoTooltipLabel(ColumnNames.DATE.toString()));
tradeIdColumn.setGraphic(new AutoTooltipLabel(ColumnNames.TRADE_ID.toString())); tradeIdColumn.setGraphic(new AutoTooltipLabel(ColumnNames.TRADE_ID.toString()));
stateColumn.setGraphic(new AutoTooltipLabel(ColumnNames.STATUS.toString())); stateColumn.setGraphic(new AutoTooltipLabel(ColumnNames.STATUS.toString()));
duplicateColumn.setGraphic(new AutoTooltipLabel(""));
avatarColumn.setText(""); avatarColumn.setText("");
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
@ -216,10 +225,11 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
setDateColumnCellFactory(); setDateColumnCellFactory();
setMarketColumnCellFactory(); setMarketColumnCellFactory();
setStateColumnCellFactory(); setStateColumnCellFactory();
setDuplicateColumnCellFactory();
setAvatarColumnCellFactory(); setAvatarColumnCellFactory();
tradeIdColumn.setComparator(Comparator.comparing(o -> o.getId())); tradeIdColumn.setComparator(Comparator.comparing(Tradable::getId));
dateColumn.setComparator(Comparator.comparing(o -> o.getDate())); dateColumn.setComparator(Comparator.comparing(Tradable::getDate));
directionColumn.setComparator(Comparator.comparing(o -> o.getOffer().getDirection())); directionColumn.setComparator(Comparator.comparing(o -> o.getOffer().getDirection()));
marketColumn.setComparator(Comparator.comparing(model::getMarketLabel)); marketColumn.setComparator(Comparator.comparing(model::getMarketLabel));
priceColumn.setComparator(Comparator.comparing(model::getPrice, Comparator.nullsFirst(Comparator.naturalOrder()))); priceColumn.setComparator(Comparator.comparing(model::getPrice, Comparator.nullsFirst(Comparator.naturalOrder())));
@ -229,7 +239,7 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
volumeColumn.setComparator(nullsFirstComparingAsTrade(TradeModel::getVolume)); volumeColumn.setComparator(nullsFirstComparingAsTrade(TradeModel::getVolume));
amountColumn.setComparator(Comparator.comparing(model::getAmount, Comparator.nullsFirst(Comparator.naturalOrder()))); amountColumn.setComparator(Comparator.comparing(model::getAmount, Comparator.nullsFirst(Comparator.naturalOrder())));
avatarColumn.setComparator(Comparator.comparing( avatarColumn.setComparator(Comparator.comparing(
o -> model.dataModel.getNumPastTrades(o), model.dataModel::getNumPastTrades,
Comparator.nullsFirst(Comparator.naturalOrder()) Comparator.nullsFirst(Comparator.naturalOrder())
)); ));
txFeeColumn.setComparator(nullsFirstComparing(o -> txFeeColumn.setComparator(nullsFirstComparing(o ->
@ -263,18 +273,7 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
TableRow<Tradable> row = new TableRow<>(); TableRow<Tradable> row = new TableRow<>();
ContextMenu rowMenu = new ContextMenu(); ContextMenu rowMenu = new ContextMenu();
MenuItem editItem = new MenuItem(Res.get("portfolio.context.offerLikeThis")); MenuItem editItem = new MenuItem(Res.get("portfolio.context.offerLikeThis"));
editItem.setOnAction((event) -> { editItem.setOnAction((ActionEvent event) -> onDuplicateOffer(row.getItem().getOffer()));
try {
OfferPayloadBase offerPayloadBase = row.getItem().getOffer().getOfferPayloadBase();
if (offerPayloadBase.getPubKeyRing().equals(keyRing.getPubKeyRing())) {
navigation.navigateToWithData(offerPayloadBase, MainView.class, PortfolioView.class, DuplicateOfferView.class);
} else {
new Popup().warning(Res.get("portfolio.context.notYourOffer")).show();
}
} catch (NullPointerException e) {
log.warn("Unable to get offerPayload - {}", e.toString());
}
});
rowMenu.getItems().add(editItem); rowMenu.getItems().add(editItem);
row.contextMenuProperty().bind( row.contextMenuProperty().bind(
Bindings.when(Bindings.isNotNull(row.itemProperty())) Bindings.when(Bindings.isNotNull(row.itemProperty()))
@ -579,6 +578,40 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
}); });
} }
private void setDuplicateColumnCellFactory() {
duplicateColumn.getStyleClass().add("avatar-column");
duplicateColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper<>(offerListItem.getValue()));
duplicateColumn.setCellFactory(
new Callback<>() {
@Override
public TableCell<Tradable, Tradable> call(TableColumn<Tradable, Tradable> column) {
return new TableCell<>() {
Button button;
@Override
public void updateItem(final Tradable item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
if (button == null) {
button = getRegularIconButton(MaterialDesignIcon.CONTENT_COPY);
button.setTooltip(new Tooltip(Res.get("shared.duplicateOffer")));
setGraphic(button);
}
button.setOnAction(event -> onDuplicateOffer(item.getOffer()));
} else {
setGraphic(null);
if (button != null) {
button.setOnAction(null);
button = null;
}
}
}
};
}
});
}
@SuppressWarnings("UnusedReturnValue") @SuppressWarnings("UnusedReturnValue")
private TableColumn<Tradable, Tradable> setAvatarColumnCellFactory() { private TableColumn<Tradable, Tradable> setAvatarColumnCellFactory() {
avatarColumn.getStyleClass().addAll("last-column", "avatar-column"); avatarColumn.getStyleClass().addAll("last-column", "avatar-column");
@ -593,7 +626,7 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
public void updateItem(final Tradable item, boolean empty) { public void updateItem(final Tradable item, boolean empty) {
super.updateItem(item, empty); super.updateItem(item, empty);
if (item != null && !empty && item instanceof TradeModel) { if (!empty && item instanceof TradeModel) {
TradeModel tradeModel = (TradeModel) item; TradeModel tradeModel = (TradeModel) item;
int numPastTrades = model.dataModel.getNumPastTrades(tradeModel); int numPastTrades = model.dataModel.getNumPastTrades(tradeModel);
NodeAddress tradingPeerNodeAddress = tradeModel.getTradingPeerNodeAddress(); NodeAddress tradingPeerNodeAddress = tradeModel.getTradingPeerNodeAddress();
@ -783,6 +816,19 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
}); });
} }
private void onDuplicateOffer(Offer offer) {
try {
OfferPayloadBase offerPayloadBase = offer.getOfferPayloadBase();
if (offerPayloadBase.getPubKeyRing().equals(keyRing.getPubKeyRing())) {
navigation.navigateToWithData(offerPayloadBase, MainView.class, PortfolioView.class, DuplicateOfferView.class);
} else {
new Popup().warning(Res.get("portfolio.context.notYourOffer")).show();
}
} catch (NullPointerException e) {
log.warn("Unable to get offerPayload - {}", e.toString());
}
}
private Tradable getDummyTradable() { private Tradable getDummyTradable() {
return new Tradable() { return new Tradable() {
@Override @Override

View File

@ -55,6 +55,7 @@
<TableColumn fx:id="deactivateItemColumn" minWidth="60" maxWidth="60" sortable="false"/> <TableColumn fx:id="deactivateItemColumn" minWidth="60" maxWidth="60" sortable="false"/>
<TableColumn fx:id="editItemColumn" minWidth="30" maxWidth="30" sortable="false"/> <TableColumn fx:id="editItemColumn" minWidth="30" maxWidth="30" sortable="false"/>
<TableColumn fx:id="triggerIconColumn" minWidth="30" maxWidth="30" sortable="false"/> <TableColumn fx:id="triggerIconColumn" minWidth="30" maxWidth="30" sortable="false"/>
<TableColumn fx:id="duplicateItemColumn" minWidth="30" maxWidth="30" sortable="false"/>
<TableColumn fx:id="removeItemColumn" minWidth="30" maxWidth="30" sortable="false"/> <TableColumn fx:id="removeItemColumn" minWidth="30" maxWidth="30" sortable="false"/>
</columns> </columns>
</TableView> </TableView>

View File

@ -98,7 +98,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
@FXML @FXML
TableColumn<OpenOfferListItem, OpenOfferListItem> priceColumn, deviationColumn, amountColumn, volumeColumn, TableColumn<OpenOfferListItem, OpenOfferListItem> priceColumn, deviationColumn, amountColumn, volumeColumn,
marketColumn, directionColumn, dateColumn, offerIdColumn, deactivateItemColumn, marketColumn, directionColumn, dateColumn, offerIdColumn, deactivateItemColumn,
removeItemColumn, editItemColumn, triggerPriceColumn, triggerIconColumn, paymentMethodColumn; removeItemColumn, editItemColumn, triggerPriceColumn, triggerIconColumn, paymentMethodColumn, duplicateItemColumn;
@FXML @FXML
HBox searchBox; HBox searchBox;
@FXML @FXML
@ -152,6 +152,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
triggerPriceColumn.setGraphic(new AutoTooltipLabel(Res.get("openOffer.header.triggerPrice"))); triggerPriceColumn.setGraphic(new AutoTooltipLabel(Res.get("openOffer.header.triggerPrice")));
deactivateItemColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.enabled"))); deactivateItemColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.enabled")));
editItemColumn.setGraphic(new AutoTooltipLabel("")); editItemColumn.setGraphic(new AutoTooltipLabel(""));
duplicateItemColumn.setGraphic(new AutoTooltipLabel(""));
removeItemColumn.setGraphic(new AutoTooltipLabel("")); removeItemColumn.setGraphic(new AutoTooltipLabel(""));
setOfferIdColumnCellFactory(); setOfferIdColumnCellFactory();
@ -167,6 +168,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
setEditColumnCellFactory(); setEditColumnCellFactory();
setTriggerIconColumnCellFactory(); setTriggerIconColumnCellFactory();
setTriggerPriceColumnCellFactory(); setTriggerPriceColumnCellFactory();
setDuplicateColumnCellFactory();
setRemoveColumnCellFactory(); setRemoveColumnCellFactory();
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
@ -192,15 +194,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
final TableRow<OpenOfferListItem> row = new TableRow<>(); final TableRow<OpenOfferListItem> row = new TableRow<>();
final ContextMenu rowMenu = new ContextMenu(); final ContextMenu rowMenu = new ContextMenu();
MenuItem editItem = new MenuItem(Res.get("portfolio.context.offerLikeThis")); MenuItem editItem = new MenuItem(Res.get("portfolio.context.offerLikeThis"));
editItem.setOnAction((event) -> { editItem.setOnAction((event) -> onDuplicateOffer(row.getItem().getOffer()));
try {
OfferPayloadBase offerPayloadBase = row.getItem().getOffer().getOfferPayloadBase();
navigation.navigateToWithData(offerPayloadBase, MainView.class, PortfolioView.class,
DuplicateOfferView.class);
} catch (NullPointerException e) {
log.warn("Unable to get offerPayload - {}", e.toString());
}
});
rowMenu.getItems().add(editItem); rowMenu.getItems().add(editItem);
row.contextMenuProperty().bind( row.contextMenuProperty().bind(
Bindings.when(Bindings.isNotNull(row.itemProperty())) Bindings.when(Bindings.isNotNull(row.itemProperty()))
@ -356,11 +350,8 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
if (model.getDirectionLabel(item).contains(filterString)) { if (model.getDirectionLabel(item).contains(filterString)) {
return true; return true;
} }
if (offer.getOfferFeePaymentTxId() != null && return offer.getOfferFeePaymentTxId() != null &&
offer.getOfferFeePaymentTxId().contains(filterString)) { offer.getOfferFeePaymentTxId().contains(filterString);
return true;
}
return false;
}); });
} }
@ -440,6 +431,16 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
} }
} }
private void onDuplicateOffer(Offer offer) {
try {
OfferPayloadBase offerPayloadBase = offer.getOfferPayloadBase();
navigation.navigateToWithData(offerPayloadBase, MainView.class, PortfolioView.class,
DuplicateOfferView.class);
} catch (NullPointerException e) {
log.warn("Unable to get offerPayload - {}", e.toString());
}
}
private void setOfferIdColumnCellFactory() { private void setOfferIdColumnCellFactory() {
offerIdColumn.setCellValueFactory((openOfferListItem) -> new ReadOnlyObjectWrapper<>(openOfferListItem.getValue())); offerIdColumn.setCellValueFactory((openOfferListItem) -> new ReadOnlyObjectWrapper<>(openOfferListItem.getValue()));
offerIdColumn.getStyleClass().addAll("number-column", "first-column"); offerIdColumn.getStyleClass().addAll("number-column", "first-column");
@ -787,6 +788,40 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
}); });
} }
private void setDuplicateColumnCellFactory() {
duplicateItemColumn.getStyleClass().add("avatar-column");
duplicateItemColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper<>(offerListItem.getValue()));
duplicateItemColumn.setCellFactory(
new Callback<>() {
@Override
public TableCell<OpenOfferListItem, OpenOfferListItem> call(TableColumn<OpenOfferListItem, OpenOfferListItem> column) {
return new TableCell<>() {
Button button;
@Override
public void updateItem(final OpenOfferListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
if (button == null) {
button = getRegularIconButton(MaterialDesignIcon.CONTENT_COPY);
button.setTooltip(new Tooltip(Res.get("shared.duplicateOffer")));
setGraphic(button);
}
button.setOnAction(event -> onDuplicateOffer(item.getOffer()));
} else {
setGraphic(null);
if (button != null) {
button.setOnAction(null);
button = null;
}
}
}
};
}
});
}
private void setTriggerIconColumnCellFactory() { private void setTriggerIconColumnCellFactory() {
triggerIconColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper<>(offerListItem.getValue())); triggerIconColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper<>(offerListItem.getValue()));
triggerIconColumn.setCellFactory( triggerIconColumn.setCellFactory(