Add closed trades and open offers UIs

This commit is contained in:
Manfred Karrer 2014-09-26 01:23:52 +02:00
parent 8ae0dd8b41
commit 63df466281
26 changed files with 1332 additions and 433 deletions

View File

@ -89,17 +89,14 @@ import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
* Wait until steve's akka version to see how to continue here
*/
public class WalletFacade {
private static final Logger log = LoggerFactory.getLogger(WalletFacade.class);
public static final String MAIN_NET = "MAIN_NET";
public static final String TEST_NET = "TEST_NET";
public static final String REG_TEST_NET = "REG_TEST_NET";
public static final String WALLET_PREFIX = BitSquare.getAppName();
private static final Logger log = LoggerFactory.getLogger(WalletFacade.class);
private final ReentrantLock lock = Threading.lock("lock");
private final NetworkParameters params;
private WalletAppKit walletAppKit;
private final FeePolicy feePolicy;

View File

@ -22,7 +22,6 @@ import io.bitsquare.persistence.Persistence;
import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@ -58,34 +57,32 @@ public class Navigation {
///////////////////////////////////////////////////////////////////////////////////////////
public void navigationTo(Item... items) {
if (items != null)
log.trace("navigationTo " + Arrays.asList(items).toString());
List<Item> temp = new ArrayList<>();
for (int i = 0; i < items.length; i++) {
Item item = items[i];
temp.add(item);
if (currentItems == null ||
(currentItems != null &&
currentItems.length > i &&
item != currentItems[i] &&
i != items.length - 1)) {
List<Item> temp2 = new ArrayList<>(temp);
for (int n = i + 1; n < items.length; n++) {
Item[] newTemp = new Item[i + 1];
currentItems = temp2.toArray(newTemp);
navigationTo(currentItems);
item = items[n];
temp2.add(item);
if (items != null) {
for (int i = 0; i < items.length; i++) {
Item item = items[i];
temp.add(item);
if (currentItems == null ||
(currentItems != null &&
currentItems.length > i &&
item != currentItems[i] &&
i != items.length - 1)) {
List<Item> temp2 = new ArrayList<>(temp);
for (int n = i + 1; n < items.length; n++) {
Item[] newTemp = new Item[i + 1];
currentItems = temp2.toArray(newTemp);
navigationTo(currentItems);
item = items[n];
temp2.add(item);
}
}
}
}
currentItems = items;
persistence.write(this, "navigationItems", items);
if (items != null)
log.trace("navigationTo notify listeners " + Arrays.asList(items).toString() + " / " + listeners
.size());
listeners.stream().forEach((e) -> e.onNavigationRequested(items));
currentItems = items;
persistence.write(this, "navigationItems", items);
listeners.stream().forEach((e) -> e.onNavigationRequested(items));
}
}
public void navigateToLastStoredItem() {

View File

@ -174,14 +174,15 @@ class MainModel extends UIModel {
}
});
tradeManager.getTrades().addListener((MapChangeListener<String, Trade>) change -> updateNumPendingTrades());
tradeManager.getPendingTrades().addListener((MapChangeListener<String,
Trade>) change -> updateNumPendingTrades());
updateNumPendingTrades();
backendInited.set(true);
}
private void updateNumPendingTrades() {
numPendingTrades.set(tradeManager.getTrades().size());
numPendingTrades.set(tradeManager.getPendingTrades().size());
}
private void updateBalance(Coin balance) {

View File

@ -83,21 +83,49 @@ public class AccountSetupViewCB extends ViewCB implements MultiStepNavigation {
if (navigationItems != null &&
navigationItems.length == 4 &&
navigationItems[2] == Navigation.Item.ACCOUNT_SETUP) {
loadView(navigationItems[3]);
log.debug("### " + navigationItems[3]);
//loadView(navigationItems[3]);
switch (navigationItems[3]) {
case SEED_WORDS:
childController = seedWords.show();
break;
case ADD_PASSWORD:
seedWords.onCompleted();
childController = password.show();
break;
case RESTRICTIONS:
seedWords.onCompleted();
password.onCompleted();
childController = restrictions.show();
break;
case FIAT_ACCOUNT:
seedWords.onCompleted();
password.onCompleted();
restrictions.onCompleted();
childController = fiatAccount.show();
break;
case REGISTRATION:
seedWords.onCompleted();
password.onCompleted();
restrictions.onCompleted();
fiatAccount.onCompleted();
childController = registration.show();
break;
}
}
};
seedWords = new WizardItem(navigation, "Backup wallet seed", "Write down the seed word for your wallet",
seedWords = new WizardItem(navigation, this, "Backup wallet seed", "Write down the seed word for your wallet",
Navigation.Item.SEED_WORDS);
password = new WizardItem(navigation, "Setup password", "Protect your wallet with a password",
password = new WizardItem(navigation, this, "Setup password", "Protect your wallet with a password",
Navigation.Item.ADD_PASSWORD);
restrictions = new WizardItem(navigation, "Setup your preferences",
restrictions = new WizardItem(navigation, this, "Setup your preferences",
"Define your preferences with whom you want to trade",
Navigation.Item.RESTRICTIONS);
fiatAccount = new WizardItem(navigation, " Setup Payments account(s)",
fiatAccount = new WizardItem(navigation, this, " Setup Payments account(s)",
"You need to add a payments account to your trading account",
Navigation.Item.FIAT_ACCOUNT);
registration = new WizardItem(navigation, "Register your account",
registration = new WizardItem(navigation, this, "Register your account",
"Pay in the registration fee of 0.0002 BTC and store your account in the BTC block chain",
Navigation.Item.REGISTRATION);
@ -107,9 +135,7 @@ public class AccountSetupViewCB extends ViewCB implements MultiStepNavigation {
navigation.addListener(listener);
// triggers navigationTo
childController = seedWords.show();
}
@Override
@ -145,7 +171,10 @@ public class AccountSetupViewCB extends ViewCB implements MultiStepNavigation {
registration.onCompleted();
childController = null;
navigation.navigationTo(navigation.getItemsForReturning());
if (navigation.getItemsForReturning() != null)
navigation.navigationTo(navigation.getItemsForReturning());
else
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.HOME);
}
}
@ -180,12 +209,14 @@ class WizardItem extends HBox {
private final ImageView imageView;
private final Label titleLabel;
private final Label subTitleLabel;
private AccountSetupViewCB host;
private final Navigation.Item navigationItem;
private final Navigation navigation;
WizardItem(Navigation navigation, String title, String subTitle,
WizardItem(Navigation navigation, AccountSetupViewCB host, String title, String subTitle,
Navigation.Item navigationItem) {
this.navigation = navigation;
this.host = host;
this.navigationItem = navigationItem;
setId("wizard-item-background-deactivated");
@ -223,9 +254,10 @@ class WizardItem extends HBox {
}
ViewCB<? extends PresentationModel> show() {
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ACCOUNT, Navigation
host.loadView(navigationItem);
/* navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ACCOUNT, Navigation
.Item.ACCOUNT_SETUP,
navigationItem);
navigationItem);*/
setId("wizard-item-background-active");
imageView.setId("image-arrow-blue");

View File

@ -20,6 +20,7 @@ package io.bitsquare.gui.main.orders;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.ViewCB;
import io.bitsquare.trade.TradeManager;
import io.bitsquare.util.ViewLoader;
import java.io.IOException;
@ -30,6 +31,7 @@ import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
@ -42,9 +44,11 @@ public class OrdersViewCB extends CachedViewCB {
private static final Logger log = LoggerFactory.getLogger(OrdersViewCB.class);
private Navigation navigation;
private Navigation.Listener listener;
private TradeManager tradeManager;
private Navigation.Listener navigationListener;
@FXML Tab offersTab, pendingTradesTab, closedTradesTab;
private ChangeListener<Tab> tabChangeListener;
///////////////////////////////////////////////////////////////////////////////////////////
@ -52,10 +56,11 @@ public class OrdersViewCB extends CachedViewCB {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
OrdersViewCB(Navigation navigation) {
OrdersViewCB(Navigation navigation, TradeManager tradeManager) {
super();
this.navigation = navigation;
this.tradeManager = tradeManager;
}
@ -65,29 +70,47 @@ public class OrdersViewCB extends CachedViewCB {
@Override
public void initialize(URL url, ResourceBundle rb) {
listener = navigationItems -> {
if (navigationItems != null && navigationItems.length == 3 && navigationItems[1] == Navigation.Item.ORDERS)
navigationListener = navigationItems -> {
if (navigationItems != null && navigationItems.length == 3 && navigationItems[1] == Navigation.Item
.ORDERS) {
log.debug("#### Orders " + navigationItems[2]);
loadView(navigationItems[2]);
}
};
tabChangeListener = (ov, oldValue, newValue) -> {
log.debug("#### newValue " + newValue.getText());
if (newValue == offersTab)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ORDERS, Navigation.Item.OFFERS);
else if (newValue == pendingTradesTab)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ORDERS, Navigation.Item.PENDING_TRADES);
else if (newValue == closedTradesTab)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ORDERS, Navigation.Item.CLOSED_TRADES);
};
super.initialize(url, rb);
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
navigation.addListener(listener);
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ORDERS, Navigation.Item.PENDING_TRADES);
((TabPane) root).getSelectionModel().selectedItemProperty().addListener(tabChangeListener);
navigation.addListener(navigationListener);
if (tradeManager.getPendingTrades().size() == 0)
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ORDERS, Navigation.Item.OFFERS);
else
navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ORDERS, Navigation.Item.PENDING_TRADES);
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
navigation.removeListener(listener);
((TabPane) root).getSelectionModel().selectedItemProperty().removeListener(tabChangeListener);
navigation.removeListener(navigationListener);
}
@SuppressWarnings("EmptyMethod")

View File

@ -17,60 +17,31 @@
package io.bitsquare.gui.main.orders.closed;
import io.bitsquare.gui.CachedViewController;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import io.bitsquare.trade.Trade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//TODO impl. missing yet
public class ClosedTradeController extends CachedViewController {
private static final Logger log = LoggerFactory.getLogger(ClosedTradeController.class);
public class ClosedTradesListItem {
private static final Logger log = LoggerFactory.getLogger(ClosedTradesListItem.class);
private final Trade trade;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private ClosedTradeController() {
ClosedTradesListItem(Trade trade) {
this.trade = trade;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
Trade getTrade() {
return trade;
}
@Override
public void deactivate() {
super.deactivate();
}
@Override
public void activate() {
super.activate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// GUI Event handlers
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private Methods
///////////////////////////////////////////////////////////////////////////////////////////
}

View File

@ -0,0 +1,103 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare 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.
*
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.main.orders.closed;
import io.bitsquare.gui.UIModel;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeManager;
import com.google.inject.Inject;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ClosedTradesModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(ClosedTradesModel.class);
private TradeManager tradeManager;
private ObservableList<ClosedTradesListItem> list = FXCollections.observableArrayList();
private MapChangeListener<String, Trade> mapChangeListener;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public ClosedTradesModel(TradeManager tradeManager) {
this.tradeManager = tradeManager;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize() {
mapChangeListener = change -> {
if (change.wasAdded())
list.add(new ClosedTradesListItem(change.getValueAdded()));
else if (change.wasRemoved())
list.removeIf(e -> e.getTrade().getId().equals(change.getValueRemoved().getId()));
};
super.initialize();
}
@Override
public void activate() {
super.activate();
list.clear();
tradeManager.getClosedTrades().values().stream()
.forEach(e -> list.add(new ClosedTradesListItem(e)));
tradeManager.getClosedTrades().addListener(mapChangeListener);
// we sort by date
list.sort((o1, o2) -> o2.getTrade().getDate().compareTo(o1.getTrade().getDate()));
}
@Override
public void deactivate() {
super.deactivate();
tradeManager.getClosedTrades().removeListener(mapChangeListener);
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
public ObservableList<ClosedTradesListItem> getList() {
return list;
}
}

View File

@ -0,0 +1,118 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare 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.
*
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.main.orders.closed;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.util.BSFormatter;
import com.google.inject.Inject;
import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ClosedTradesPM extends PresentationModel<ClosedTradesModel> {
private static final Logger log = LoggerFactory.getLogger(ClosedTradesPM.class);
private BSFormatter formatter;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public ClosedTradesPM(ClosedTradesModel model, BSFormatter formatter) {
super(model);
this.formatter = formatter;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize() {
super.initialize();
}
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
public ObservableList<ClosedTradesListItem> getList() {
return model.getList();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
String getTradeId(ClosedTradesListItem item) {
return item.getTrade().getId();
}
String getAmount(ClosedTradesListItem item) {
return (item != null) ? BSFormatter.formatAmountWithMinAmount(item.getTrade().getOffer()) : "";
}
String getPrice(ClosedTradesListItem item) {
return (item != null) ? BSFormatter.formatFiat(item.getTrade().getOffer().getPrice()) : "";
}
String getVolume(ClosedTradesListItem item) {
return (item != null) ? BSFormatter.formatVolumeWithMinVolume(item.getTrade().getOffer()) : "";
}
String getDirectionLabel(ClosedTradesListItem item) {
return (item != null) ? BSFormatter.formatDirection(item.getTrade().getOffer().getMirroredDirection()) : "";
}
String getDate(ClosedTradesListItem item) {
return formatter.formatDateTime(item.getTrade().getDate());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
}

View File

@ -17,15 +17,40 @@
~ along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
-->
<?import io.bitsquare.gui.components.TitledSeparator?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.orders.closed.ClosedTradeController"
AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" AnchorPane.topAnchor="0"
xmlns:fx="http://javafx.com/fxml">
<VBox spacing="20" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0">
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.orders.closed.ClosedTradesViewCB"
hgap="5.0" vgap="5"
xmlns:fx="http://javafx.com/fxml">
<padding>
<Insets bottom="20.0" left="25.0" top="30.0" right="25"/>
</padding>
<Label id="form-header-text" text="Closed"/>
<TitledSeparator text="Closed trades" GridPane.rowIndex="0" GridPane.columnIndex="0" GridPane.columnSpan="2"/>
</VBox>
</AnchorPane>
<TableView fx:id="table" GridPane.rowIndex="0" GridPane.columnIndex="0" GridPane.columnSpan="2">
<GridPane.margin>
<Insets top="10.0" left="-10" right="-10" bottom="-15"/>
</GridPane.margin>
<columns>
<TableColumn text="Trade ID" fx:id="tradeIdColumn" minWidth="100" sortable="false"/>
<TableColumn text="Date" fx:id="dateColumn" minWidth="130"/>
<TableColumn text="Amount in BTC (Min.)" fx:id="amountColumn" minWidth="130" sortable="false"/>
<TableColumn text="Price" fx:id="priceColumn" minWidth="100" sortable="false"/>
<TableColumn text="Amount in EUR (Min.)" fx:id="volumeColumn" minWidth="130" sortable="false"/>
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="80" sortable="false"/>
</columns>
</TableView>
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/>
<ColumnConstraints hgrow="ALWAYS"/>
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="ALWAYS"/>
</rowConstraints>
</GridPane>

View File

@ -0,0 +1,240 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare 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.
*
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.main.orders.closed;
import io.bitsquare.gui.CachedViewCB;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.util.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ClosedTradesViewCB extends CachedViewCB<ClosedTradesPM> {
private static final Logger log = LoggerFactory.getLogger(ClosedTradesViewCB.class);
@FXML TableColumn<ClosedTradesListItem, ClosedTradesListItem> priceColumn, amountColumn, volumeColumn,
directionColumn, dateColumn, tradeIdColumn, removeItemColumn;
@FXML TableView<ClosedTradesListItem> table;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private ClosedTradesViewCB(ClosedTradesPM presentationModel) {
super(presentationModel);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
setTradeIdColumnCellFactory();
setDirectionColumnCellFactory();
setAmountColumnCellFactory();
setPriceColumnCellFactory();
setVolumeColumnCellFactory();
setDateColumnCellFactory();
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
super.initialize(url, rb);
}
@Override
public void activate() {
super.activate();
table.setItems(presentationModel.getList());
}
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private Methods
///////////////////////////////////////////////////////////////////////////////////////////
private void openOfferDetails(ClosedTradesListItem item) {
// TODO Open popup with details view
log.debug("Trade details " + item);
}
///////////////////////////////////////////////////////////////////////////////////////////
// CellFactories
///////////////////////////////////////////////////////////////////////////////////////////
private void setTradeIdColumnCellFactory() {
tradeIdColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper(offerListItem.getValue()));
tradeIdColumn.setCellFactory(
new Callback<TableColumn<ClosedTradesListItem, ClosedTradesListItem>, TableCell<ClosedTradesListItem,
ClosedTradesListItem>>() {
@Override
public TableCell<ClosedTradesListItem, ClosedTradesListItem> call(TableColumn<ClosedTradesListItem,
ClosedTradesListItem> column) {
return new TableCell<ClosedTradesListItem, ClosedTradesListItem>() {
Hyperlink hyperlink;
@Override
public void updateItem(final ClosedTradesListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
hyperlink = new Hyperlink(presentationModel.getTradeId(item));
Tooltip.install(hyperlink, new Tooltip(presentationModel.getTradeId(item)));
hyperlink.setOnAction(event -> openOfferDetails(item));
setGraphic(hyperlink);
}
else {
setGraphic(null);
setId(null);
}
}
};
}
});
}
private void setDateColumnCellFactory() {
dateColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
dateColumn.setCellFactory(
new Callback<TableColumn<ClosedTradesListItem, ClosedTradesListItem>, TableCell<ClosedTradesListItem,
ClosedTradesListItem>>() {
@Override
public TableCell<ClosedTradesListItem, ClosedTradesListItem> call(
TableColumn<ClosedTradesListItem, ClosedTradesListItem> column) {
return new TableCell<ClosedTradesListItem, ClosedTradesListItem>() {
@Override
public void updateItem(final ClosedTradesListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null)
setText(presentationModel.getDate(item));
else
setText("");
}
};
}
});
}
private void setAmountColumnCellFactory() {
amountColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
amountColumn.setCellFactory(
new Callback<TableColumn<ClosedTradesListItem, ClosedTradesListItem>, TableCell<ClosedTradesListItem,
ClosedTradesListItem>>() {
@Override
public TableCell<ClosedTradesListItem, ClosedTradesListItem> call(
TableColumn<ClosedTradesListItem, ClosedTradesListItem> column) {
return new TableCell<ClosedTradesListItem, ClosedTradesListItem>() {
@Override
public void updateItem(final ClosedTradesListItem item, boolean empty) {
super.updateItem(item, empty);
setText(presentationModel.getAmount(item));
}
};
}
});
}
private void setPriceColumnCellFactory() {
priceColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
priceColumn.setCellFactory(
new Callback<TableColumn<ClosedTradesListItem, ClosedTradesListItem>, TableCell<ClosedTradesListItem,
ClosedTradesListItem>>() {
@Override
public TableCell<ClosedTradesListItem, ClosedTradesListItem> call(
TableColumn<ClosedTradesListItem, ClosedTradesListItem> column) {
return new TableCell<ClosedTradesListItem, ClosedTradesListItem>() {
@Override
public void updateItem(final ClosedTradesListItem item, boolean empty) {
super.updateItem(item, empty);
setText(presentationModel.getPrice(item));
}
};
}
});
}
private void setVolumeColumnCellFactory() {
volumeColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
volumeColumn.setCellFactory(
new Callback<TableColumn<ClosedTradesListItem, ClosedTradesListItem>, TableCell<ClosedTradesListItem,
ClosedTradesListItem>>() {
@Override
public TableCell<ClosedTradesListItem, ClosedTradesListItem> call(
TableColumn<ClosedTradesListItem, ClosedTradesListItem> column) {
return new TableCell<ClosedTradesListItem, ClosedTradesListItem>() {
@Override
public void updateItem(final ClosedTradesListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null)
setText(presentationModel.getVolume(item));
else
setText("");
}
};
}
});
}
private void setDirectionColumnCellFactory() {
directionColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
directionColumn.setCellFactory(
new Callback<TableColumn<ClosedTradesListItem, ClosedTradesListItem>, TableCell<ClosedTradesListItem,
ClosedTradesListItem>>() {
@Override
public TableCell<ClosedTradesListItem, ClosedTradesListItem> call(
TableColumn<ClosedTradesListItem, ClosedTradesListItem> column) {
return new TableCell<ClosedTradesListItem, ClosedTradesListItem>() {
@Override
public void updateItem(final ClosedTradesListItem item, boolean empty) {
super.updateItem(item, empty);
setText(presentationModel.getDirectionLabel(item));
}
};
}
});
}
}

View File

@ -1,184 +0,0 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare 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.
*
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.main.orders.offer;
import io.bitsquare.gui.CachedViewController;
import io.bitsquare.gui.util.ImageUtil;
import io.bitsquare.trade.Offer;
import io.bitsquare.trade.TradeManager;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.util.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OfferController extends CachedViewController {
private static final Logger log = LoggerFactory.getLogger(OfferController.class);
private final TradeManager tradeManager;
private ObservableList<OfferListItem> offerListItems;
@FXML TableColumn<String, OfferListItem> offerIdColumn, dateColumn, amountColumn, priceColumn,
volumeColumn, removeColumn;
@FXML TableView<OfferListItem> offerTable;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private OfferController(TradeManager tradeManager) {
this.tradeManager = tradeManager;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
setOfferIdColumnColumnCellFactory();
setRemoveColumnCellFactory();
offerTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
}
@Override
public void deactivate() {
super.deactivate();
}
@Override
public void activate() {
super.activate();
offerListItems = FXCollections.observableArrayList();
Map<String, Offer> offerMap = tradeManager.getOffers();
List<Offer> offerList = new ArrayList<>(offerMap.values());
offerListItems.addAll(offerList.stream().map(OfferListItem::new).collect(Collectors.toList()));
offerTable.setItems(offerListItems);
}
///////////////////////////////////////////////////////////////////////////////////////////
// GUI Event handlers
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private Methods
///////////////////////////////////////////////////////////////////////////////////////////
private void removeOffer(OfferListItem offerListItem) {
tradeManager.removeOffer(offerListItem.getOffer());
offerListItems.remove(offerListItem);
}
private void openOfferDetails(OfferListItem offerListItem) {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Table columns
///////////////////////////////////////////////////////////////////////////////////////////
private void setOfferIdColumnColumnCellFactory() {
offerIdColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper(offerListItem.getValue()));
offerIdColumn.setCellFactory(
new Callback<TableColumn<String, OfferListItem>, TableCell<String, OfferListItem>>() {
@Override
public TableCell<String, OfferListItem> call(TableColumn<String, OfferListItem> column) {
return new TableCell<String, OfferListItem>() {
Hyperlink hyperlink;
@Override
public void updateItem(final OfferListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
hyperlink = new Hyperlink(item.getOfferId());
//hyperlink.getStyleClass().setAll("aaa");
Tooltip tooltip = new Tooltip(item.getOfferId());
Tooltip.install(hyperlink, tooltip);
hyperlink.setOnAction(event -> openOfferDetails(item));
setGraphic(hyperlink);
}
else {
setGraphic(null);
setId(null);
}
}
};
}
});
}
private void setRemoveColumnCellFactory() {
removeColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper(offerListItem.getValue()));
removeColumn.setCellFactory(
new Callback<TableColumn<String, OfferListItem>, TableCell<String, OfferListItem>>() {
@Override
public TableCell<String, OfferListItem> call(TableColumn<String, OfferListItem> directionColumn) {
return new TableCell<String, OfferListItem>() {
final ImageView iconView = ImageUtil.getImageViewById(ImageUtil.REMOVE_ICON);
final Button button = new Button();
{
button.setText("Remove");
button.setGraphic(iconView);
button.setMinWidth(70);
}
@Override
public void updateItem(final OfferListItem offerListItem, boolean empty) {
super.updateItem(offerListItem, empty);
if (offerListItem != null) {
button.setOnAction(event -> removeOffer(offerListItem));
setGraphic(button);
}
else {
setGraphic(null);
}
}
};
}
});
}
}

View File

@ -0,0 +1,110 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare 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.
*
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.main.orders.offer;
import io.bitsquare.gui.UIModel;
import io.bitsquare.trade.Offer;
import io.bitsquare.trade.TradeManager;
import com.google.inject.Inject;
import java.util.stream.Collectors;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OffersModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(OffersModel.class);
private TradeManager tradeManager;
private ObservableList<OfferListItem> list = FXCollections.observableArrayList();
private MapChangeListener<String, Offer> offerMapChangeListener;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public OffersModel(TradeManager tradeManager) {
this.tradeManager = tradeManager;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize() {
offerMapChangeListener = change -> {
if (change.wasAdded())
list.add(new OfferListItem(change.getValueAdded()));
else if (change.wasRemoved())
list.removeIf(e -> e.getOfferId().equals(change.getValueRemoved().getId()));
};
super.initialize();
}
@Override
public void activate() {
super.activate();
list.clear();
list.addAll(tradeManager.getOffers().values().stream().map(OfferListItem::new).collect(Collectors.toList()));
tradeManager.getOffers().addListener(offerMapChangeListener);
}
@Override
public void deactivate() {
super.deactivate();
tradeManager.getOffers().removeListener(offerMapChangeListener);
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////////////////////////////
void removeOffer(OfferListItem item) {
tradeManager.removeOffer(item.getOffer());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
public ObservableList<OfferListItem> getList() {
return list;
}
}

View File

@ -0,0 +1,127 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare 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.
*
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.main.orders.offer;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.util.BSFormatter;
import com.google.inject.Inject;
import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OffersPM extends PresentationModel<OffersModel> {
private static final Logger log = LoggerFactory.getLogger(OffersPM.class);
private BSFormatter formatter;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public OffersPM(OffersModel model, BSFormatter formatter) {
super(model);
this.formatter = formatter;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize() {
super.initialize();
}
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
public ObservableList<OfferListItem> getList() {
return model.getList();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////////////////////////////
void removeOffer(OfferListItem item) {
model.removeOffer(item);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
String getTradeId(OfferListItem item) {
return item.getOfferId();
}
String getAmount(OfferListItem item) {
return (item != null) ? BSFormatter.formatAmountWithMinAmount(item.getOffer()) : "";
}
String getPrice(OfferListItem item) {
return (item != null) ? BSFormatter.formatFiat(item.getOffer().getPrice()) : "";
}
String getVolume(OfferListItem item) {
return (item != null) ? BSFormatter.formatVolumeWithMinVolume(item.getOffer()) : "";
}
String getDirectionLabel(OfferListItem item) {
return (item != null) ? BSFormatter.formatDirection(item.getOffer().getMirroredDirection()) : "";
}
String getDate(OfferListItem item) {
return formatter.formatDateTime(item.getOffer().getCreationDate());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
}

View File

@ -17,46 +17,41 @@
~ along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
-->
<?import io.bitsquare.gui.components.TitledSeparator?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.cell.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.orders.offer.OfferController"
spacing="10" xmlns:fx="http://javafx.com/fxml">
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.orders.offer.OffersViewCB"
hgap="5.0" vgap="5"
xmlns:fx="http://javafx.com/fxml">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
<Insets bottom="20.0" left="25.0" top="30.0" right="25"/>
</padding>
<TableView fx:id="offerTable" VBox.vgrow="ALWAYS">
<columns>
<TitledSeparator text="Open offers" GridPane.rowIndex="0" GridPane.columnIndex="0" GridPane.columnSpan="2"/>
<TableColumn text="Offer ID" fx:id="offerIdColumn" minWidth="100" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="offerId"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Date" fx:id="dateColumn" minWidth="100" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="date"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Amount in BTC (Min.)" fx:id="amountColumn" minWidth="70" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="amount"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Price" fx:id="priceColumn" minWidth="70" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="price"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Amount in EUR (Min.)" fx:id="volumeColumn" minWidth="70" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="volume"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="" fx:id="removeColumn" minWidth="50" sortable="false"/>
<TableView fx:id="table" GridPane.rowIndex="0" GridPane.columnIndex="0" GridPane.columnSpan="2">
<GridPane.margin>
<Insets top="10.0" left="-10" right="-10" bottom="-15"/>
</GridPane.margin>
<columns>
<TableColumn text="Offer ID" fx:id="offerIdColumn" minWidth="100" sortable="false"/>
<TableColumn text="Date" fx:id="dateColumn" minWidth="130"/>
<TableColumn text="Amount in BTC (Min.)" fx:id="amountColumn" minWidth="130" sortable="false"/>
<TableColumn text="Price" fx:id="priceColumn" minWidth="80" sortable="false"/>
<TableColumn text="Amount in EUR (Min.)" fx:id="volumeColumn" minWidth="130" sortable="false"/>
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="70" sortable="false"/>
<TableColumn text="" fx:id="removeItemColumn" minWidth="100" sortable="false"/>
</columns>
</TableView>
</VBox>
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/>
<ColumnConstraints hgrow="ALWAYS"/>
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="ALWAYS"/>
</rowConstraints>
</GridPane>

View File

@ -0,0 +1,281 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare 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.
*
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.main.orders.offer;
import io.bitsquare.gui.CachedViewCB;
import java.net.URL;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.util.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OffersViewCB extends CachedViewCB<OffersPM> {
private static final Logger log = LoggerFactory.getLogger(OffersViewCB.class);
@FXML TableColumn<OfferListItem, OfferListItem> priceColumn, amountColumn, volumeColumn,
directionColumn, dateColumn, offerIdColumn, removeItemColumn;
@FXML TableView<OfferListItem> table;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
private OffersViewCB(OffersPM presentationModel) {
super(presentationModel);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb) {
setOfferIdColumnCellFactory();
setDirectionColumnCellFactory();
setAmountColumnCellFactory();
setPriceColumnCellFactory();
setVolumeColumnCellFactory();
setDateColumnCellFactory();
setRemoveColumnCellFactory();
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
super.initialize(url, rb);
}
@Override
public void activate() {
super.activate();
table.setItems(presentationModel.getList());
}
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private Methods
///////////////////////////////////////////////////////////////////////////////////////////
private void removeOffer(OfferListItem item) {
presentationModel.removeOffer(item);
}
private void openOfferDetails(OfferListItem item) {
// TODO Open popup with details view
log.debug("openOfferDetails " + item);
}
///////////////////////////////////////////////////////////////////////////////////////////
// CellFactories
///////////////////////////////////////////////////////////////////////////////////////////
private void setOfferIdColumnCellFactory() {
offerIdColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper(offerListItem.getValue()));
offerIdColumn.setCellFactory(
new Callback<TableColumn<OfferListItem, OfferListItem>, TableCell<OfferListItem, OfferListItem>>() {
@Override
public TableCell<OfferListItem, OfferListItem> call(TableColumn<OfferListItem,
OfferListItem> column) {
return new TableCell<OfferListItem, OfferListItem>() {
Hyperlink hyperlink;
@Override
public void updateItem(final OfferListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
hyperlink = new Hyperlink(presentationModel.getTradeId(item));
Tooltip.install(hyperlink, new Tooltip(presentationModel.getTradeId(item)));
hyperlink.setOnAction(event -> openOfferDetails(item));
setGraphic(hyperlink);
}
else {
setGraphic(null);
setId(null);
}
}
};
}
});
}
private void setDateColumnCellFactory() {
dateColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
dateColumn.setCellFactory(
new Callback<TableColumn<OfferListItem, OfferListItem>, TableCell<OfferListItem,
OfferListItem>>() {
@Override
public TableCell<OfferListItem, OfferListItem> call(
TableColumn<OfferListItem, OfferListItem> column) {
return new TableCell<OfferListItem, OfferListItem>() {
@Override
public void updateItem(final OfferListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null)
setText(presentationModel.getDate(item));
else
setText("");
}
};
}
});
}
private void setAmountColumnCellFactory() {
amountColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
amountColumn.setCellFactory(
new Callback<TableColumn<OfferListItem, OfferListItem>, TableCell<OfferListItem,
OfferListItem>>() {
@Override
public TableCell<OfferListItem, OfferListItem> call(
TableColumn<OfferListItem, OfferListItem> column) {
return new TableCell<OfferListItem, OfferListItem>() {
@Override
public void updateItem(final OfferListItem item, boolean empty) {
super.updateItem(item, empty);
setText(presentationModel.getAmount(item));
}
};
}
});
}
private void setPriceColumnCellFactory() {
priceColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
priceColumn.setCellFactory(
new Callback<TableColumn<OfferListItem, OfferListItem>, TableCell<OfferListItem,
OfferListItem>>() {
@Override
public TableCell<OfferListItem, OfferListItem> call(
TableColumn<OfferListItem, OfferListItem> column) {
return new TableCell<OfferListItem, OfferListItem>() {
@Override
public void updateItem(final OfferListItem item, boolean empty) {
super.updateItem(item, empty);
setText(presentationModel.getPrice(item));
}
};
}
});
}
private void setVolumeColumnCellFactory() {
volumeColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
volumeColumn.setCellFactory(
new Callback<TableColumn<OfferListItem, OfferListItem>, TableCell<OfferListItem,
OfferListItem>>() {
@Override
public TableCell<OfferListItem, OfferListItem> call(
TableColumn<OfferListItem, OfferListItem> column) {
return new TableCell<OfferListItem, OfferListItem>() {
@Override
public void updateItem(final OfferListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null)
setText(presentationModel.getVolume(item));
else
setText("");
}
};
}
});
}
private void setDirectionColumnCellFactory() {
directionColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
directionColumn.setCellFactory(
new Callback<TableColumn<OfferListItem, OfferListItem>, TableCell<OfferListItem,
OfferListItem>>() {
@Override
public TableCell<OfferListItem, OfferListItem> call(
TableColumn<OfferListItem, OfferListItem> column) {
return new TableCell<OfferListItem, OfferListItem>() {
@Override
public void updateItem(final OfferListItem item, boolean empty) {
super.updateItem(item, empty);
setText(presentationModel.getDirectionLabel(item));
}
};
}
});
}
private void setRemoveColumnCellFactory() {
removeItemColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper(offerListItem.getValue()));
removeItemColumn.setCellFactory(
new Callback<TableColumn<OfferListItem, OfferListItem>, TableCell<OfferListItem, OfferListItem>>() {
@Override
public TableCell<OfferListItem, OfferListItem> call(TableColumn<OfferListItem,
OfferListItem> directionColumn) {
return new TableCell<OfferListItem, OfferListItem>() {
final ImageView iconView = new ImageView();
final Button button = new Button();
{
iconView.setId("image-remove");
button.setText("Remove");
button.setGraphic(iconView);
button.setMinWidth(70);
}
@Override
public void updateItem(final OfferListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
button.setOnAction(event -> removeOffer(item));
setGraphic(button);
}
else {
setGraphic(null);
}
}
};
}
});
}
}

View File

@ -55,6 +55,7 @@ class PendingTradesModel extends UIModel {
private PendingTradesListItem selectedItem;
private boolean isOfferer;
private Trade closedTrade;
private TxConfidenceListener txConfidenceListener;
private ChangeListener<Trade.State> stateChangeListener;
@ -88,10 +89,13 @@ class PendingTradesModel extends UIModel {
faultChangeListener = (ov, oldValue, newValue) -> fault.set(newValue);
mapChangeListener = change -> {
log.debug("######## " + change);
log.debug("######## " + change.getValueAdded());
log.debug("######## " + change.getValueRemoved());
if (change.wasAdded())
list.add(new PendingTradesListItem(change.getValueAdded()));
else if (change.wasRemoved())
list.remove(new PendingTradesListItem(change.getValueRemoved()));
closedTrade = change.getValueRemoved();
};
super.initialize();
@ -103,10 +107,9 @@ class PendingTradesModel extends UIModel {
list.clear();
// transform trades to list of PendingTradesListItems and keep it updated
tradeManager.getTrades().values().stream()
.filter(e -> e.getState() != Trade.State.CLOSED)
tradeManager.getPendingTrades().values().stream()
.forEach(e -> list.add(new PendingTradesListItem(e)));
tradeManager.getTrades().addListener(mapChangeListener);
tradeManager.getPendingTrades().addListener(mapChangeListener);
// we sort by date
list.sort((o1, o2) -> o2.getTrade().getDate().compareTo(o1.getTrade().getDate()));
@ -117,18 +120,17 @@ class PendingTradesModel extends UIModel {
tradeManager.getCurrentPendingTrade().getId().equals(e.getTrade().getId()))
.findFirst();
if (currentTradeItemOptional.isPresent())
selectPendingTrade(currentTradeItemOptional.get());
selectTrade(currentTradeItemOptional.get());
else if (list.size() > 0)
selectPendingTrade(list.get(0));
selectTrade(list.get(0));
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
tradeManager.getTrades().removeListener(mapChangeListener);
selectPendingTrade(null);
tradeManager.getPendingTrades().removeListener(mapChangeListener);
selectTrade(null);
}
@SuppressWarnings("EmptyMethod")
@ -142,7 +144,7 @@ class PendingTradesModel extends UIModel {
// Methods
///////////////////////////////////////////////////////////////////////////////////////////
void selectPendingTrade(PendingTradesListItem item) {
void selectTrade(PendingTradesListItem item) {
// clean up previous selectedItem
if (selectedItem != null) {
Trade trade = getTrade();
@ -162,7 +164,8 @@ class PendingTradesModel extends UIModel {
tradeState.set(null);
Trade trade = getTrade();
txId.set(trade.getDepositTx().getHashAsString());
if (trade.getDepositTx() != null)
txId.set(trade.getDepositTx().getHashAsString());
txConfidenceListener = new TxConfidenceListener(txId.get()) {
@Override
@ -178,6 +181,11 @@ class PendingTradesModel extends UIModel {
trade.faultProperty().addListener(faultChangeListener);
fault.set(trade.faultProperty().get());
if (closedTrade != null) {
list.removeIf(e -> e.getTrade().getId().equals(closedTrade.getId()));
closedTrade = null;
}
}
else {
txId.set(null);
@ -193,6 +201,12 @@ class PendingTradesModel extends UIModel {
tradeManager.fiatPaymentReceived(getTrade().getId());
}
void closeSummary() {
if (closedTrade != null) {
list.removeIf(e -> e.getTrade().getId().equals(closedTrade.getId()));
closedTrade = null;
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters

View File

@ -30,7 +30,6 @@ import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList;
import javafx.collections.transformation.SortedList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -113,8 +112,8 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
// Methods
///////////////////////////////////////////////////////////////////////////////////////////
void selectPendingTrade(PendingTradesListItem item) {
model.selectPendingTrade(item);
void selectTrade(PendingTradesListItem item) {
model.selectTrade(item);
}
void fiatPaymentStarted() {
@ -125,13 +124,16 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
model.fiatPaymentReceived();
}
void closeSummary() {
model.closeSummary();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
ObservableList<PendingTradesListItem> getList() {
return new SortedList<>(model.getList());
return model.getList();
}
boolean isOfferer() {
@ -146,6 +148,11 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
return model.getSelectedItem();
}
// columns
String getTradeId(PendingTradesListItem item) {
return item.getTrade().getId();
}
String getAmount(PendingTradesListItem item) {
return (item != null) ? BSFormatter.formatAmountWithMinAmount(item.getTrade().getOffer()) : "";
}
@ -162,6 +169,11 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
return (item != null) ? BSFormatter.formatDirection(item.getTrade().getOffer().getMirroredDirection()) : "";
}
String getDate(PendingTradesListItem item) {
return formatter.formatDateTime(item.getTrade().getDate());
}
// payment
String getPaymentMethod() {
return BSResources.get(model.getTrade().getContract().getTakerBankAccount().getBankAccountType().toString());
}
@ -178,14 +190,7 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
return model.getTrade().getContract().getTakerBankAccount().getAccountSecondaryID();
}
String getDate(PendingTradesListItem item) {
return formatter.formatDateTime(item.getTrade().getDate());
}
String getTradeId(PendingTradesListItem item) {
return item.getTrade().getId();
}
// summary
String getTradeVolume() {
return formatter.formatCoinWithCode(model.getTrade().getTradeAmount());
}
@ -221,11 +226,10 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
state.set(model.isOfferer() ? State.OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED :
State.TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT);
break;
case PAYMENT_RECEIVED:
case PAYOUT_PUBLISHED:
case COMPLETED:
state.set(model.isOfferer() ? State.OFFERER_BUYER_COMPLETED : State.TAKER_SELLER_COMPLETED);
break;
case FAULT:
case FAILED:
// TODO
break;
default:

View File

@ -48,7 +48,7 @@
<TableColumn text="Price" fx:id="priceColumn" minWidth="100" sortable="false"/>
<TableColumn text="Amount in EUR (Min.)" fx:id="volumeColumn" minWidth="130" sortable="false"/>
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="80" sortable="false"/>
<TableColumn fx:id="selectColumn" minWidth="60" sortable="false" text=""/>
<TableColumn text="" fx:id="selectColumn" minWidth="60" sortable="false"/>
</columns>
</TableView>
@ -142,7 +142,7 @@
<Label fx:id="btcLabel" GridPane.rowIndex="5" visible="false">
<GridPane.margin>
<Insets top="60.0"/>
<Insets top="60.0"/>
</GridPane.margin>
</Label>
<TextField fx:id="btcTextField" GridPane.rowIndex="5" GridPane.columnIndex="1" editable="false"
@ -165,6 +165,13 @@
<InfoDisplay fx:id="summaryInfoDisplay" onAction="#onOpenSummaryHelp" rowIndex="9" gridPane="$root"
visible="false"/>
<Button fx:id="closeSummaryButton" text="Close summary" onAction="#onCloseSummary" GridPane.rowIndex="10"
GridPane.columnIndex="1" defaultButton="true" visible="false">
<GridPane.margin>
<Insets top="15"/>
</GridPane.margin>
</Button>
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/>
<ColumnConstraints hgrow="ALWAYS"/>
@ -182,6 +189,7 @@
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
</rowConstraints>
</GridPane>

View File

@ -56,7 +56,7 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
collateralTextField;
@FXML TxIdTextField txIdTextField;
@FXML InfoDisplay infoDisplay, paymentsInfoDisplay, summaryInfoDisplay;
@FXML Button confirmPaymentReceiptButton, paymentsButton;
@FXML Button confirmPaymentReceiptButton, paymentsButton, closeSummaryButton;
@FXML TextFieldWithCopyIcon holderNameTextField, secondaryIdTextField, primaryIdTextField;
@FXML TableView<PendingTradesListItem> table;
@FXML TableColumn<PendingTradesListItem, PendingTradesListItem> priceColumn, amountColumn, volumeColumn,
@ -102,7 +102,7 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
selectedItemChangeListener = (obsValue, oldValue, newValue) -> {
if (oldValue != newValue) {
if (oldValue != null && newValue != null)
presentationModel.selectPendingTrade(newValue);
presentationModel.selectTrade(newValue);
else if (newValue == null)
table.getSelectionModel().clearSelection();
}
@ -180,6 +180,12 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
presentationModel.fiatPaymentReceived();
}
@FXML
void onCloseSummary() {
presentationModel.closeSummary();
setSummaryControlsVisible(false);
}
@FXML
void onOpenHelp() {
Help.openWindow(presentationModel.isOfferer() ? HelpId.PENDING_TRADE_OFFERER : HelpId.PENDING_TRADE_TAKER);
@ -367,7 +373,13 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
private void onFault(Throwable fault) {
// TODO
log.error(fault.toString());
if (fault != null)
log.error(fault.toString());
}
private void openOfferDetails(PendingTradesListItem item) {
// TODO Open popup with details view
log.debug("Trade details " + item);
}
private void setPaymentsControlsVisible(boolean visible) {
@ -395,6 +407,7 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
collateralLabel.setVisible(visible);
collateralTextField.setVisible(visible);
summaryInfoDisplay.setVisible(visible);
closeSummaryButton.setVisible(visible);
}
@ -402,6 +415,39 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
// CellFactories
///////////////////////////////////////////////////////////////////////////////////////////
private void setTradeIdColumnCellFactory() {
tradeIdColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper(offerListItem.getValue()));
tradeIdColumn.setCellFactory(
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>,
TableCell<PendingTradesListItem, PendingTradesListItem>>() {
@Override
public TableCell<PendingTradesListItem, PendingTradesListItem> call
(TableColumn<PendingTradesListItem,
PendingTradesListItem> column) {
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
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));
Tooltip.install(hyperlink, new Tooltip(presentationModel.getTradeId(item)));
hyperlink.setOnAction(event -> openOfferDetails(item));
setGraphic(hyperlink);
}
else {
setGraphic(null);
setId(null);
}
}
};
}
});
}
private void setDateColumnCellFactory() {
dateColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
dateColumn.setCellFactory(
@ -424,32 +470,6 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
});
}
private void setTradeIdColumnCellFactory() {
tradeIdColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
tradeIdColumn.setCellFactory(
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>, TableCell<PendingTradesListItem,
PendingTradesListItem>>() {
@Override
public TableCell<PendingTradesListItem, PendingTradesListItem> call(
TableColumn<PendingTradesListItem, PendingTradesListItem> column) {
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
@Override
public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(presentationModel.getTradeId(item));
Tooltip.install(this, new Tooltip(presentationModel.getTradeId(item)));
}
else {
setText("");
}
}
};
}
});
}
private void setAmountColumnCellFactory() {
amountColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
amountColumn.setCellFactory(
@ -559,5 +579,7 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
}
});
}
}

View File

@ -127,8 +127,6 @@ class CreateOfferModel extends UIModel {
@Override
public void initialize() {
super.initialize();
// static data
offerFeeAsCoin.set(FeePolicy.CREATE_OFFER_FEE);
networkFeeAsCoin.set(FeePolicy.TX_FEE);
@ -153,6 +151,11 @@ class CreateOfferModel extends UIModel {
if (settings != null)
btcCode.bind(settings.btcDenominationProperty());
// we need to set it here already as initWithData is called before activate
collateralAsLong.set(settings.getCollateral());
super.initialize();
}
@Override
@ -161,7 +164,9 @@ class CreateOfferModel extends UIModel {
// might be changed after screen change
if (settings != null) {
// set it here again to cover the case of an collateral change after a screen change
collateralAsLong.set(settings.getCollateral());
acceptedCountries.setAll(settings.getAcceptedCountries());
acceptedLanguages.setAll(settings.getAcceptedLanguageLocales());
acceptedArbitrators.setAll(settings.getAcceptedArbitrators());

View File

@ -157,16 +157,24 @@ class CreateOfferPM extends PresentationModel<CreateOfferModel> {
directionLabel.set(model.getDirection() == Direction.BUY ? BSResources.get("shared.buy") : BSResources.get
("shared.sell"));
// apply only if valid
// apply only if valid
boolean amountValid = false;
if (amount != null && isBtcInputValid(amount.toPlainString())
.isValid) {
model.amountAsCoin.set(amount);
model.minAmountAsCoin.set(amount);
amountValid = true;
}
// apply only if valid
if (price != null && isBtcInputValid(price.toPlainString()).isValid)
boolean priceValid = false;
if (price != null && isBtcInputValid(price.toPlainString()).isValid) {
model.priceAsFiat.set(parseToFiatWith2Decimals(price.toPlainString()));
priceValid = true;
}
if (amountValid && priceValid)
model.calculateTotalToPay();
}

View File

@ -160,7 +160,7 @@ class TakeOfferModel extends UIModel {
transactionId.set(trade.getDepositTx().getHashAsString());
requestTakeOfferSuccess.set(true);
break;
case FAULT:
case FAILED:
requestTakeOfferErrorMessage.set("An error occurred. Error: " + trade.getFault().getMessage());
break;
case OFFERER_REJECTED:

View File

@ -46,10 +46,8 @@ public class Trade implements Serializable {
DEPOSIT_PUBLISHED,
DEPOSIT_CONFIRMED,
PAYMENT_STARTED,
PAYMENT_RECEIVED, /* For taker only*/
PAYOUT_PUBLISHED,
FAULT,
CLOSED
FAILED,
COMPLETED
}

View File

@ -83,7 +83,8 @@ public class TradeManager {
private final Map<String, CreateOfferCoordinator> createOfferCoordinatorMap = new HashMap<>();
private final ObservableMap<String, Offer> offers = FXCollections.observableHashMap();
private final ObservableMap<String, Trade> trades = FXCollections.observableHashMap();
private final ObservableMap<String, Trade> pendingTrades = FXCollections.observableHashMap();
private final ObservableMap<String, Trade> closedTrades = FXCollections.observableHashMap();
// the latest pending trade
private Trade currentPendingTrade;
@ -109,9 +110,14 @@ public class TradeManager {
offers.putAll((Map<String, Offer>) offersObject);
}
Object tradesObject = persistence.read(this, "trades");
if (tradesObject instanceof HashMap) {
trades.putAll((Map<String, Trade>) tradesObject);
Object pendingTradesObject = persistence.read(this, "pendingTrades");
if (pendingTradesObject instanceof HashMap) {
pendingTrades.putAll((Map<String, Trade>) pendingTradesObject);
}
Object closedTradesObject = persistence.read(this, "closedTrades");
if (closedTradesObject instanceof HashMap) {
closedTrades.putAll((Map<String, Trade>) closedTradesObject);
}
messageFacade.addIncomingTradeMessageListener(this::onIncomingTradeMessage);
@ -210,22 +216,25 @@ public class TradeManager {
///////////////////////////////////////////////////////////////////////////////////////////
public Trade createTrade(Offer offer) {
if (trades.containsKey(offer.getId()))
if (pendingTrades.containsKey(offer.getId()))
log.error("trades contains already an trade with the ID " + offer.getId());
Trade trade = new Trade(offer);
trades.put(offer.getId(), trade);
persistTrades();
pendingTrades.put(offer.getId(), trade);
persistPendingTrades();
return trade;
}
public void removeTrade(Trade trade) {
if (!trades.containsKey(trade.getId()))
public void closeTrade(Trade trade) {
if (!pendingTrades.containsKey(trade.getId()))
log.error("trades does not contain the trade with the ID " + trade.getId());
trades.remove(trade.getId());
persistTrades();
pendingTrades.remove(trade.getId());
persistPendingTrades();
closedTrades.put(trade.getId(), trade);
persistClosedTrades();
}
@ -252,7 +261,7 @@ public class TradeManager {
@Override
public void onOfferAccepted(Offer offer) {
trade.setState(Trade.State.OFFERER_ACCEPTED);
persistTrades();
persistPendingTrades();
removeOffer(offer);
}
@ -260,7 +269,7 @@ public class TradeManager {
public void onDepositTxPublished(Transaction depositTx) {
trade.setDepositTx(depositTx);
trade.setState(Trade.State.DEPOSIT_PUBLISHED);
persistTrades();
persistPendingTrades();
log.trace("trading onDepositTxPublishedMessage " + depositTx.getHashAsString());
}
@ -268,14 +277,15 @@ public class TradeManager {
public void onDepositTxConfirmedInBlockchain() {
log.trace("trading onDepositTxConfirmedInBlockchain");
trade.setState(Trade.State.DEPOSIT_CONFIRMED);
persistTrades();
persistPendingTrades();
}
@Override
public void onPayoutTxPublished(Transaction payoutTx) {
trade.setPayoutTx(payoutTx);
trade.setState(Trade.State.PAYOUT_PUBLISHED);
persistTrades();
trade.setState(Trade.State.COMPLETED);
closeTrade(trade);
log.debug("trading onPayoutTxPublishedMessage");
}
@ -283,8 +293,8 @@ public class TradeManager {
public void onFault(Throwable throwable, BuyerAcceptsOfferProtocol.State state) {
log.error("Error while executing trade process at state: " + state + " / " + throwable);
trade.setFault(throwable);
trade.setState(Trade.State.FAULT);
persistTrades();
trade.setState(Trade.State.FAILED);
persistPendingTrades();
}
// probably not needed
@ -325,33 +335,33 @@ public class TradeManager {
@Override
public void onTakeOfferRequestAccepted(Trade trade) {
trade.setState(Trade.State.OFFERER_ACCEPTED);
persistTrades();
persistPendingTrades();
}
@Override
public void onTakeOfferRequestRejected(Trade trade) {
trade.setState(Trade.State.OFFERER_REJECTED);
persistTrades();
persistPendingTrades();
}
@Override
public void onDepositTxPublished(Transaction depositTx) {
trade.setDepositTx(depositTx);
trade.setState(Trade.State.DEPOSIT_PUBLISHED);
persistTrades();
persistPendingTrades();
}
@Override
public void onBankTransferInited(String tradeId) {
trade.setState(Trade.State.PAYMENT_STARTED);
persistTrades();
persistPendingTrades();
}
@Override
public void onPayoutTxPublished(Trade trade, Transaction payoutTx) {
trade.setState(Trade.State.PAYOUT_PUBLISHED);
trade.setPayoutTx(payoutTx);
persistTrades();
trade.setState(Trade.State.COMPLETED);
closeTrade(trade);
}
@Override
@ -364,12 +374,6 @@ public class TradeManager {
public void onWaitingForPeerResponse(SellerTakesOfferProtocol.State state) {
}
@Override
public void onCompleted(SellerTakesOfferProtocol.State state) {
trade.setState(Trade.State.PAYMENT_RECEIVED);
persistTrades();
}
};
SellerTakesOfferProtocol sellerTakesOfferProtocol = new SellerTakesOfferProtocol(
@ -387,8 +391,8 @@ public class TradeManager {
public void fiatPaymentStarted(String tradeId) {
if (offererAsBuyerProtocolMap.get(tradeId) != null) {
offererAsBuyerProtocolMap.get(tradeId).onUIEventBankTransferInited();
trades.get(tradeId).setState(Trade.State.PAYMENT_STARTED);
persistTrades();
pendingTrades.get(tradeId).setState(Trade.State.PAYMENT_STARTED);
persistPendingTrades();
}
else {
// For usability tests we don't want to crash
@ -402,8 +406,6 @@ public class TradeManager {
public void fiatPaymentReceived(String tradeId) {
takerAsSellerProtocolMap.get(tradeId).onUIEventFiatReceived();
trades.get(tradeId).setState(Trade.State.PAYMENT_RECEIVED);
persistTrades();
}
///////////////////////////////////////////////////////////////////////////////////////////
@ -436,7 +438,7 @@ public class TradeManager {
(RequestOffererPublishDepositTxMessage) tradeMessage);
}
else if (tradeMessage instanceof DepositTxPublishedMessage) {
persistTrades();
persistPendingTrades();
takerAsSellerProtocolMap.get(tradeId).onDepositTxPublishedMessage((DepositTxPublishedMessage) tradeMessage);
}
else if (tradeMessage instanceof BankTransferInitedMessage) {
@ -453,7 +455,7 @@ public class TradeManager {
///////////////////////////////////////////////////////////////////////////////////////////
public boolean isOfferAlreadyInTrades(Offer offer) {
return trades.containsKey(offer.getId());
return pendingTrades.containsKey(offer.getId());
}
@ -461,16 +463,16 @@ public class TradeManager {
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
public ObservableMap<String, Trade> getTrades() {
return trades;
}
public Map<String, Offer> getOffers() {
public ObservableMap<String, Offer> getOffers() {
return offers;
}
public Offer getOffer(String offerId) {
return offers.get(offerId);
public ObservableMap<String, Trade> getPendingTrades() {
return pendingTrades;
}
public ObservableMap<String, Trade> getClosedTrades() {
return closedTrades;
}
public Trade getCurrentPendingTrade() {
@ -486,14 +488,19 @@ public class TradeManager {
persistence.write(this, "offers", (Map<String, Offer>) new HashMap<>(offers));
}
private void persistTrades() {
persistence.write(this, "trades", (Map<String, Trade>) new HashMap<>(trades));
private void persistPendingTrades() {
persistence.write(this, "pendingTrades", (Map<String, Trade>) new HashMap<>(pendingTrades));
}
private void persistClosedTrades() {
persistence.write(this, "closedTrades", (Map<String, Trade>) new HashMap<>(closedTrades));
}
@Nullable
public Trade getTrade(String tradeId) {
if (trades.containsKey(tradeId)) {
return trades.get(tradeId);
if (pendingTrades.containsKey(tradeId)) {
return pendingTrades.get(tradeId);
}
else {
return null;

View File

@ -392,7 +392,6 @@ public class SellerTakesOfferProtocol {
public void onResultSendPayoutTxToOfferer() {
log.debug("onResultSendPayoutTxToOfferer called " + step++);
listener.onCompleted(state);
}

View File

@ -32,8 +32,6 @@ public interface SellerTakesOfferProtocolListener {
void onWaitingForPeerResponse(SellerTakesOfferProtocol.State state);
void onCompleted(SellerTakesOfferProtocol.State state);
void onTakeOfferRequestAccepted(Trade trade);
void onTakeOfferRequestRejected(Trade trade);