Search in sources :

Example 1 with Tradable

use of bisq.core.trade.Tradable in project bisq-core by bisq-network.

the class DisputeManager method onDisputeResultMessage.

// We get that message at both peers. The dispute object is in context of the trader
private void onDisputeResultMessage(DisputeResultMessage disputeResultMessage) {
    DisputeResult disputeResult = disputeResultMessage.getDisputeResult();
    if (!isArbitrator(disputeResult)) {
        final String tradeId = disputeResult.getTradeId();
        Optional<Dispute> disputeOptional = findDispute(tradeId, disputeResult.getTraderId());
        final String uid = disputeResultMessage.getUid();
        if (disputeOptional.isPresent()) {
            cleanupRetryMap(uid);
            Dispute dispute = disputeOptional.get();
            DisputeCommunicationMessage disputeCommunicationMessage = disputeResult.getDisputeCommunicationMessage();
            if (!dispute.getDisputeCommunicationMessages().contains(disputeCommunicationMessage))
                dispute.addDisputeMessage(disputeCommunicationMessage);
            else
                log.warn("We got a dispute mail msg what we have already stored. TradeId = " + disputeCommunicationMessage.getTradeId());
            dispute.setIsClosed(true);
            if (dispute.disputeResultProperty().get() != null)
                log.warn("We got already a dispute result. That should only happen if a dispute needs to be closed " + "again because the first close did not succeed. TradeId = " + tradeId);
            dispute.setDisputeResult(disputeResult);
            // We need to avoid publishing the tx from both traders as it would create problems with zero confirmation withdrawals
            // There would be different transactions if both sign and publish (signers: once buyer+arb, once seller+arb)
            // The tx publisher is the winner or in case both get 50% the buyer, as the buyer has more inventive to publish the tx as he receives
            // more BTC as he has deposited
            final Contract contract = dispute.getContract();
            boolean isBuyer = keyRing.getPubKeyRing().equals(contract.getBuyerPubKeyRing());
            DisputeResult.Winner publisher = disputeResult.getWinner();
            // Default isLoserPublisher is set to false
            if (disputeResult.isLoserPublisher()) {
                // we invert the logic
                if (publisher == DisputeResult.Winner.BUYER)
                    publisher = DisputeResult.Winner.SELLER;
                else if (publisher == DisputeResult.Winner.SELLER)
                    publisher = DisputeResult.Winner.BUYER;
            }
            if ((isBuyer && publisher == DisputeResult.Winner.BUYER) || (!isBuyer && publisher == DisputeResult.Winner.SELLER)) {
                final Optional<Trade> tradeOptional = tradeManager.getTradeById(tradeId);
                Transaction payoutTx = null;
                if (tradeOptional.isPresent()) {
                    payoutTx = tradeOptional.get().getPayoutTx();
                } else {
                    final Optional<Tradable> tradableOptional = closedTradableManager.getTradableById(tradeId);
                    if (tradableOptional.isPresent() && tradableOptional.get() instanceof Trade) {
                        payoutTx = ((Trade) tradableOptional.get()).getPayoutTx();
                    }
                }
                if (payoutTx == null) {
                    if (dispute.getDepositTxSerialized() != null) {
                        try {
                            log.debug("do payout Transaction ");
                            byte[] multiSigPubKey = isBuyer ? contract.getBuyerMultiSigPubKey() : contract.getSellerMultiSigPubKey();
                            DeterministicKey multiSigKeyPair = walletService.getMultiSigKeyPair(dispute.getTradeId(), multiSigPubKey);
                            Transaction signedDisputedPayoutTx = tradeWalletService.traderSignAndFinalizeDisputedPayoutTx(dispute.getDepositTxSerialized(), disputeResult.getArbitratorSignature(), disputeResult.getBuyerPayoutAmount(), disputeResult.getSellerPayoutAmount(), contract.getBuyerPayoutAddressString(), contract.getSellerPayoutAddressString(), multiSigKeyPair, contract.getBuyerMultiSigPubKey(), contract.getSellerMultiSigPubKey(), disputeResult.getArbitratorPubKey());
                            Transaction committedDisputedPayoutTx = tradeWalletService.addTxToWallet(signedDisputedPayoutTx);
                            log.debug("broadcast committedDisputedPayoutTx");
                            tradeWalletService.broadcastTx(committedDisputedPayoutTx, new FutureCallback<Transaction>() {

                                @Override
                                public void onSuccess(Transaction transaction) {
                                    log.debug("BroadcastTx succeeded. Transaction:" + transaction);
                                    // after successful publish we send peer the tx
                                    dispute.setDisputePayoutTxId(transaction.getHashAsString());
                                    sendPeerPublishedPayoutTxMessage(transaction, dispute, contract);
                                    // set state after payout as we call swapTradeEntryToAvailableEntry
                                    if (tradeManager.getTradeById(dispute.getTradeId()).isPresent())
                                        tradeManager.closeDisputedTrade(dispute.getTradeId());
                                    else {
                                        Optional<OpenOffer> openOfferOptional = openOfferManager.getOpenOfferById(dispute.getTradeId());
                                        if (openOfferOptional.isPresent())
                                            openOfferManager.closeOpenOffer(openOfferOptional.get().getOffer());
                                    }
                                }

                                @Override
                                public void onFailure(@NotNull Throwable t) {
                                    log.error(t.getMessage());
                                }
                            }, 15);
                        } catch (AddressFormatException | WalletException | TransactionVerificationException e) {
                            e.printStackTrace();
                            log.error("Error at traderSignAndFinalizeDisputedPayoutTx " + e.getMessage());
                            throw new RuntimeException("Error at traderSignAndFinalizeDisputedPayoutTx " + e.toString());
                        }
                    } else {
                        log.warn("DepositTx is null. TradeId = " + tradeId);
                    }
                } else {
                    log.warn("We got already a payout tx. That might be the case if the other peer did not get the " + "payout tx and opened a dispute. TradeId = " + tradeId);
                    dispute.setDisputePayoutTxId(payoutTx.getHashAsString());
                    sendPeerPublishedPayoutTxMessage(payoutTx, dispute, contract);
                }
            } else {
                log.trace("We don't publish the tx as we are not the winning party.");
                // Clean up tangling trades
                if (dispute.disputeResultProperty().get() != null && dispute.isClosed() && tradeManager.getTradeById(dispute.getTradeId()).isPresent())
                    tradeManager.closeDisputedTrade(dispute.getTradeId());
            }
        } else {
            log.debug("We got a dispute result msg but we don't have a matching dispute. " + "That might happen when we get the disputeResultMessage before the dispute was created. " + "We try again after 2 sec. to apply the disputeResultMessage. TradeId = " + tradeId);
            if (!delayMsgMap.containsKey(uid)) {
                // We delay2 sec. to be sure the comm. msg gets added first
                Timer timer = UserThread.runAfter(() -> onDisputeResultMessage(disputeResultMessage), 2);
                delayMsgMap.put(uid, timer);
            } else {
                log.warn("We got a dispute result msg after we already repeated to apply the message after a delay. " + "That should never happen. TradeId = " + tradeId);
            }
        }
    } else {
        log.error("Arbitrator received disputeResultMessage. That must never happen.");
    }
}
Also used : Tradable(bisq.core.trade.Tradable) Trade(bisq.core.trade.Trade) DisputeCommunicationMessage(bisq.core.arbitration.messages.DisputeCommunicationMessage) WalletException(bisq.core.btc.exceptions.WalletException) AddressFormatException(org.bitcoinj.core.AddressFormatException) Optional(java.util.Optional) TransactionVerificationException(bisq.core.btc.exceptions.TransactionVerificationException) Transaction(org.bitcoinj.core.Transaction) Timer(bisq.common.Timer) Contract(bisq.core.trade.Contract) DeterministicKey(org.bitcoinj.crypto.DeterministicKey)

