Update Signed Offers view in legacy UI

This commit is contained in:
napoly 2023-03-17 18:43:33 +01:00 committed by woodser
parent 3b8f19c4ce
commit 4bef95172c
9 changed files with 525 additions and 445 deletions

View File

@ -14,11 +14,11 @@ jobs:
fail-fast: false fail-fast: false
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
with: with:
lfs: true lfs: true
- name: Set up JDK 11 - name: Set up JDK 11
uses: actions/setup-java@v2 uses: actions/setup-java@v3
with: with:
java-version: '11' java-version: '11'
distribution: 'adopt' distribution: 'adopt'
@ -26,11 +26,11 @@ jobs:
- name: Build with Gradle - name: Build with Gradle
run: ./gradlew build --stacktrace --scan run: ./gradlew build --stacktrace --scan
- name: cache nodes dependencies - name: cache nodes dependencies
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: cached-localnet name: cached-localnet
path: .localnet path: .localnet
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v3
if: failure() if: failure()
with: with:
name: gradlew-report name: gradlew-report

View File

@ -90,6 +90,7 @@ shared.usage=Usage
shared.state=Status shared.state=Status
shared.tradeId=Trade ID shared.tradeId=Trade ID
shared.offerId=Offer ID shared.offerId=Offer ID
shared.traderId=Trader ID
shared.bankName=Bank name shared.bankName=Bank name
shared.acceptedBanks=Accepted banks shared.acceptedBanks=Accepted banks
shared.amountMinMax=Amount (min - max) shared.amountMinMax=Amount (min - max)

View File

@ -0,0 +1,48 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package haveno.desktop.main.offer.signedoffer;
import org.apache.commons.lang3.StringUtils;
import lombok.Getter;
import haveno.core.offer.SignedOffer;
import haveno.desktop.util.filtering.FilterableListItem;
class SignedOfferListItem implements FilterableListItem {
@Getter
private final SignedOffer signedOffer;
SignedOfferListItem(SignedOffer signedOffer) {
this.signedOffer = signedOffer;
}
@Override
public boolean match(String filterString) {
if (filterString.isEmpty()) {
return true;
}
if (StringUtils.containsIgnoreCase(String.valueOf(signedOffer.getTraderId()), filterString)) {
return true;
}
if (StringUtils.containsIgnoreCase(String.valueOf(signedOffer.getOfferId()), filterString)) {
return true;
}
return StringUtils.containsIgnoreCase(String.valueOf(signedOffer.getReserveTxKeyImages()), filterString);
}
}

View File

@ -17,17 +17,19 @@
~ along with Haveno. If not, see <http://www.gnu.org/licenses/>. ~ along with Haveno. If not, see <http://www.gnu.org/licenses/>.
--> -->
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableView?> <?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?> <?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<VBox fx:id="root" fx:controller="haveno.desktop.main.support.dispute.agent.SignedOfferView" <?import javafx.geometry.Insets?>
<?import haveno.desktop.components.list.FilterBox?>
<VBox fx:id="root" fx:controller="haveno.desktop.main.offer.signedoffer.SignedOfferView"
spacing="10" xmlns:fx="http://javafx.com/fxml"> spacing="10" xmlns:fx="http://javafx.com/fxml">
<padding> <padding>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0"/> <Insets bottom="15.0" left="15.0" right="15.0" top="15.0"/>
</padding> </padding>
<FilterBox fx:id="filterBox" />
<TableView fx:id="tableView" VBox.vgrow="ALWAYS" /> <TableView fx:id="tableView" VBox.vgrow="ALWAYS" />
<HBox spacing="10"> <HBox spacing="10">
<Label fx:id="numItems"/> <Label fx:id="numItems"/>

View File

