Use colors for buy/sell, redesign offerbook, market overview

This commit is contained in:
Manfred Karrer 2016-02-21 22:03:37 +01:00
parent daa41d222a
commit ca20de64d9
18 changed files with 284 additions and 134 deletions

View File

@ -54,8 +54,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
@JsonExclude
private static final Logger log = LoggerFactory.getLogger(Offer.class);
// public static final long TTL = TimeUnit.SECONDS.toMillis(60);
public static final long TTL = TimeUnit.SECONDS.toMillis(10); //TODO
public static final long TTL = TimeUnit.SECONDS.toMillis(60);
// public static final long TTL = TimeUnit.SECONDS.toMillis(10); //TODO
public final static String TAC_OFFERER = "When placing that offer I accept that anyone who fulfills my conditions can " +
"take that offer.";

View File

@ -30,14 +30,40 @@ bg color of non edit textFields: fafafa
-bs-very-light-grey: #f8f8f8;
-fx-accent: #0f87c3;
-bs-blue-soft: derive(-fx-accent, 60%);
-bs-blue-transparent: #0f87c344;
-bs-green: #00aa33;
-bs-green-soft: derive(-bs-green, 60%);
-bs-green-transparent: #00aa3344;
-bs-error-red: #dd0000;
-bs-red-soft: derive(-bs-error-red, 60%);
-bs-orange: #dd8f05;
-bs-blue-transparent: #0f87c344;
-bs-green-transparent: #00aa3344;
-bs-orange: #ff8a2b;
-bs-yellow: #ffb60f;
-bs-turquoise: #2cacaf;
-bs-turquoise2: #1c9099;
-bs-brown: #52321b;
-bs-dark-blue: #0b456d;
-bs-dark-green: #708614;
-bs-fresh-green: #b7d042;
-bs-ocher: #de9d2c;
-bs-light-blue: #c4eef2;
-bs-smooth-red: #ed7157;
-bs-soft-red: #fe5e1c;
-bs-soft-red2: #f35e1c;
-bs-warning: -bs-orange;
-bs-buy: -bs-yellow;
-bs-buy-dark: derive(-bs-buy, -10%);
-bs-buy-transparent: derive(-bs-buy, 95%);
-bs-sell: -bs-turquoise;
-bs-sell-dark: derive(-bs-sell, -10%);
-bs-sell-transparent: derive(-bs-sell, 95%);
-fx-default-button: derive(-fx-accent, 95%);
-fx-focus-color: -fx-accent;
@ -625,7 +651,7 @@ textfield */
#open-support-button {
-fx-font-weight: bold;
-fx-font-size: 14;
-fx-base: -bs-orange;
-fx-base: -bs-warning;
}
#open-dispute-button {
@ -783,7 +809,7 @@ textfield */
/********************************************************************************************************************
*
* Chart
* Market overview
*
********************************************************************************************************************/
@ -801,27 +827,27 @@ textfield */
}
#charts .default-color0.chart-area-symbol {
-fx-background-color: -bs-green, white;
-fx-background-color: -bs-sell, white;
}
#charts .default-color1.chart-area-symbol {
-fx-background-color: -fx-accent, white;
-fx-background-color: -bs-buy, white;
}
#charts .default-color0.chart-series-area-line {
-fx-stroke: -bs-green;
-fx-stroke: -bs-sell;
}
#charts .default-color1.chart-series-area-line {
-fx-stroke: -fx-accent;
-fx-stroke: -bs-buy;
}
#charts .default-color0.chart-series-area-fill {
-fx-fill: -bs-green-transparent;
-fx-fill: -bs-sell-transparent;
}
#charts .default-color1.chart-series-area-fill {
-fx-fill: -bs-blue-transparent;
-fx-fill: -bs-buy-transparent;
}
#charts .axis-label {
@ -829,6 +855,69 @@ textfield */
-fx-alignment: center;
}
/********************************************************************************************************************
*
* Rounded buttons
*
********************************************************************************************************************/
#buy-button-big {
-fx-base: -bs-buy;
-fx-text-fill: white;
-fx-font-weight: bold;
-fx-font-size: 15;
-fx-background-radius: 20;
}
#buy-button-big:hover {
-fx-base: -bs-buy-dark;
}
#sell-button-big {
-fx-base: -bs-sell;
-fx-text-fill: white;
-fx-font-weight: bold;
-fx-font-size: 15;
-fx-background-radius: 20;
}
#sell-button-big:hover {
-fx-base: -bs-sell-dark;
}
#buy-button {
-fx-base: -bs-buy;
-fx-text-fill: white;
-fx-font-weight: bold;
-fx-background-radius: 13;
}
#buy-button:hover {
-fx-base: -bs-buy-dark;
}
#sell-button {
-fx-base: -bs-sell;
-fx-text-fill: white;
-fx-font-weight: bold;
-fx-background-radius: 13;
}
#sell-button:hover {
-fx-base: -bs-sell-dark;
}
#cancel-button {
-fx-base: -bs-light-grey;
-fx-text-fill: white;
-fx-font-weight: bold;
-fx-background-radius: 13;
}
#cancel-button:hover {
-fx-base: derive(-bs-light-grey, -10%);
}
/********************************************************************************************************************
*
* Popups

View File

@ -30,10 +30,19 @@
-fx-image: url("../../../images/buy.png");
}
#image-buy-white {
-fx-image: url("../../../images/buy_white.png");
}
#image-sell {
-fx-image: url("../../../images/sell.png");
}
#image-sell-white {
-fx-image: url("../../../images/sell_white.png");
}
#image-expand {
-fx-image: url("../../../images/expand.png");
}

View File

@ -18,7 +18,7 @@
package io.bitsquare.gui.main.markets.charts;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.util.Tuple2;
import io.bitsquare.common.util.Tuple3;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
import io.bitsquare.gui.common.view.FxmlView;
@ -105,8 +105,8 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
createChart();
Tuple2<TableView<Offer>, VBox> tupleBuy = getOfferTable(Offer.Direction.BUY);
Tuple2<TableView<Offer>, VBox> tupleSell = getOfferTable(Offer.Direction.SELL);
Tuple3<TableView<Offer>, VBox, Button> tupleBuy = getOfferTable(Offer.Direction.BUY);
Tuple3<TableView<Offer>, VBox, Button> tupleSell = getOfferTable(Offer.Direction.SELL);
buyOfferTableView = tupleBuy.first;
sellOfferTableView = tupleSell.first;
@ -152,7 +152,7 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
}
private Tuple2<TableView<Offer>, VBox> getOfferTable(Offer.Direction direction) {
private Tuple3<TableView<Offer>, VBox, Button> getOfferTable(Offer.Direction direction) {
TableView<Offer> tableView = new TableView<>();
// price
@ -224,63 +224,35 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
});
tableView.getColumns().add(volumeColumn);
// select
TableColumn<Offer, Offer> selectColumn = new TableColumn<>("I want to:");
selectColumn.setMinWidth(100);
selectColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
selectColumn.setCellFactory(
new Callback<TableColumn<Offer, Offer>, TableCell<Offer, Offer>>() {
@Override
public TableCell<Offer, Offer> call(TableColumn<Offer, Offer> column) {
return new TableCell<Offer, Offer>() {
final Button button = new Button();
final ImageView iconView = new ImageView();
{
button.setGraphic(iconView);
button.setMinWidth(70);
}
@Override
public void updateItem(final Offer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
boolean isSellOffer = item.getDirection() == Offer.Direction.SELL;
iconView.setId(isSellOffer ? "image-buy" : "image-sell");
button.setText(isSellOffer ? "Buy" : "Sell");
button.setOnAction(e -> {
if (isSellOffer)
navigation.navigateTo(MainView.class, BuyOfferView.class);
else
navigation.navigateTo(MainView.class, SellOfferView.class);
});
setGraphic(button);
} else {
setGraphic(null);
if (button != null)
button.setOnAction(null);
}
}
};
}
});
tableView.getColumns().add(selectColumn);
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
Label placeholder = new Label("Currently there are no offers available");
placeholder.setWrapText(true);
tableView.setPlaceholder(placeholder);
tableView.getSelectionModel().setCellSelectionEnabled(false);
Label titleLabel = new Label(direction.equals(Offer.Direction.BUY) ? "Offers for buying bitcoin (bid)" : "Offers for selling bitcoin (ask)");
titleLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 16; -fx-alignment: center");
UserThread.execute(() -> titleLabel.prefWidthProperty().bind(tableView.widthProperty()));
boolean isSellOffer = direction == Offer.Direction.SELL;
Button button = new Button();
ImageView iconView = new ImageView();
iconView.setId(isSellOffer ? "image-buy-white" : "image-sell-white");
button.setGraphic(iconView);
button.setGraphicTextGap(10);
button.setText(isSellOffer ? "I want to buy bitcoin" : "I want to sell bitcoin");
button.setMinHeight(40);
button.setId(isSellOffer ? "buy-button-big" : "sell-button-big");
button.setOnAction(e -> navigation.navigateTo(MainView.class, isSellOffer ? BuyOfferView.class : SellOfferView.class));
VBox vBox = new VBox();
vBox.setSpacing(10);
vBox.setFillWidth(true);
vBox.setMinHeight(150);
vBox.getChildren().addAll(titleLabel, tableView);
return new Tuple2<>(tableView, vBox);
vBox.setMinHeight(120);
vBox.getChildren().addAll(titleLabel, tableView, button);
button.prefWidthProperty().bind(vBox.widthProperty());
return new Tuple3<>(tableView, vBox, button);
}

View File

@ -82,10 +82,10 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
private BalanceTextField balanceTextField;
private ProgressIndicator placeOfferSpinner;
private TitledGroupBg payFundsPane;
private Button nextButton, cancelButton1, cancelButton2, placeOfferButton;
private Button nextButton, cancelButton1, cancelButton2, createOfferButton;
private InputTextField amountTextField, minAmountTextField, priceTextField, volumeTextField;
private TextField totalToPayTextField, currencyTextField;
private Label buyLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, totalToPayInfoIconLabel, amountBtcLabel, priceCurrencyLabel,
private Label directionLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, totalToPayInfoIconLabel, amountBtcLabel, priceCurrencyLabel,
volumeCurrencyLabel, minAmountBtcLabel, priceDescriptionLabel, volumeDescriptionLabel, placeOfferSpinnerInfoLabel, currencyTextFieldLabel,
currencyComboBoxLabel;
private ComboBox<PaymentAccount> paymentAccountsComboBox;
@ -156,7 +156,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
addBindings();
addListeners();
buyLabel.setText(model.getDirectionLabel());
directionLabel.setText(model.getDirectionLabel());
amountDescriptionLabel.setText(model.getAmountDescription());
addressTextField.setAddress(model.getAddressAsString());
addressTextField.setPaymentLabel(model.getPaymentLabel());
@ -181,12 +181,24 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
public void initWithData(Offer.Direction direction, TradeCurrency tradeCurrency) {
model.initWithData(direction, tradeCurrency);
ImageView iconView = new ImageView();
createOfferButton.setGraphic(iconView);
if (direction == Offer.Direction.BUY) {
imageView.setId("image-buy-large");
createOfferButton.setId("buy-button-big");
nextButton.setId("buy-button");
createOfferButton.setText("Place offer for buying bitcoin");
iconView.setId("image-buy-white");
} else {
imageView.setId("image-sell-large");
// only needed for sell
totalToPayTextField.setPromptText(BSResources.get("createOffer.fundsBox.totalsNeeded.prompt"));
createOfferButton.setId("sell-button-big");
nextButton.setId("sell-button");
createOfferButton.setText("Place offer for selling bitcoin");
iconView.setId("image-sell-white");
}
}
@ -354,8 +366,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
volumeTextField.validationResultProperty().bind(model.volumeValidationResult);
// buttons
placeOfferButton.visibleProperty().bind(model.isPlaceOfferButtonVisible);
placeOfferButton.disableProperty().bind(model.isPlaceOfferButtonDisabled);
createOfferButton.visibleProperty().bind(model.isPlaceOfferButtonVisible);
createOfferButton.disableProperty().bind(model.isPlaceOfferButtonDisabled);
placeOfferSpinnerInfoLabel.visibleProperty().bind(model.isPlaceOfferSpinnerVisible);
@ -387,8 +399,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
minAmountTextField.validationResultProperty().unbind();
priceTextField.validationResultProperty().unbind();
volumeTextField.validationResultProperty().unbind();
placeOfferButton.visibleProperty().unbind();
placeOfferButton.disableProperty().unbind();
createOfferButton.visibleProperty().unbind();
createOfferButton.disableProperty().unbind();
placeOfferSpinnerInfoLabel.visibleProperty().unbind();
currencyComboBox.managedProperty().unbind();
currencyComboBoxLabel.visibleProperty().unbind();
@ -613,14 +625,14 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
imageView = new ImageView();
imageView.setPickOnBounds(true);
buyLabel = new Label();
buyLabel.setId("direction-icon-label");
buyLabel.setAlignment(Pos.CENTER);
buyLabel.setPadding(new Insets(-5, 0, 0, 0));
directionLabel = new Label();
directionLabel.setAlignment(Pos.CENTER);
directionLabel.setPadding(new Insets(-5, 0, 0, 0));
directionLabel.setId("direction-icon-label");
VBox imageVBox = new VBox();
imageVBox.setAlignment(Pos.CENTER);
imageVBox.setSpacing(6);
imageVBox.getChildren().addAll(imageView, buyLabel);
imageVBox.getChildren().addAll(imageView, directionLabel);
GridPane.setRowIndex(imageVBox, gridRow);
GridPane.setRowSpan(imageVBox, 2);
GridPane.setMargin(imageVBox, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, 10, 10, 10));
@ -636,9 +648,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
cancelButton1 = tuple.second;
cancelButton1.setDefaultButton(false);
cancelButton1.setOnAction(e -> close());
cancelButton1.setId("cancel-button");
GridPane.setMargin(nextButton, new Insets(-35, 0, 0, 0));
nextButton.setId("show-details-button");
nextButton.setOnAction(e -> onShowFundsScreen());
}
@ -679,11 +691,11 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
balanceTextField = balanceTuple.second;
balanceTextField.setVisible(false);
Tuple3<Button, ProgressIndicator, Label> placeOfferTuple = addButtonWithStatusAfterGroup(gridPane, ++gridRow,
BSResources.get("createOffer.fundsBox.placeOffer"));
placeOfferButton = placeOfferTuple.first;
placeOfferButton.setVisible(false);
placeOfferButton.setOnAction(e -> onPlaceOffer());
Tuple3<Button, ProgressIndicator, Label> placeOfferTuple = addButtonWithStatusAfterGroup(gridPane, ++gridRow, "");
createOfferButton = placeOfferTuple.first;
createOfferButton.setVisible(false);
createOfferButton.setOnAction(e -> onPlaceOffer());
createOfferButton.setMinHeight(40);
placeOfferSpinner = placeOfferTuple.second;
placeOfferSpinner.setPrefSize(18, 18);
placeOfferSpinnerInfoLabel = placeOfferTuple.third;
@ -694,6 +706,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
cancelButton2.setOnAction(e -> close());
cancelButton2.setDefaultButton(false);
cancelButton2.setVisible(false);
cancelButton2.setId("cancel-button");
}
private void addAmountPriceFields() {

View File

@ -17,18 +17,12 @@
~ along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
-->
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.offer.offerbook.OfferBookView"
hgap="5.0" vgap="5"
xmlns:fx="http://javafx.com/fxml">
<rowConstraints>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints vgrow="ALWAYS"/>
</rowConstraints>
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/>
<ColumnConstraints hgrow="ALWAYS"/>

View File

@ -21,7 +21,7 @@ import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
import io.bitsquare.gui.common.view.FxmlView;
import io.bitsquare.gui.components.HyperlinkWithIcon;
import io.bitsquare.gui.components.TableGroupHeadline;
import io.bitsquare.gui.components.TitledGroupBg;
import io.bitsquare.gui.main.MainView;
import io.bitsquare.gui.main.account.AccountView;
import io.bitsquare.gui.main.account.content.arbitratorselection.ArbitratorSelectionView;
@ -38,10 +38,13 @@ import io.bitsquare.locale.TradeCurrency;
import io.bitsquare.payment.PaymentMethod;
import io.bitsquare.trade.offer.Offer;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.util.Callback;
import javafx.util.StringConverter;
@ -64,7 +67,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
private OfferView.OfferActionHandler offerActionHandler;
private int gridRow = 0;
private TableGroupHeadline offerBookTitle;
private TitledGroupBg offerBookTitle;
///////////////////////////////////////////////////////////////////////////////////////////
@ -81,8 +84,9 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
@Override
public void initialize() {
root.setPadding(new Insets(30, 25, -1, 25));
addTitledGroupBg(root, gridRow, 2, "Filter offer book");
root.setPadding(new Insets(20, 25, 5, 25));
offerBookTitle = addTitledGroupBg(root, gridRow, 3, "");
currencyComboBox = addLabelComboBox(root, gridRow, "Filter by currency:", Layout.FIRST_ROW_DISTANCE).second;
currencyComboBox.setPromptText("Select currency");
@ -116,21 +120,15 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
}
});
// createOfferButton
createOfferButton = addButtonAfterGroup(root, ++gridRow, "Create new offer");
offerBookTitle = new TableGroupHeadline("");
GridPane.setRowIndex(offerBookTitle, ++gridRow);
GridPane.setColumnSpan(offerBookTitle, 2);
GridPane.setMargin(offerBookTitle, new Insets(20, -10, -10, -10));
root.getChildren().add(offerBookTitle);
tableView = new TableView<>();
GridPane.setRowIndex(tableView, gridRow);
GridPane.setRowIndex(tableView, ++gridRow);
GridPane.setColumnIndex(tableView, 0);
GridPane.setColumnSpan(tableView, 2);
GridPane.setMargin(tableView, new Insets(40, -10, -15, -10));
GridPane.setMargin(tableView, new Insets(10, -10, -10, -10));
GridPane.setVgrow(tableView, Priority.ALWAYS);
root.getChildren().add(tableView);
amountColumn = getAmountColumn();
tableView.getColumns().add(amountColumn);
priceColumn = getPriceColumn();
@ -151,6 +149,15 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
amountColumn.setComparator((o1, o2) -> o1.getOffer().getAmount().compareTo(o2.getOffer().getAmount()));
volumeColumn.setComparator((o1, o2) -> o1.getOffer().getOfferVolume().compareTo(o2.getOffer().getOfferVolume()));
paymentMethodColumn.setComparator((o1, o2) -> o1.getOffer().getPaymentMethod().compareTo(o2.getOffer().getPaymentMethod()));
createOfferButton = addButton(root, ++gridRow, "");
createOfferButton.setMinHeight(40);
createOfferButton.setPadding(new Insets(0, 20, 0, 20));
createOfferButton.setGraphicTextGap(10);
GridPane.setMargin(createOfferButton, new Insets(15, 0, 0, 0));
GridPane.setHalignment(createOfferButton, HPos.RIGHT);
GridPane.setVgrow(createOfferButton, Priority.NEVER);
GridPane.setValignment(createOfferButton, VPos.TOP);
}
@Override
@ -211,8 +218,21 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
}
public void setDirection(Offer.Direction direction) {
offerBookTitle.setText(direction == Offer.Direction.SELL ? "Offers for buying bitcoin " : "Offers for selling bitcoin ");
model.setDirection(direction);
ImageView iconView = new ImageView();
createOfferButton.setGraphic(iconView);
if (direction == Offer.Direction.SELL) {
offerBookTitle.setText("Offers for buying bitcoin ");
createOfferButton.setId("sell-button-big");
createOfferButton.setText("Create new offer for selling bitcoin");
iconView.setId("image-sell-white");
} else {
offerBookTitle.setText("Offers for selling bitcoin ");
createOfferButton.setId("buy-button-big");
createOfferButton.setText("Create new offer for buying bitcoin");
iconView.setId("image-buy-white");
}
}
public void setOfferActionHandler(OfferView.OfferActionHandler offerActionHandler) {
@ -456,7 +476,10 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
{
button.setGraphic(iconView);
button.setMinWidth(70);
button.setMinWidth(150);
button.setMaxWidth(150);
button.setGraphicTextGap(10);
button.setStyle("-fx-text-fill: white;");
}
@Override
@ -495,9 +518,12 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
if (myOffer) {
iconView.setId("image-remove");
title = "Remove";
button.setId("cancel-button");
button.setOnAction(e -> onRemoveOpenOffer(offer));
} else {
iconView.setId(offer.getDirection() == Offer.Direction.SELL ? "image-buy" : "image-sell");
boolean isSellOffer = offer.getDirection() == Offer.Direction.SELL;
iconView.setId(isSellOffer ? "image-buy-white" : "image-sell-white");
button.setId(isSellOffer ? "buy-button" : "sell-button");
title = model.getDirectionLabel(offer);
button.setOnAction(e -> onTakeOffer(offer));
}
@ -505,7 +531,6 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
if (!isTradable)
button.setOnAction(e -> onShowInfo(isPaymentAccountValidForOffer, hasMatchingArbitrator, hasSameProtocolVersion));
button.setText(title);
setGraphic(button);
} else {

View File

@ -83,7 +83,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
private Button nextButton, takeOfferButton, cancelButton1, cancelButton2;
private InputTextField amountTextField;
private TextField paymentMethodTextField, currencyTextField, priceTextField, volumeTextField, amountRangeTextField;
private Label buyLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, totalToPayInfoIconLabel,
private Label directionLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, totalToPayInfoIconLabel,
amountBtcLabel, priceCurrencyLabel,
volumeCurrencyLabel, amountRangeBtcLabel, priceDescriptionLabel, volumeDescriptionLabel, takeOfferSpinnerInfoLabel;
private TextFieldWithCopyIcon totalToPayTextField;
@ -303,10 +303,25 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
public void initWithData(Offer offer) {
model.initWithData(offer);
if (model.getOffer().getDirection() == Offer.Direction.SELL)
ImageView iconView = new ImageView();
takeOfferButton.setGraphic(iconView);
if (model.getOffer().getDirection() == Offer.Direction.SELL) {
imageView.setId("image-buy-large");
else
directionLabel.setId("direction-icon-label-buy");
takeOfferButton.setId("buy-button-big");
takeOfferButton.setText("Take offer for buying bitcoin");
nextButton.setId("buy-button");
iconView.setId("image-buy-white");
} else {
imageView.setId("image-sell-large");
directionLabel.setId("direction-icon-label-sell");
takeOfferButton.setId("sell-button-big");
nextButton.setId("sell-button");
takeOfferButton.setText("Take offer for selling bitcoin");
iconView.setId("image-sell-white");
}
balanceTextField.setup(model.address.get(), model.getFormatter());
@ -322,7 +337,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
if (!showComboBox)
paymentMethodTextField.setText(BSResources.get(model.getPaymentMethod().getId()));
currencyTextField.setText(model.dataModel.getCurrencyNameAndCode());
buyLabel.setText(model.getDirectionLabel());
directionLabel.setText(model.getDirectionLabel());
amountDescriptionLabel.setText(model.getAmountDescription());
amountRangeTextField.setText(model.getAmountRange());
priceTextField.setText(model.getPrice());
@ -493,14 +508,13 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
imageView = new ImageView();
imageView.setPickOnBounds(true);
buyLabel = new Label();
buyLabel.setId("direction-icon-label");
buyLabel.setAlignment(Pos.CENTER);
buyLabel.setPadding(new Insets(-5, 0, 0, 0));
directionLabel = new Label();
directionLabel.setAlignment(Pos.CENTER);
directionLabel.setPadding(new Insets(-5, 0, 0, 0));
VBox imageVBox = new VBox();
imageVBox.setAlignment(Pos.CENTER);
imageVBox.setSpacing(6);
imageVBox.getChildren().addAll(imageView, buyLabel);
imageVBox.getChildren().addAll(imageView, directionLabel);
GridPane.setRowIndex(imageVBox, gridRow);
GridPane.setRowSpan(imageVBox, 2);
GridPane.setMargin(imageVBox, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, 10, 10, 10));
@ -516,9 +530,9 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
cancelButton1 = tuple.second;
cancelButton1.setDefaultButton(false);
cancelButton1.setOnAction(e -> close());
cancelButton1.setId("cancel-button");
GridPane.setMargin(nextButton, new Insets(-35, 0, 0, 0));
nextButton.setId("show-details-button");
nextButton.setOnAction(e -> onShowPayFundsScreen());
}
@ -560,10 +574,11 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
balanceTextField = balanceTuple.second;
balanceTextField.setVisible(false);
Tuple3<Button, ProgressIndicator, Label> takeOfferTuple = addButtonWithStatusAfterGroup(gridPane, ++gridRow, BSResources.get("takeOffer.fundsBox.takeOffer"));
Tuple3<Button, ProgressIndicator, Label> takeOfferTuple = addButtonWithStatusAfterGroup(gridPane, ++gridRow, "");
takeOfferButton = takeOfferTuple.first;
takeOfferButton.setVisible(false);
takeOfferButton.setOnAction(e -> onTakeOffer());
takeOfferButton.setMinHeight(40);
takeOfferSpinner = takeOfferTuple.second;
takeOfferSpinner.setPrefSize(18, 18);
takeOfferSpinnerInfoLabel = takeOfferTuple.third;
@ -574,6 +589,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
cancelButton2.setOnAction(e -> close());
cancelButton2.setDefaultButton(false);
cancelButton2.setVisible(false);
cancelButton2.setId("cancel-button");
}
private void addAmountPriceFields() {

View File

@ -248,7 +248,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
if (model.showDispute(item.getTrade())) {
setStyle("-fx-text-fill: -bs-error-red");
} else if (model.showWarning(item.getTrade())) {
setStyle("-fx-text-fill: -bs-orange");
setStyle("-fx-text-fill: -bs-warning");
} else {
setId("-fx-text-fill: black");
}

View File

@ -609,6 +609,23 @@ public class FormBuilder {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Label + Button
///////////////////////////////////////////////////////////////////////////////////////////
public static Tuple2<Label, Button> addLabelButton(GridPane gridPane, int rowIndex, String labelText, String buttonTitle, double top) {
Label label = addLabel(gridPane, rowIndex, labelText, top);
Button button = new Button(buttonTitle);
button.setDefaultButton(true);
GridPane.setRowIndex(button, rowIndex);
GridPane.setColumnIndex(button, 1);
gridPane.getChildren().add(button);
GridPane.setMargin(button, new Insets(top, 0, 0, 0));
return new Tuple2<>(label, button);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Button
///////////////////////////////////////////////////////////////////////////////////////////

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

View File

@ -6,6 +6,7 @@ import io.bitsquare.app.Log;
import io.bitsquare.app.Version;
import io.bitsquare.common.ByteArrayUtils;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.util.Tuple2;
import io.bitsquare.crypto.PrefixedSealedAndSignedMessage;
import io.bitsquare.p2p.Message;
import io.bitsquare.p2p.NodeAddress;
@ -58,10 +59,10 @@ public class Connection implements MessageListener {
private static final int MAX_MSG_SIZE = 100 * 1024; // 100 kb of compressed data
private static final int MSG_THROTTLE_PER_SEC = 10; // With MAX_MSG_SIZE of 100kb results in bandwidth of 10 mbit/sec
private static final int MSG_THROTTLE_PER_10SEC = 50; // With MAX_MSG_SIZE of 100kb results in bandwidth of 5 mbit/sec for 10 sec
// private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(60);
private static final int MSG_THROTTLE_PER_10_SEC = 50; // With MAX_MSG_SIZE of 100kb results in bandwidth of 5 mbit/sec for 10 sec
private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(60);
//TODO
private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(30);
// private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(30);
public static int getMaxMsgSize() {
return MAX_MSG_SIZE;
@ -96,7 +97,7 @@ public class Connection implements MessageListener {
private final boolean useCompression = false;
private PeerType peerType;
private final ObjectProperty<NodeAddress> nodeAddressProperty = new SimpleObjectProperty<>();
private final List<Long> messageTimeStamps = new ArrayList<>();
private final List<Tuple2<Long, Serializable>> messageTimeStamps = new ArrayList<>();
private final CopyOnWriteArraySet<MessageListener> messageListeners = new CopyOnWriteArraySet<>();
@ -231,28 +232,40 @@ public class Connection implements MessageListener {
sharedModel.reportInvalidRequest(ruleViolation);
}
private boolean violatesThrottleLimit() {
private boolean violatesThrottleLimit(Serializable serializable) {
long now = System.currentTimeMillis();
boolean violated = false;
//TODO remove serializable storage after network is tested stable
if (messageTimeStamps.size() >= MSG_THROTTLE_PER_SEC) {
// check if we got more than 10 (MSG_THROTTLE_PER_SEC) msg per sec.
long compareValue = messageTimeStamps.get(messageTimeStamps.size() - MSG_THROTTLE_PER_SEC);
long compareValue = messageTimeStamps.get(messageTimeStamps.size() - MSG_THROTTLE_PER_SEC).first;
// if duration < 1 sec we received too much messages
violated = now - compareValue < TimeUnit.SECONDS.toMillis(1);
if (violated) {
log.error("violatesThrottleLimit 1 ");
log.error("compareValue " + compareValue);
log.error("messageTimeStamps: \n\t" + messageTimeStamps.stream().map(e -> e.second.toString() + "\n\t").toString());
}
}
if (messageTimeStamps.size() >= MSG_THROTTLE_PER_10SEC) {
if (messageTimeStamps.size() >= MSG_THROTTLE_PER_10_SEC) {
if (!violated) {
// check if we got more than 50 msg per 10 sec.
long compareValue = messageTimeStamps.get(messageTimeStamps.size() - MSG_THROTTLE_PER_10SEC);
long compareValue = messageTimeStamps.get(messageTimeStamps.size() - MSG_THROTTLE_PER_10_SEC).first;
// if duration < 10 sec we received too much messages
violated = now - compareValue < TimeUnit.SECONDS.toMillis(10);
if (violated) {
log.error("violatesThrottleLimit 2 ");
log.error("compareValue " + compareValue);
log.error("messageTimeStamps: \n\t" + messageTimeStamps.stream().map(e -> e.second.toString() + "\n\t").toString());
}
}
// we limit to max 50 (MSG_THROTTLE_PER_10SEC) entries
messageTimeStamps.remove(0);
}
messageTimeStamps.add(now);
messageTimeStamps.add(new Tuple2<>(now, serializable));
return violated;
}
@ -641,7 +654,7 @@ public class Connection implements MessageListener {
return;
}
if (sharedModel.connection.violatesThrottleLimit()) {
if (sharedModel.connection.violatesThrottleLimit(serializable)) {
reportInvalidRequest(RuleViolation.THROTTLE_LIMIT_EXCEEDED);
return;
}

View File

@ -17,13 +17,14 @@ import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class KeepAliveManager implements MessageListener, ConnectionListener, PeerManager.Listener {
private static final Logger log = LoggerFactory.getLogger(KeepAliveManager.class);
//private static final int INTERVAL_SEC = new Random().nextInt(10) + 10;
private static final int INTERVAL_SEC = new Random().nextInt(10) + 10;
//TODO
private static final int INTERVAL_SEC = 5;
// private static final int INTERVAL_SEC = 5;
private final NetworkNode networkNode;
private final PeerManager peerManager;

View File

@ -39,7 +39,8 @@ public class P2PDataStorage implements MessageListener, ConnectionListener {
@VisibleForTesting
//public static int CHECK_TTL_INTERVAL_MILLIS = (int) TimeUnit.SECONDS.toMillis(30);
public static int CHECK_TTL_INTERVAL_MILLIS = (int) TimeUnit.SECONDS.toMillis(5);//TODO
public static int CHECK_TTL_INTERVAL_MILLIS = (int) TimeUnit.HOURS.toMillis(30);
// public static int CHECK_TTL_INTERVAL_MILLIS = (int) TimeUnit.SECONDS.toMillis(5);//TODO
private final Broadcaster broadcaster;
private final Map<ByteArray, ProtectedData> map = new ConcurrentHashMap<>();

View File

@ -60,7 +60,7 @@ public class ProtectedData implements Payload {
", ttl=" + ttl +
", date=" + date +
", sequenceNumber=" + sequenceNumber +
", ownerStoragePubKey.hashCode()=" + ownerPubKey.hashCode() +
", ownerPubKey.hashCode()=" + ownerPubKey.hashCode() +
", signature.hashCode()=" + Arrays.toString(signature).hashCode() +
'}';
}