mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-22 08:29:16 -04:00
Use colors for buy/sell, redesign offerbook, market overview
This commit is contained in:
parent
daa41d222a
commit
ca20de64d9
@ -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.";
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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"/>
|
||||
|
@ -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 {
|
||||
|
@ -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() {
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
BIN
gui/src/main/resources/images/buy_white.png
Normal file
BIN
gui/src/main/resources/images/buy_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 287 B |
BIN
gui/src/main/resources/images/buy_white@2x.png
Normal file
BIN
gui/src/main/resources/images/buy_white@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 650 B |
BIN
gui/src/main/resources/images/sell_white.png
Normal file
BIN
gui/src/main/resources/images/sell_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 290 B |
BIN
gui/src/main/resources/images/sell_white@2x.png
Normal file
BIN
gui/src/main/resources/images/sell_white@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 691 B |
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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<>();
|
||||
|
@ -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() +
|
||||
'}';
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user