Example 2 with Tradable

use of bisq.core.trade.Tradable in project bisq-desktop by bisq-network.

the class TransactionAwareTradableFactoryTest method testCreateWhenNotOpenOfferOrTrade.

@Test
public void testCreateWhenNotOpenOfferOrTrade() {
    DisputeManager manager = mock(DisputeManager.class);
    TransactionAwareTradableFactory factory = new TransactionAwareTradableFactory(manager);
    Tradable delegate = mock(Tradable.class);
    assertFalse(delegate instanceof OpenOffer);
    assertFalse(delegate instanceof Trade);
    TransactionAwareTradable tradable = factory.create(delegate);
    assertFalse(tradable.isRelatedToTransaction(mock(Transaction.class)));
}
Also used : Trade(bisq.core.trade.Trade) Tradable(bisq.core.trade.Tradable) DisputeManager(bisq.core.arbitration.DisputeManager) OpenOffer(bisq.core.offer.OpenOffer) Test(org.junit.Test)

Example 3 with Tradable

use of bisq.core.trade.Tradable in project bisq-desktop by bisq-network.

the class LockedView method setDetailsColumnCellFactory.

private void setDetailsColumnCellFactory() {
    detailsColumn.setCellValueFactory((addressListItem) -> new ReadOnlyObjectWrapper<>(addressListItem.getValue()));
    detailsColumn.setCellFactory(new Callback<TableColumn<LockedListItem, LockedListItem>, TableCell<LockedListItem, LockedListItem>>() {

        @Override
        public TableCell<LockedListItem, LockedListItem> call(TableColumn<LockedListItem, LockedListItem> column) {
            return new TableCell<LockedListItem, LockedListItem>() {

                private HyperlinkWithIcon field;

                @Override
                public void updateItem(final LockedListItem item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item != null && !empty) {
                        Optional<Tradable> tradableOptional = getTradable(item);
                        AddressEntry addressEntry = item.getAddressEntry();
                        if (tradableOptional.isPresent()) {
                            field = new HyperlinkWithIcon(Res.get("funds.locked.locked", addressEntry.getShortOfferId()), AwesomeIcon.INFO_SIGN);
                            field.setOnAction(event -> openDetailPopup(item));
                            field.setTooltip(new Tooltip(Res.get("tooltip.openPopupForDetails")));
                            setGraphic(field);
                        } else if (addressEntry.getContext() == AddressEntry.Context.ARBITRATOR) {
                            setGraphic(new AutoTooltipLabel(Res.get("shared.arbitratorsFee")));
                        } else {
                            setGraphic(new AutoTooltipLabel(Res.get("shared.noDetailsAvailable")));
                        }
                    } else {
                        setGraphic(null);
                        if (field != null)
                            field.setOnAction(null);
                    }
                }
            };
        }
    });
}
Also used : GUIUtil(bisq.desktop.util.GUIUtil) BtcWalletService(bisq.core.btc.wallet.BtcWalletService) ActivatableView(bisq.desktop.common.view.ActivatableView) Transaction(org.bitcoinj.core.Transaction) OfferDetailsWindow(bisq.desktop.main.overlays.windows.OfferDetailsWindow) OpenOffer(bisq.core.offer.OpenOffer) HyperlinkWithIcon(bisq.desktop.components.HyperlinkWithIcon) Coin(org.bitcoinj.core.Coin) FXCollections(javafx.collections.FXCollections) Tradable(bisq.core.trade.Tradable) VBox(javafx.scene.layout.VBox) FxmlView(bisq.desktop.common.view.FxmlView) BSFormatter(bisq.desktop.util.BSFormatter) TableColumn(javafx.scene.control.TableColumn) Inject(javax.inject.Inject) BalanceListener(bisq.core.btc.listeners.BalanceListener) TableCell(javafx.scene.control.TableCell) ReadOnlyObjectWrapper(javafx.beans.property.ReadOnlyObjectWrapper) ListChangeListener(javafx.collections.ListChangeListener) Res(bisq.core.locale.Res) TableView(javafx.scene.control.TableView) Callback(javafx.util.Callback) Tooltip(javafx.scene.control.Tooltip) SortedList(javafx.collections.transformation.SortedList) TradeDetailsWindow(bisq.desktop.main.overlays.windows.TradeDetailsWindow) Trade(bisq.core.trade.Trade) AutoTooltipLabel(bisq.desktop.components.AutoTooltipLabel) Collectors(java.util.stream.Collectors) OpenOfferManager(bisq.core.offer.OpenOfferManager) FXML(javafx.fxml.FXML) AddressEntry(bisq.core.btc.AddressEntry) TradeManager(bisq.core.trade.TradeManager) Preferences(bisq.core.user.Preferences) Optional(java.util.Optional) ObservableList(javafx.collections.ObservableList) AwesomeIcon(de.jensd.fx.fontawesome.AwesomeIcon) Optional(java.util.Optional) AddressEntry(bisq.core.btc.AddressEntry) Tooltip(javafx.scene.control.Tooltip) TableColumn(javafx.scene.control.TableColumn) TableCell(javafx.scene.control.TableCell) AutoTooltipLabel(bisq.desktop.components.AutoTooltipLabel) HyperlinkWithIcon(bisq.desktop.components.HyperlinkWithIcon)

