/*
* 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.market.spread;
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
import io.bitsquare.gui.common.view.FxmlView;
import io.bitsquare.gui.components.TableGroupHeadline;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.CurrencyUtil;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.ListChangeListener;
import javafx.collections.transformation.SortedList;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.util.Callback;
import org.bitcoinj.core.Coin;
import javax.inject.Inject;
@FxmlView
public class SpreadView extends ActivatableViewAndModel<GridPane, SpreadViewModel> {
private final BSFormatter formatter;
private final int gridRow = 0;
private TableView<SpreadItem> tableView;
private SortedList<SpreadItem> sortedList;
private ListChangeListener<SpreadItem> itemListChangeListener;
private TableColumn<SpreadItem, SpreadItem> totalAmountColumn, numberOfOffersColumn, numberOfBuyOffersColumn, numberOfSellOffersColumn;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public SpreadView(SpreadViewModel model, BSFormatter formatter) {
super(model);
this.formatter = formatter;
}
@Override
public void initialize() {
TableGroupHeadline header = new TableGroupHeadline("Statistics");
GridPane.setRowIndex(header, gridRow);
GridPane.setMargin(header, new Insets(0, -10, -10, -10));
root.getChildren().add(header);
tableView = new TableView<>();
GridPane.setRowIndex(tableView, gridRow);
GridPane.setMargin(tableView, new Insets(20, -10, -10, -10));
GridPane.setVgrow(tableView, Priority.ALWAYS);
GridPane.setHgrow(tableView, Priority.ALWAYS);
root.getChildren().add(tableView);
Label placeholder = new Label("Currently there is no data available");
placeholder.setWrapText(true);
tableView.setPlaceholder(placeholder);
TableColumn<SpreadItem, SpreadItem> currencyColumn = getCurrencyColumn();
tableView.getColumns().add(currencyColumn);
numberOfOffersColumn = getNumberOfOffersColumn();
tableView.getColumns().add(numberOfOffersColumn);
numberOfBuyOffersColumn = getNumberOfBuyOffersColumn();
tableView.getColumns().add(numberOfBuyOffersColumn);
numberOfSellOffersColumn = getNumberOfSellOffersColumn();
tableView.getColumns().add(numberOfSellOffersColumn);
totalAmountColumn = getTotalAmountColumn();
tableView.getColumns().add(totalAmountColumn);
TableColumn<SpreadItem, SpreadItem> spreadColumn = getSpreadColumn();
tableView.getColumns().add(spreadColumn);
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
currencyColumn.setComparator((o1, o2) -> CurrencyUtil.getNameByCode(o1.currencyCode).compareTo(CurrencyUtil.getNameByCode(o2.currencyCode)));
numberOfOffersColumn.setComparator((o1, o2) -> Integer.valueOf(o1.numberOfOffers).compareTo(o2.numberOfOffers));
numberOfBuyOffersColumn.setComparator((o1, o2) -> Integer.valueOf(o1.numberOfBuyOffers).compareTo(o2.numberOfBuyOffers));
numberOfSellOffersColumn.setComparator((o1, o2) -> Integer.valueOf(o1.numberOfSellOffers).compareTo(o2.numberOfSellOffers));
totalAmountColumn.setComparator((o1, o2) -> o1.totalAmount.compareTo(o2.totalAmount));
spreadColumn.setComparator((o1, o2) -> o1.spread != null && o2.spread != null ? formatter.formatVolumeWithCode(o1.spread).compareTo(formatter.formatVolumeWithCode(o2.spread)) : 0);
numberOfOffersColumn.setSortType(TableColumn.SortType.DESCENDING);
tableView.getSortOrder().add(numberOfOffersColumn);
itemListChangeListener = c -> updateHeaders();
}
@Override
protected void activate() {
sortedList = new SortedList<>(model.spreadItems);
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
tableView.setItems(sortedList);
sortedList.addListener(itemListChangeListener);
updateHeaders();
}
@Override
protected void deactivate() {
sortedList.comparatorProperty().unbind();
sortedList.removeListener(itemListChangeListener);
}
private void updateHeaders() {
numberOfOffersColumn.setText("All offers (" + sortedList.stream().mapToInt(item -> item.numberOfOffers).sum() + ")");
numberOfBuyOffersColumn.setText("Buy BTC (" + sortedList.stream().mapToInt(item -> item.numberOfBuyOffers).sum() + ")");
numberOfSellOffersColumn.setText("Sell BTC (" + sortedList.stream().mapToInt(item -> item.numberOfSellOffers).sum() + ")");
totalAmountColumn.setText("Total BTC (" + formatter.formatCoin(Coin.valueOf(sortedList.stream().mapToLong(item -> item.totalAmount.value).sum())) + ")");
}
///////////////////////////////////////////////////////////////////////////////////////////
// Columns
///////////////////////////////////////////////////////////////////////////////////////////
private TableColumn<SpreadItem, SpreadItem> getCurrencyColumn() {
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Currency") {
{
setMinWidth(160); //110
}
};
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
column.setCellFactory(
new Callback<TableColumn<SpreadItem, SpreadItem>, TableCell<SpreadItem,
SpreadItem>>() {
@Override
public TableCell<SpreadItem, SpreadItem> call(
TableColumn<SpreadItem, SpreadItem> column) {
return new TableCell<SpreadItem, SpreadItem>() {
@Override
public void updateItem(final SpreadItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(CurrencyUtil.getNameAndCode(item.currencyCode));
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SpreadItem, SpreadItem> getNumberOfOffersColumn() {
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Total offers") {
{
setMinWidth(100);
}
};
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
column.setCellFactory(
new Callback<TableColumn<SpreadItem, SpreadItem>, TableCell<SpreadItem,
SpreadItem>>() {
@Override
public TableCell<SpreadItem, SpreadItem> call(
TableColumn<SpreadItem, SpreadItem> column) {
return new TableCell<SpreadItem, SpreadItem>() {
@Override
public void updateItem(final SpreadItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(String.valueOf(item.numberOfOffers));
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SpreadItem, SpreadItem> getNumberOfBuyOffersColumn() {
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Buy offers") {
{
setMinWidth(100);
}
};
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
column.setCellFactory(
new Callback<TableColumn<SpreadItem, SpreadItem>, TableCell<SpreadItem,
SpreadItem>>() {
@Override
public TableCell<SpreadItem, SpreadItem> call(
TableColumn<SpreadItem, SpreadItem> column) {
return new TableCell<SpreadItem, SpreadItem>() {
@Override
public void updateItem(final SpreadItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(String.valueOf(item.numberOfBuyOffers));
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SpreadItem, SpreadItem> getNumberOfSellOffersColumn() {
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Sell offers") {
{
setMinWidth(100);
}
};
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
column.setCellFactory(
new Callback<TableColumn<SpreadItem, SpreadItem>, TableCell<SpreadItem,
SpreadItem>>() {
@Override
public TableCell<SpreadItem, SpreadItem> call(
TableColumn<SpreadItem, SpreadItem> column) {
return new TableCell<SpreadItem, SpreadItem>() {
@Override
public void updateItem(final SpreadItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(String.valueOf(item.numberOfSellOffers));
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SpreadItem, SpreadItem> getTotalAmountColumn() {
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Total amount") {
{
setMinWidth(140); //170
}
};
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
column.setCellFactory(
new Callback<TableColumn<SpreadItem, SpreadItem>, TableCell<SpreadItem,
SpreadItem>>() {
@Override
public TableCell<SpreadItem, SpreadItem> call(
TableColumn<SpreadItem, SpreadItem> column) {
return new TableCell<SpreadItem, SpreadItem>() {
@Override
public void updateItem(final SpreadItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(formatter.formatCoin(item.totalAmount));
else
setText("");
}
};
}
});
return column;
}
private TableColumn<SpreadItem, SpreadItem> getSpreadColumn() {
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Spread") {
{
setMinWidth(110); //130
}
};
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
column.setCellFactory(
new Callback<TableColumn<SpreadItem, SpreadItem>, TableCell<SpreadItem,
SpreadItem>>() {
@Override
public TableCell<SpreadItem, SpreadItem> call(
TableColumn<SpreadItem, SpreadItem> column) {
return new TableCell<SpreadItem, SpreadItem>() {
@Override
public void updateItem(final SpreadItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
if (item.spread != null)
setText(formatter.formatVolumeWithCode(item.spread) + item.percentage);
else
setText("-");
} else {
setText("");
}
}
};
}
});
return column;
}
}