add percentage price (WIP)

This commit is contained in:
Manfred Karrer 2016-04-14 19:12:43 +02:00
parent 5ba1aa0a59
commit 517ee371db
5 changed files with 119 additions and 16 deletions

View File

@ -106,6 +106,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
private final long date;
private final long protocolVersion;
private final long fiatPrice;
private final double percentagePrice;
private final boolean usePercentageBasedPrice;
private final long amount;
private final long minAmount;
private final NodeAddress offererNodeAddress;
@ -138,6 +140,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
PubKeyRing pubKeyRing,
Direction direction,
long fiatPrice,
double percentagePrice,
boolean usePercentageBasedPrice,
long amount,
long minAmount,
String currencyCode,
@ -153,6 +157,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
this.pubKeyRing = pubKeyRing;
this.direction = direction;
this.fiatPrice = fiatPrice;
this.percentagePrice = percentagePrice;
this.usePercentageBasedPrice = usePercentageBasedPrice;
this.amount = amount;
this.minAmount = minAmount;
this.currencyCode = currencyCode;
@ -315,6 +321,14 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
return Fiat.valueOf(currencyCode, fiatPrice);
}
public double getPercentagePrice() {
return percentagePrice;
}
public boolean isUsePercentageBasedPrice() {
return usePercentageBasedPrice;
}
public Coin getAmount() {
return Coin.valueOf(amount);
}
@ -391,11 +405,11 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Offer)) return false;
Offer offer = (Offer) o;
if (date != offer.date) return false;
if (fiatPrice != offer.fiatPrice) return false;
if (Double.compare(offer.percentagePrice, percentagePrice) != 0) return false;
if (usePercentageBasedPrice != offer.usePercentageBasedPrice) return false;
if (amount != offer.amount) return false;
if (minAmount != offer.minAmount) return false;
if (id != null ? !id.equals(offer.id) : offer.id != null) return false;
@ -418,7 +432,6 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
if (arbitratorNodeAddresses != null ? !arbitratorNodeAddresses.equals(offer.arbitratorNodeAddresses) : offer.arbitratorNodeAddresses != null)
return false;
return !(offerFeePaymentTxID != null ? !offerFeePaymentTxID.equals(offer.offerFeePaymentTxID) : offer.offerFeePaymentTxID != null);
}
@Override
@ -428,6 +441,9 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
result = 31 * result + (currencyCode != null ? currencyCode.hashCode() : 0);
result = 31 * result + (int) (date ^ (date >>> 32));
result = 31 * result + (int) (fiatPrice ^ (fiatPrice >>> 32));
long temp = Double.doubleToLongBits(percentagePrice);
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + (usePercentageBasedPrice ? 1 : 0);
result = 31 * result + (int) (amount ^ (amount >>> 32));
result = 31 * result + (int) (minAmount ^ (minAmount >>> 32));
result = 31 * result + (offererNodeAddress != null ? offererNodeAddress.hashCode() : 0);
@ -451,6 +467,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
"\n\tcurrencyCode='" + currencyCode + '\'' +
"\n\tdate=" + date +
"\n\tfiatPrice=" + fiatPrice +
"\n\tpercentagePrice=" + percentagePrice +
"\n\tusePercentageBasedPrice=" + usePercentageBasedPrice +
"\n\tamount=" + amount +
"\n\tminAmount=" + minAmount +
"\n\toffererAddress=" + offererNodeAddress +
@ -471,5 +489,4 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
"\n\tTAC_TAKER=" + TAC_TAKER +
'}';
}
}

View File

@ -496,6 +496,26 @@ textfield */
-fx-border-insets: 0 0 0 -2;
}
#toggle-price-left {
-fx-border-radius: 4 0 0 4;
-fx-padding: 4 4 4 4;
-fx-border-color: #aaa;
-fx-border-style: solid none solid solid;
-fx-border-insets: 0 -2 0 0;
-fx-background-insets: 0 -2 0 0;
-fx-background-radius: 4 0 0 4;
}
#toggle-price-right {
-fx-border-radius: 0 4 4 0;
-fx-padding: 4 4 4 4;
-fx-border-color: #aaa;
-fx-border-style: solid solid solid none;
-fx-border-insets: 0 0 0 -2;
-fx-background-insets: 0 0 0 -2;
-fx-background-radius: 0 4 4 0;
}
#totals-separator {
-fx-background: #AAAAAA;
}