Example 4 with Tradable

use of bisq.core.trade.Tradable in project bisq-desktop by bisq-network.

the class ReservedView method setDetailsColumnCellFactory.

private void setDetailsColumnCellFactory() {
    detailsColumn.setCellValueFactory((addressListItem) -> new ReadOnlyObjectWrapper<>(addressListItem.getValue()));
    detailsColumn.setCellFactory(new Callback<TableColumn<ReservedListItem, ReservedListItem>, TableCell<ReservedListItem, ReservedListItem>>() {

        @Override
        public TableCell<ReservedListItem, ReservedListItem> call(TableColumn<ReservedListItem, ReservedListItem> column) {
            return new TableCell<ReservedListItem, ReservedListItem>() {

                private HyperlinkWithIcon field;

                @Override
                public void updateItem(final ReservedListItem item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item != null && !empty) {
                        Optional<Tradable> tradableOptional = getTradable(item);
                        if (tradableOptional.isPresent()) {
                            field = new HyperlinkWithIcon(Res.get("funds.reserved.reserved", item.getAddressEntry().getShortOfferId()), AwesomeIcon.INFO_SIGN);
                            field.setOnAction(event -> openDetailPopup(item));
                            field.setTooltip(new Tooltip(Res.get("tooltip.openPopupForDetails")));
                            setGraphic(field);
                        } else if (item.getAddressEntry().getContext() == AddressEntry.Context.ARBITRATOR) {
                            setGraphic(new AutoTooltipLabel(Res.get("shared.arbitratorsFee")));
                        } else {
                            setGraphic(new AutoTooltipLabel(Res.get("shared.noDetailsAvailable")));
                        }
                    } else {
                        setGraphic(null);
                        if (field != null)
                            field.setOnAction(null);
                    }
                }
            };
        }
    });
}
Also used : GUIUtil(bisq.desktop.util.GUIUtil) BtcWalletService(bisq.core.btc.wallet.BtcWalletService) ActivatableView(bisq.desktop.common.view.ActivatableView) Transaction(org.bitcoinj.core.Transaction) OfferDetailsWindow(bisq.desktop.main.overlays.windows.OfferDetailsWindow) OpenOffer(bisq.core.offer.OpenOffer) HyperlinkWithIcon(bisq.desktop.components.HyperlinkWithIcon) Coin(org.bitcoinj.core.Coin) FXCollections(javafx.collections.FXCollections) Tradable(bisq.core.trade.Tradable) VBox(javafx.scene.layout.VBox) FxmlView(bisq.desktop.common.view.FxmlView) BSFormatter(bisq.desktop.util.BSFormatter) TableColumn(javafx.scene.control.TableColumn) Inject(javax.inject.Inject) BalanceListener(bisq.core.btc.listeners.BalanceListener) TableCell(javafx.scene.control.TableCell) ReadOnlyObjectWrapper(javafx.beans.property.ReadOnlyObjectWrapper) ListChangeListener(javafx.collections.ListChangeListener) Res(bisq.core.locale.Res) TableView(javafx.scene.control.TableView) Callback(javafx.util.Callback) Tooltip(javafx.scene.control.Tooltip) SortedList(javafx.collections.transformation.SortedList) TradeDetailsWindow(bisq.desktop.main.overlays.windows.TradeDetailsWindow) Trade(bisq.core.trade.Trade) AutoTooltipLabel(bisq.desktop.components.AutoTooltipLabel) Collectors(java.util.stream.Collectors) OpenOfferManager(bisq.core.offer.OpenOfferManager) FXML(javafx.fxml.FXML) AddressEntry(bisq.core.btc.AddressEntry) TradeManager(bisq.core.trade.TradeManager) Preferences(bisq.core.user.Preferences) Optional(java.util.Optional) ObservableList(javafx.collections.ObservableList) AwesomeIcon(de.jensd.fx.fontawesome.AwesomeIcon) Optional(java.util.Optional) Tooltip(javafx.scene.control.Tooltip) TableColumn(javafx.scene.control.TableColumn) TableCell(javafx.scene.control.TableCell) AutoTooltipLabel(bisq.desktop.components.AutoTooltipLabel) HyperlinkWithIcon(bisq.desktop.components.HyperlinkWithIcon)