@ -0,0 +1,358 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package haveno.desktop.main.offer.signedoffer;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.geometry.Insets;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.util.Callback;
import javafx.util.Duration;
import java.util.Comparator;
import java.util.Date;
import haveno.common.util.Utilities;
import haveno.core.locale.Res;
import haveno.core.offer.SignedOffer;
import haveno.core.trade.HavenoUtils;
import haveno.core.xmr.wallet.XmrWalletService;
import haveno.desktop.common.view.ActivatableViewAndModel;
import haveno.desktop.common.view.FxmlView;
import haveno.desktop.components.AutoTooltipLabel;
import haveno.desktop.components.AutoTooltipTableColumn;
import haveno.desktop.components.HyperlinkWithIcon;
import haveno.desktop.components.InputTextField;
import haveno.desktop.components.list.FilterBox;
import haveno.desktop.main.offer.OfferViewUtil;
import haveno.desktop.main.overlays.popups.Popup;
import haveno.desktop.util.DisplayUtils;
import haveno.desktop.util.GUIUtil;
@FxmlView
public class SignedOfferView extends ActivatableViewAndModel<VBox, SignedOffersViewModel> {
@FXML
FilterBox filterBox;
@FXML
protected TableView<SignedOfferListItem> tableView;
@FXML
TableColumn<SignedOfferListItem, SignedOfferListItem> dateColumn;
@FXML
TableColumn<SignedOfferListItem, SignedOfferListItem> traderIdColumn;
@FXML
TableColumn<SignedOfferListItem, SignedOfferListItem> offerIdColumn;
@FXML
TableColumn<SignedOfferListItem, SignedOfferListItem> reserveTxKeyImages;
@FXML
TableColumn<SignedOfferListItem, SignedOfferListItem> makerPenaltyFeeColumn;
@FXML
InputTextField filterTextField;
@FXML
Label numItems;
@FXML
Region footerSpacer;
private SignedOfferListItem selectedSignedOffer;
private final XmrWalletService xmrWalletService;
private ContextMenu contextMenu;
@Inject
public SignedOfferView(SignedOffersViewModel model, XmrWalletService xmrWalletService) {
super(model);
this.xmrWalletService = xmrWalletService;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Life cycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize() {
Label label = new AutoTooltipLabel(Res.get("support.filter"));
HBox.setMargin(label, new Insets(5, 0, 0, 0));
HBox.setHgrow(label, Priority.NEVER);
filterTextField = new InputTextField();
Tooltip tooltip = new Tooltip();
tooltip.setShowDelay(Duration.millis(100));
tooltip.setShowDuration(Duration.seconds(10));
filterTextField.setTooltip(tooltip);
HBox.setHgrow(filterTextField, Priority.NEVER);
filterTextField.setText("open");
setupTable();
}
@Override
protected void activate() {
FilteredList<SignedOfferListItem> filteredList = new FilteredList<>(model.getList());
SortedList<SignedOfferListItem> sortedList = new SortedList<>(filteredList);
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
tableView.setItems(sortedList);
filterBox.initialize(filteredList, tableView);
filterBox.activate();
contextMenu = new ContextMenu();
MenuItem makerPenalization = new MenuItem(
Res.get("support.contextmenu.penalize.msg", Res.get("shared.maker").toLowerCase())
);
MenuItem copyToClipboard = new MenuItem(Res.get("shared.copyToClipboard"));
contextMenu.getItems().addAll(makerPenalization, copyToClipboard);
tableView.setRowFactory(tv -> {
TableRow<SignedOfferListItem> row = new TableRow<>();
row.setOnContextMenuRequested(event -> contextMenu.show(row, event.getScreenX(), event.getScreenY()));
return row;
});
copyToClipboard.setOnAction(event -> {
selectedSignedOffer = tableView.getSelectionModel().getSelectedItem();
Utilities.copyToClipboard(selectedSignedOffer.getSignedOffer().toJson());
});
makerPenalization.setOnAction(event -> {
selectedSignedOffer = tableView.getSelectionModel().getSelectedItem();
if(selectedSignedOffer != null) {
SignedOffer signedOffer = selectedSignedOffer.getSignedOffer();
new Popup().warning(Res.get("support.prompt.signedOffer.penalty.msg",
signedOffer.getOfferId(),
HavenoUtils.formatXmr(signedOffer.getPenaltyAmount(), true),
HavenoUtils.formatXmr(signedOffer.getReserveTxMinerFee(), true),
signedOffer.getReserveTxHash(),
signedOffer.getReserveTxKeyImages())
).onAction(() -> OfferViewUtil.submitTransactionHex(xmrWalletService, tableView,
signedOffer.getReserveTxHex())).show();
} else {
new Popup().error(Res.get("support.prompt.signedOffer.error.msg")).show();
}
});
GUIUtil.requestFocus(tableView);
}
@Override
protected void deactivate() {
filterBox.deactivate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// SignedOfferView
///////////////////////////////////////////////////////////////////////////////////////////
protected void setupTable() {
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
Label placeholder = new AutoTooltipLabel(Res.get("support.noTickets"));
placeholder.setWrapText(true);
tableView.setPlaceholder(placeholder);
tableView.getSelectionModel().clearSelection();
dateColumn = getDateColumn();
tableView.getColumns().add(dateColumn);
traderIdColumn = getTraderIdColumn();
tableView.getColumns().add(traderIdColumn);
offerIdColumn = getOfferIdColumn();
tableView.getColumns().add(offerIdColumn);
makerPenaltyFeeColumn = getMakerPenaltyFeeColumn();
tableView.getColumns().add(makerPenaltyFeeColumn);
reserveTxKeyImages = getReserveTxKeyImagesColumn();
tableView.getColumns().add(reserveTxKeyImages);
traderIdColumn.setComparator(Comparator.comparing(o -> o.getSignedOffer().getTraderId()));
offerIdColumn.setComparator(Comparator.comparing(o -> o.getSignedOffer().getOfferId()));
dateColumn.setComparator(Comparator.comparing(o -> o.getSignedOffer().getTimeStamp()));
dateColumn.setSortType(TableColumn.SortType.DESCENDING);
tableView.getSortOrder().add(dateColumn);
}
private TableColumn<SignedOfferListItem, SignedOfferListItem> getDateColumn() {
TableColumn<SignedOfferListItem, SignedOfferListItem> column = new AutoTooltipTableColumn<>(Res.get("shared.date")) {
{
setMinWidth(180);
}
};
column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOfferListItem, SignedOfferListItem> call(TableColumn<SignedOfferListItem, SignedOfferListItem> column) {
return new TableCell<>() {
@Override
public void updateItem(final SignedOfferListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(DisplayUtils.formatDateTime(new Date(item.getSignedOffer().getTimeStamp())));
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SignedOfferListItem, SignedOfferListItem> getTraderIdColumn() {
TableColumn<SignedOfferListItem, SignedOfferListItem> column = new AutoTooltipTableColumn<>(Res.get("shared.traderId")) {
{
setMinWidth(110);
}
};
column.setCellValueFactory(signedOffer -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOfferListItem, SignedOfferListItem> call(TableColumn<SignedOfferListItem, SignedOfferListItem> column) {
return new TableCell<>() {
private HyperlinkWithIcon field;
@Override
public void updateItem(final SignedOfferListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
setText(String.valueOf(item.getSignedOffer().getTraderId()));
setGraphic(field);
} else {
setGraphic(null);
setText("");
if (field != null)
field.setOnAction(null);
}
}
};
}
});
return column;
}
private TableColumn<SignedOfferListItem, SignedOfferListItem> getOfferIdColumn() {
TableColumn<SignedOfferListItem, SignedOfferListItem> column = new AutoTooltipTableColumn<>(Res.get("shared.offerId")) {
{
setMinWidth(110);
}
};
column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOfferListItem, SignedOfferListItem> call(TableColumn<SignedOfferListItem, SignedOfferListItem> column) {
return new TableCell<>() {
private HyperlinkWithIcon field;
@Override
public void updateItem(final SignedOfferListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
setText(String.valueOf(item.getSignedOffer().getOfferId()));
setGraphic(field);
} else {
setGraphic(null);
setText("");
if (field != null)
field.setOnAction(null);
}
}
};
}
});
return column;
}
private TableColumn<SignedOfferListItem, SignedOfferListItem> getMakerPenaltyFeeColumn() {
TableColumn<SignedOfferListItem, SignedOfferListItem> column = new AutoTooltipTableColumn<>(Res.get("support.maker.penalty.fee")) {
{
setMinWidth(160);
}
};
column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOfferListItem, SignedOfferListItem> call(TableColumn<SignedOfferListItem, SignedOfferListItem> column) {
return new TableCell<>() {
@Override
public void updateItem(final SignedOfferListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(HavenoUtils.formatXmr(item.getSignedOffer().getPenaltyAmount(), true));
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SignedOfferListItem, SignedOfferListItem> getReserveTxKeyImagesColumn() {
TableColumn<SignedOfferListItem, SignedOfferListItem> column = new AutoTooltipTableColumn<>(Res.get("support.txKeyImages")) {
{
setMinWidth(160);
}
};
column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOfferListItem, SignedOfferListItem> call(TableColumn<SignedOfferListItem, SignedOfferListItem> column) {
return new TableCell<>() {
@Override
public void updateItem(final SignedOfferListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(item.getSignedOffer().getReserveTxKeyImages().toString());
else
setText("");
}
};
}
});
return column;
}
}

View File

@ -0,0 +1,70 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package haveno.desktop.main.offer.signedoffer;
import com.google.inject.Inject;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import java.util.stream.Collectors;
import haveno.core.offer.OpenOfferManager;
import haveno.core.offer.SignedOffer;
import haveno.desktop.common.model.ActivatableDataModel;
import java.sql.Date;
class SignedOffersDataModel extends ActivatableDataModel {
private final OpenOfferManager openOfferManager;
private final ObservableList<SignedOfferListItem> list = FXCollections.observableArrayList();
private final ListChangeListener<SignedOffer> tradesListChangeListener;
@Inject
public SignedOffersDataModel(OpenOfferManager openOfferManager) {
this.openOfferManager = openOfferManager;
tradesListChangeListener = change -> applyList();
}
@Override
protected void activate() {
openOfferManager.getObservableSignedOffersList().addListener(tradesListChangeListener);
applyList();
}
@Override
protected void deactivate() {
openOfferManager.getObservableSignedOffersList().removeListener(tradesListChangeListener);
}
public ObservableList<SignedOfferListItem> getList() {
return list;
}
private void applyList() {
list.clear();
list.addAll(openOfferManager.getObservableSignedOffersList().stream().map(SignedOfferListItem::new).collect(Collectors.toList()));
// we sort by date, the earliest first
list.sort((o1, o2) -> new Date(o2.getSignedOffer().getTimeStamp()).compareTo(new Date(o1.getSignedOffer().getTimeStamp())));
}
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package haveno.desktop.main.offer.signedoffer;
import com.google.inject.Inject;
import javafx.collections.ObservableList;
import haveno.desktop.common.model.ActivatableWithDataModel;
import haveno.desktop.common.model.ViewModel;
class SignedOffersViewModel extends ActivatableWithDataModel<SignedOffersDataModel> implements ViewModel {
@Inject
public SignedOffersViewModel(SignedOffersDataModel model) {
super(model);
}
public ObservableList<SignedOfferListItem> getList() {
return dataModel.getList();
}
}

View File

@ -38,7 +38,7 @@ import haveno.desktop.common.view.View;
import haveno.desktop.common.view.ViewLoader; import haveno.desktop.common.view.ViewLoader;
import haveno.desktop.main.MainView; import haveno.desktop.main.MainView;
import haveno.desktop.main.overlays.popups.Popup; import haveno.desktop.main.overlays.popups.Popup;
import haveno.desktop.main.support.dispute.agent.SignedOfferView; import haveno.desktop.main.offer.signedoffer.SignedOfferView;
import haveno.desktop.main.support.dispute.agent.arbitration.ArbitratorView; import haveno.desktop.main.support.dispute.agent.arbitration.ArbitratorView;
import haveno.desktop.main.support.dispute.agent.mediation.MediatorView; import haveno.desktop.main.support.dispute.agent.mediation.MediatorView;
import haveno.desktop.main.support.dispute.agent.refund.RefundAgentView; import haveno.desktop.main.support.dispute.agent.refund.RefundAgentView;

View File

@ -1,438 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package haveno.desktop.main.support.dispute.agent;
import haveno.common.UserThread;
import haveno.common.util.Utilities;
import haveno.core.locale.Res;
import haveno.core.offer.OpenOfferManager;
import haveno.core.offer.SignedOffer;
import haveno.core.trade.HavenoUtils;
import haveno.core.xmr.wallet.XmrWalletService;
import haveno.desktop.common.view.ActivatableView;
import haveno.desktop.common.view.FxmlView;
import haveno.desktop.components.AutoTooltipLabel;
import haveno.desktop.components.AutoTooltipTableColumn;
import haveno.desktop.components.HyperlinkWithIcon;
import haveno.desktop.components.InputTextField;
import haveno.desktop.main.offer.OfferViewUtil;
import haveno.desktop.main.overlays.popups.Popup;
import haveno.desktop.util.DisplayUtils;
import haveno.desktop.util.GUIUtil;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.ListChangeListener;
import javafx.collections.transformation.SortedList;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import javafx.util.Duration;
import javax.inject.Inject;
import java.util.Comparator;
import java.util.Date;
@FxmlView
public class SignedOfferView extends ActivatableView<VBox, Void> {
private final OpenOfferManager openOfferManager;
@FXML
protected TableView<SignedOffer> tableView;
@FXML
TableColumn<SignedOffer, SignedOffer> dateColumn;
@FXML
TableColumn<SignedOffer, SignedOffer> offerIdColumn;
@FXML
TableColumn<SignedOffer, SignedOffer> reserveTxHashColumn;
@FXML
TableColumn<SignedOffer, SignedOffer> reserveTxHexColumn;
@FXML
TableColumn<SignedOffer, SignedOffer> reserveTxKeyImages;
@FXML
TableColumn<SignedOffer, SignedOffer> arbitratorSignatureColumn;
@FXML
TableColumn<SignedOffer, SignedOffer> reserveTxMinerFeeColumn;
@FXML
TableColumn<SignedOffer, SignedOffer> makerPenaltyFeeColumn;
@FXML
InputTextField filterTextField;
@FXML
Label numItems;
@FXML
Region footerSpacer;
private SignedOffer selectedSignedOffer;
private XmrWalletService xmrWalletService;
private ContextMenu contextMenu;
private final ListChangeListener<SignedOffer> signedOfferListChangeListener;
@Inject
public SignedOfferView(OpenOfferManager openOfferManager, XmrWalletService xmrWalletService) {
this.openOfferManager = openOfferManager;
this.xmrWalletService = xmrWalletService;
signedOfferListChangeListener = change -> applyList();
}
private void applyList() {
UserThread.execute(() -> {
SortedList<SignedOffer> sortedList = new SortedList<>(openOfferManager.getObservableSignedOffersList());
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
tableView.setItems(sortedList);
numItems.setText(Res.get("shared.numItemsLabel", sortedList.size()));
});
}
///////////////////////////////////////////////////////////////////////////////////////////
// Life cycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize() {
Label label = new AutoTooltipLabel(Res.get("support.filter"));
HBox.setMargin(label, new Insets(5, 0, 0, 0));
HBox.setHgrow(label, Priority.NEVER);
filterTextField = new InputTextField();
Tooltip tooltip = new Tooltip();
tooltip.setShowDelay(Duration.millis(100));
tooltip.setShowDuration(Duration.seconds(10));
filterTextField.setTooltip(tooltip);
HBox.setHgrow(filterTextField, Priority.NEVER);
filterTextField.setText("open");
setupTable();
}
@Override
protected void activate() {
super.activate();
applyList();
openOfferManager.getObservableSignedOffersList().addListener(signedOfferListChangeListener);
contextMenu = new ContextMenu();
MenuItem item1 = new MenuItem(Res.get("support.contextmenu.penalize.msg",
Res.get("shared.maker")));
contextMenu.getItems().addAll(item1);
tableView.setRowFactory(tv -> {
TableRow<SignedOffer> row = new TableRow<>();
row.setOnContextMenuRequested(event -> {
contextMenu.show(row, event.getScreenX(), event.getScreenY());
});
return row;
});
item1.setOnAction(event -> {
selectedSignedOffer = tableView.getSelectionModel().getSelectedItem();
if(selectedSignedOffer != null) {
new Popup().warning(Res.get("support.prompt.signedOffer.penalty.msg",
selectedSignedOffer.getOfferId(),
HavenoUtils.formatXmr(selectedSignedOffer.getPenaltyAmount(), true),
HavenoUtils.formatXmr(selectedSignedOffer.getReserveTxMinerFee(), true),
selectedSignedOffer.getReserveTxHash(),
selectedSignedOffer.getReserveTxKeyImages())
).onAction(() -> OfferViewUtil.submitTransactionHex(xmrWalletService, tableView,
selectedSignedOffer.getReserveTxHex())).show();
} else {
new Popup().error(Res.get("support.prompt.signedOffer.error.msg")).show();
}
});
GUIUtil.requestFocus(tableView);
}
@Override
protected void deactivate() {
super.deactivate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// SignedOfferView
///////////////////////////////////////////////////////////////////////////////////////////
protected void setupTable() {
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
Label placeholder = new AutoTooltipLabel(Res.get("support.noTickets"));
placeholder.setWrapText(true);
tableView.setPlaceholder(placeholder);
tableView.getSelectionModel().clearSelection();
dateColumn = getDateColumn();
tableView.getColumns().add(dateColumn);
offerIdColumn = getOfferIdColumn();
tableView.getColumns().add(offerIdColumn);
reserveTxHashColumn = getReserveTxHashColumn();
tableView.getColumns().add(reserveTxHashColumn);
reserveTxHexColumn = getReserveTxHexColumn();
tableView.getColumns().add(reserveTxHexColumn);
reserveTxKeyImages = getReserveTxKeyImagesColumn();
tableView.getColumns().add(reserveTxKeyImages);
arbitratorSignatureColumn = getArbitratorSignatureColumn();
tableView.getColumns().add(arbitratorSignatureColumn);
makerPenaltyFeeColumn = getMakerPenaltyFeeColumn();
tableView.getColumns().add(makerPenaltyFeeColumn);
reserveTxMinerFeeColumn = getReserveTxMinerFeeColumn();
tableView.getColumns().add(reserveTxMinerFeeColumn);
offerIdColumn.setComparator(Comparator.comparing(SignedOffer::getOfferId));
dateColumn.setComparator(Comparator.comparing(SignedOffer::getTimeStamp));
dateColumn.setSortType(TableColumn.SortType.DESCENDING);
tableView.getSortOrder().add(dateColumn);
}
private TableColumn<SignedOffer, SignedOffer> getDateColumn() {
TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("shared.date")) {
{
setMinWidth(180);
}
};
column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) {
return new TableCell<>() {
@Override
public void updateItem(final SignedOffer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(DisplayUtils.formatDateTime(new Date(item.getTimeStamp())));
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SignedOffer, SignedOffer> getOfferIdColumn() {
TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("shared.offerId")) {
{
setMinWidth(110);
}
};
column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) {
return new TableCell<>() {
private HyperlinkWithIcon field;
@Override
public void updateItem(final SignedOffer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
setText(item.getOfferId());
setGraphic(field);
} else {
setGraphic(null);
setText("");
if (field != null)
field.setOnAction(null);
}
}
};
}
});
return column;
}
private TableColumn<SignedOffer, SignedOffer> getReserveTxHashColumn() {
TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("support.txHash")) {
{
setMinWidth(160);
}
};
column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) {
return new TableCell<>() {
@Override
public void updateItem(final SignedOffer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(item.getReserveTxHash());
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SignedOffer, SignedOffer> getReserveTxHexColumn() {
TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("support.txHex")) {
{
setMinWidth(160);
}
};
column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) {
return new TableCell<>() {
@Override
public void updateItem(final SignedOffer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(item.getReserveTxHex());
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SignedOffer, SignedOffer> getReserveTxKeyImagesColumn() {
TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("support.txKeyImages")) {
{
setMinWidth(160);
}
};
column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) {
return new TableCell<>() {
@Override
public void updateItem(final SignedOffer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(item.getReserveTxKeyImages().toString());
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SignedOffer, SignedOffer> getArbitratorSignatureColumn() {
TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("support.signature")) {
{
setMinWidth(160);
}
};
column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) {
return new TableCell<>() {
@Override
public void updateItem(final SignedOffer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(Utilities.bytesAsHexString(item.getArbitratorSignature()));
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SignedOffer, SignedOffer> getMakerPenaltyFeeColumn() {
TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("support.maker.penalty.fee")) {
{
setMinWidth(160);
}
};
column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) {
return new TableCell<>() {
@Override
public void updateItem(final SignedOffer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(HavenoUtils.formatXmr(item.getPenaltyAmount(), true));
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SignedOffer, SignedOffer> getReserveTxMinerFeeColumn() {
TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("support.tx.miner.fee")) {
{
setMinWidth(160);
}
};
column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
column.setCellFactory(
new Callback<>() {
@Override
public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) {
return new TableCell<>() {
@Override
public void updateItem(final SignedOffer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(HavenoUtils.formatXmr(item.getReserveTxMinerFee(), true));
else
setText("");
}
};
}
});
return column;
}
}