View File

@ -89,6 +89,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
final StringProperty btcCode = new SimpleStringProperty();
final BooleanProperty isWalletFunded = new SimpleBooleanProperty();
final BooleanProperty usePercentageBasedPrice = new SimpleBooleanProperty();
//final BooleanProperty isMainNet = new SimpleBooleanProperty();
//final BooleanProperty isFeeFromFundingTxSufficient = new SimpleBooleanProperty();
@ -96,6 +97,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
final ObjectProperty<Coin> amountAsCoin = new SimpleObjectProperty<>();
final ObjectProperty<Coin> minAmountAsCoin = new SimpleObjectProperty<>();
final ObjectProperty<Fiat> priceAsFiat = new SimpleObjectProperty<>();
final ObjectProperty<Double> priceAsPercentage = new SimpleObjectProperty<>();
final ObjectProperty<Fiat> volumeAsFiat = new SimpleObjectProperty<>();
final ObjectProperty<Coin> totalToPayAsCoin = new SimpleObjectProperty<>();
final ObjectProperty<Coin> missingCoin = new SimpleObjectProperty<>(Coin.ZERO);
@ -253,6 +255,8 @@ class CreateOfferDataModel extends ActivatableDataModel {
Offer createAndGetOffer() {
long fiatPrice = priceAsFiat.get() != null ? priceAsFiat.get().getValue() : 0L;
double percentagePrice = 0;
long amount = amountAsCoin.get() != null ? amountAsCoin.get().getValue() : 0L;
long minAmount = minAmountAsCoin.get() != null ? minAmountAsCoin.get().getValue() : 0L;
@ -284,6 +288,8 @@ class CreateOfferDataModel extends ActivatableDataModel {
keyRing.getPubKeyRing(),
direction,
fiatPrice,
percentagePrice,
usePercentageBasedPrice.get(),
amount,
minAmount,
tradeCurrencyCode.get(),
@ -378,6 +384,10 @@ class CreateOfferDataModel extends ActivatableDataModel {
return user.getAcceptedArbitrators().size() > 0;
}
public void setUsePercentageBasedPrice(boolean usePercentageBasedPrice) {
this.usePercentageBasedPrice.set(usePercentageBasedPrice);
}
/*boolean isFeeFromFundingTxSufficient() {
return !isMainNet.get() || feeFromFundingTxProperty.get().compareTo(FeePolicy.getMinRequiredFeeForFundingTx()) >= 0;
}*/

View File

@ -88,8 +88,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
private BalanceTextField balanceTextField;
private TitledGroupBg payFundsPane;
private ProgressIndicator spinner;
private Button nextButton, cancelButton1, cancelButton2, fundFromSavingsWalletButton, fundFromExternalWalletButton, placeOfferButton;
private InputTextField amountTextField, minAmountTextField, priceTextField, volumeTextField;
private Button nextButton, cancelButton1, cancelButton2, fundFromSavingsWalletButton, fundFromExternalWalletButton, placeOfferButton, usePercentageBasedPriceButton;
private InputTextField amountTextField, minAmountTextField, priceTextField, priceAsPercentageTextField, volumeTextField;
private TextField currencyTextField;
private Label directionLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, totalToPayInfoIconLabel, amountBtcLabel, priceCurrencyLabel,
volumeCurrencyLabel, minAmountBtcLabel, priceDescriptionLabel, volumeDescriptionLabel, currencyTextFieldLabel,
@ -98,6 +98,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
private ComboBox<PaymentAccount> paymentAccountsComboBox;
private ComboBox<TradeCurrency> currencyComboBox;
private PopOver totalToPayInfoPopover;
private Label priceAsPercentageLabel;
private ToggleButton fixedPriceButton;
private ToggleButton percentagePriceButton;
private OfferView.CloseHandler closeHandler;
@ -175,6 +178,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
if (spinner != null && spinner.isVisible())
spinner.setProgress(-1);
percentagePriceButton.setSelected(model.dataModel.usePercentageBasedPrice.get());
fixedPriceButton.setSelected(!model.dataModel.usePercentageBasedPrice.get());
directionLabel.setText(model.getDirectionLabel());
amountDescriptionLabel.setText(model.getAmountDescription());
addressTextField.setAddress(model.getAddressAsString());
@ -407,6 +413,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
private void addBindings() {
amountBtcLabel.textProperty().bind(model.btcCode);
priceCurrencyLabel.textProperty().bind(createStringBinding(() -> model.tradeCurrencyCode.get() + "/" + model.btcCode.get(), model.btcCode, model.tradeCurrencyCode));
priceTextField.disableProperty().bind(model.dataModel.usePercentageBasedPrice);
priceAsPercentageTextField.disableProperty().bind(model.dataModel.usePercentageBasedPrice.not());
priceAsPercentageLabel.prefWidthProperty().bind(priceCurrencyLabel.widthProperty());
volumeCurrencyLabel.textProperty().bind(model.tradeCurrencyCode);
minAmountBtcLabel.textProperty().bind(model.btcCode);
priceDescriptionLabel.textProperty().bind(createStringBinding(() -> BSResources.get("createOffer.amountPriceBox.priceDescription", model.tradeCurrencyCode.get()), model.tradeCurrencyCode));
@ -452,6 +461,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
private void removeBindings() {
amountBtcLabel.textProperty().unbind();
priceCurrencyLabel.textProperty().unbind();
priceTextField.disableProperty().unbind();
priceAsPercentageTextField.disableProperty().unbind();
volumeCurrencyLabel.textProperty().unbind();
minAmountBtcLabel.textProperty().unbind();
priceDescriptionLabel.textProperty().unbind();
@ -459,6 +470,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
amountTextField.textProperty().unbindBidirectional(model.amount);
minAmountTextField.textProperty().unbindBidirectional(model.minAmount);
priceTextField.textProperty().unbindBidirectional(model.price);
priceAsPercentageLabel.prefWidthProperty().unbind();
volumeTextField.textProperty().unbindBidirectional(model.volume);
volumeTextField.promptTextProperty().unbindBidirectional(model.volume);
totalToPayTextField.textProperty().unbind();
@ -745,8 +757,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
gridPane.getChildren().add(imageVBox);
addAmountPriceFields();
addMinAmountBox();
addSecondRow();
Tuple2<Button, Button> tuple = add2ButtonsAfterGroup(gridPane, ++gridRow, BSResources.get("createOffer.amountPriceBox.next"), BSResources.get("shared.cancel"));
nextButton = tuple.first;
@ -897,7 +908,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
xLabel.setFont(Font.font("Helvetica-Bold", 20));
xLabel.setPadding(new Insets(14, 3, 0, 3));
// price
// price as fiat
Tuple3<HBox, InputTextField, Label> priceValueCurrencyBoxTuple = FormBuilder.getValueCurrencyBox(BSResources.get("createOffer.price.prompt"));
HBox priceValueCurrencyBox = priceValueCurrencyBoxTuple.first;
priceTextField = priceValueCurrencyBoxTuple.second;
@ -906,6 +917,26 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
priceDescriptionLabel = priceInputBoxTuple.first;
VBox priceBox = priceInputBoxTuple.second;
// Fixed/Percentage toggle
ToggleGroup toggleGroup = new ToggleGroup();
fixedPriceButton = new ToggleButton("Fixed");
fixedPriceButton.setId("toggle-price-left");
fixedPriceButton.setToggleGroup(toggleGroup);
fixedPriceButton.selectedProperty().addListener((ov, oldValue, newValue) -> {
model.dataModel.setUsePercentageBasedPrice(!newValue);
});
percentagePriceButton = new ToggleButton("Percentage");
percentagePriceButton.setId("toggle-price-right");
percentagePriceButton.setToggleGroup(toggleGroup);
percentagePriceButton.selectedProperty().addListener((ov, oldValue, newValue) -> {
model.dataModel.setUsePercentageBasedPrice(newValue);
});
HBox toggleButtons = new HBox();
toggleButtons.setPadding(new Insets(18, 0, 0, 0));
toggleButtons.getChildren().addAll(fixedPriceButton, percentagePriceButton);
// =
Label resultLabel = new Label("=");
resultLabel.setFont(Font.font("Helvetica-Bold", 20));
@ -923,7 +954,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
HBox hBox = new HBox();
hBox.setSpacing(5);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.getChildren().addAll(amountBox, xLabel, priceBox, resultLabel, volumeBox);
hBox.getChildren().addAll(amountBox, xLabel, priceBox, toggleButtons, resultLabel, volumeBox);
GridPane.setRowIndex(hBox, gridRow);
GridPane.setColumnIndex(hBox, 1);
GridPane.setMargin(hBox, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, 10, 0, 0));
@ -931,7 +962,20 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
gridPane.getChildren().add(hBox);
}
private void addMinAmountBox() {
private void addSecondRow() {
Tuple3<HBox, InputTextField, Label> priceAsPercentageTuple = FormBuilder.getValueCurrencyBox(BSResources.get("createOffer.price.prompt"));
HBox priceAsPercentageValueCurrencyBox = priceAsPercentageTuple.first;
priceAsPercentageTextField = priceAsPercentageTuple.second;
priceAsPercentageLabel = priceAsPercentageTuple.third;
Tuple2<Label, VBox> priceAsPercentageInputBoxTuple = getTradeInputBox(priceAsPercentageValueCurrencyBox, "Distance in % from market price");
priceAsPercentageInputBoxTuple.first.setPrefWidth(200);
VBox priceAsPercentageInputBox = priceAsPercentageInputBoxTuple.second;
priceAsPercentageTextField.setPromptText("Enter % value");
priceAsPercentageLabel.setText("% dist.");
priceAsPercentageLabel.setStyle("-fx-alignment: center;");
Tuple3<HBox, InputTextField, Label> amountValueCurrencyBoxTuple = getValueCurrencyBox(BSResources.get("createOffer.amount.prompt"));
HBox amountValueCurrencyBox = amountValueCurrencyBoxTuple.first;
minAmountTextField = amountValueCurrencyBoxTuple.second;
@ -939,11 +983,21 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
Tuple2<Label, VBox> amountInputBoxTuple = getTradeInputBox(amountValueCurrencyBox, BSResources.get("createOffer.amountPriceBox" +
".minAmountDescription"));
VBox box = amountInputBoxTuple.second;
GridPane.setRowIndex(box, ++gridRow);
GridPane.setColumnIndex(box, 1);
GridPane.setMargin(box, new Insets(5, 10, 5, 0));
gridPane.getChildren().add(box);
Label xLabel = new Label("x");
xLabel.setFont(Font.font("Helvetica-Bold", 20));
xLabel.setPadding(new Insets(14, 3, 0, 3));
xLabel.setVisible(false); // we just use it to get the same layout as the upper row
HBox hBox = new HBox();
hBox.setSpacing(5);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.getChildren().addAll(amountInputBoxTuple.second, xLabel, priceAsPercentageInputBox);
GridPane.setRowIndex(hBox, ++gridRow);
GridPane.setColumnIndex(hBox, 1);
GridPane.setMargin(hBox, new Insets(5, 10, 5, 0));
GridPane.setColumnSpan(hBox, 2);
gridPane.getChildren().add(hBox);
}

View File

@ -267,6 +267,8 @@ public class OfferBookViewModelTest {
null,
0,
0,
false,
0,
0,
tradeCurrencyCode,
null,