Example 5 with Tradable

use of bisq.core.trade.Tradable in project bisq-desktop by bisq-network.

the class ClosedTradesView method initialize.

@Override
public void initialize() {
    priceColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.price")));
    amountColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amountWithCur", Res.getBaseCurrencyCode())));
    volumeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amount")));
    marketColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.market")));
    directionColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.offerType")));
    dateColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.dateTime")));
    tradeIdColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.tradeId")));
    stateColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.state")));
    avatarColumn.setText("");
    tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    tableView.setPlaceholder(new AutoTooltipLabel(Res.get("table.placeholder.noItems", Res.get("shared.trades"))));
    setTradeIdColumnCellFactory();
    setDirectionColumnCellFactory();
    setAmountColumnCellFactory();
    setPriceColumnCellFactory();
    setVolumeColumnCellFactory();
    setDateColumnCellFactory();
    setMarketColumnCellFactory();
    setStateColumnCellFactory();
    setAvatarColumnCellFactory();
    tradeIdColumn.setComparator(Comparator.comparing(o -> o.getTradable().getId()));
    dateColumn.setComparator(Comparator.comparing(o -> o.getTradable().getDate()));
    directionColumn.setComparator(Comparator.comparing(o -> o.getTradable().getOffer().getDirection()));
    marketColumn.setComparator(Comparator.comparing(model::getMarketLabel));
    priceColumn.setComparator((o1, o2) -> {
        final Tradable tradable1 = o1.getTradable();
        final Tradable tradable2 = o2.getTradable();
        Price price1 = null;
        Price price2 = null;
        if (tradable1 != null)
            price1 = tradable1 instanceof Trade ? ((Trade) tradable1).getTradePrice() : tradable1.getOffer().getPrice();
        if (tradable2 != null)
            price2 = tradable2 instanceof Trade ? ((Trade) tradable2).getTradePrice() : tradable2.getOffer().getPrice();
        return price1 != null && price2 != null ? price1.compareTo(price2) : 0;
    });
    volumeColumn.setComparator((o1, o2) -> {
        if (o1.getTradable() instanceof Trade && o2.getTradable() instanceof Trade) {
            Volume tradeVolume1 = ((Trade) o1.getTradable()).getTradeVolume();
            Volume tradeVolume2 = ((Trade) o2.getTradable()).getTradeVolume();
            return tradeVolume1 != null && tradeVolume2 != null ? tradeVolume1.compareTo(tradeVolume2) : 0;
        } else
            return 0;
    });
    amountColumn.setComparator((o1, o2) -> {
        if (o1.getTradable() instanceof Trade && o2.getTradable() instanceof Trade) {
            Coin amount1 = ((Trade) o1.getTradable()).getTradeAmount();
            Coin amount2 = ((Trade) o2.getTradable()).getTradeAmount();
            return amount1 != null && amount2 != null ? amount1.compareTo(amount2) : 0;
        } else
            return 0;
    });
    avatarColumn.setComparator((o1, o2) -> {
        if (o1.getTradable() instanceof Trade && o2.getTradable() instanceof Trade) {
            NodeAddress tradingPeerNodeAddress1 = ((Trade) o1.getTradable()).getTradingPeerNodeAddress();
            NodeAddress tradingPeerNodeAddress2 = ((Trade) o2.getTradable()).getTradingPeerNodeAddress();
            String address1 = tradingPeerNodeAddress1 != null ? tradingPeerNodeAddress1.getFullAddress() : "";
            String address2 = tradingPeerNodeAddress2 != null ? tradingPeerNodeAddress2.getFullAddress() : "";
            return address1 != null && address2 != null ? address1.compareTo(address2) : 0;
        } else
            return 0;
    });
    stateColumn.setComparator((o1, o2) -> model.getState(o1).compareTo(model.getState(o2)));
    dateColumn.setSortType(TableColumn.SortType.DESCENDING);
    tableView.getSortOrder().add(dateColumn);
    exportButton.setText(Res.get("shared.exportCSV"));
}
Also used : Button(javafx.scene.control.Button) GUIUtil(bisq.desktop.util.GUIUtil) OfferDetailsWindow(bisq.desktop.main.overlays.windows.OfferDetailsWindow) OpenOffer(bisq.core.offer.OpenOffer) HyperlinkWithIcon(bisq.desktop.components.HyperlinkWithIcon) Coin(org.bitcoinj.core.Coin) Tradable(bisq.core.trade.Tradable) CSVEntryConverter(com.googlecode.jcsv.writer.CSVEntryConverter) VBox(javafx.scene.layout.VBox) Volume(bisq.core.monetary.Volume) FxmlView(bisq.desktop.common.view.FxmlView) BSFormatter(bisq.desktop.util.BSFormatter) TableColumn(javafx.scene.control.TableColumn) Inject(javax.inject.Inject) TableCell(javafx.scene.control.TableCell) Insets(javafx.geometry.Insets) ReadOnlyObjectWrapper(javafx.beans.property.ReadOnlyObjectWrapper) Res(bisq.core.locale.Res) TableView(javafx.scene.control.TableView) Callback(javafx.util.Callback) Tooltip(javafx.scene.control.Tooltip) PrivateNotificationManager(bisq.core.alert.PrivateNotificationManager) SortedList(javafx.collections.transformation.SortedList) Offer(bisq.core.offer.Offer) TradeDetailsWindow(bisq.desktop.main.overlays.windows.TradeDetailsWindow) Trade(bisq.core.trade.Trade) AutoTooltipLabel(bisq.desktop.components.AutoTooltipLabel) Node(javafx.scene.Node) PeerInfoIcon(bisq.desktop.components.PeerInfoIcon) FXML(javafx.fxml.FXML) Stage(javafx.stage.Stage) NodeAddress(bisq.network.p2p.NodeAddress) AppOptionKeys(bisq.core.app.AppOptionKeys) Preferences(bisq.core.user.Preferences) Price(bisq.core.monetary.Price) Named(com.google.inject.name.Named) ObservableList(javafx.collections.ObservableList) ActivatableViewAndModel(bisq.desktop.common.view.ActivatableViewAndModel) Comparator(java.util.Comparator) Trade(bisq.core.trade.Trade) Coin(org.bitcoinj.core.Coin) Price(bisq.core.monetary.Price) Volume(bisq.core.monetary.Volume) Tradable(bisq.core.trade.Tradable) NodeAddress(bisq.network.p2p.NodeAddress) AutoTooltipLabel(bisq.desktop.components.AutoTooltipLabel)

Aggregations

Tradable (bisq.core.trade.Tradable)6 Trade (bisq.core.trade.Trade)6 OpenOffer (bisq.core.offer.OpenOffer)5 Res (bisq.core.locale.Res)4 Preferences (bisq.core.user.Preferences)4 FxmlView (bisq.desktop.common.view.FxmlView)4 AutoTooltipLabel (bisq.desktop.components.AutoTooltipLabel)4 HyperlinkWithIcon (bisq.desktop.components.HyperlinkWithIcon)4 OfferDetailsWindow (bisq.desktop.main.overlays.windows.OfferDetailsWindow)4 TradeDetailsWindow (bisq.desktop.main.overlays.windows.TradeDetailsWindow)4 BSFormatter (bisq.desktop.util.BSFormatter)4 GUIUtil (bisq.desktop.util.GUIUtil)4 ReadOnlyObjectWrapper (javafx.beans.property.ReadOnlyObjectWrapper)4 ObservableList (javafx.collections.ObservableList)4 SortedList (javafx.collections.transformation.SortedList)4 FXML (javafx.fxml.FXML)4 TableCell (javafx.scene.control.TableCell)4 TableColumn (javafx.scene.control.TableColumn)4 TableView (javafx.scene.control.TableView)4 Tooltip (javafx.scene.control.Tooltip)4