diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index e0c28fb8dd1..f8ef28949c8 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -1040,11 +1040,13 @@ funds.withdrawal.inputs=Inputs selection funds.withdrawal.useAllInputs=Use all available inputs funds.withdrawal.useCustomInputs=Use custom inputs funds.withdrawal.receiverAmount=Receiver's amount +funds.withdrawal.sendMax=Send max available funds.withdrawal.senderAmount=Sender's amount funds.withdrawal.feeExcluded=Amount excludes mining fee funds.withdrawal.feeIncluded=Amount includes mining fee funds.withdrawal.fromLabel=Withdraw from address funds.withdrawal.toLabel=Withdraw to address +funds.withdrawal.maximum=MAX funds.withdrawal.memoLabel=Withdrawal memo funds.withdrawal.memo=Optionally fill memo funds.withdrawal.withdrawButton=Withdraw selected diff --git a/core/src/main/resources/i18n/displayStrings_es.properties b/core/src/main/resources/i18n/displayStrings_es.properties index 990ef7941c6..bd4ee417a22 100644 --- a/core/src/main/resources/i18n/displayStrings_es.properties +++ b/core/src/main/resources/i18n/displayStrings_es.properties @@ -848,6 +848,7 @@ funds.withdrawal.inputs=Selección de entradas funds.withdrawal.useAllInputs=Usar todos los entradas disponibles funds.withdrawal.useCustomInputs=Usar entradas personalizados funds.withdrawal.receiverAmount=Cantidad del receptor +funds.withdrawal.sendMax=Enviar máximo disponible funds.withdrawal.senderAmount=Cantidad del emisor funds.withdrawal.feeExcluded=La cantidad no incluye comisión de minado funds.withdrawal.feeIncluded=La cantidad incluye comisión de minado diff --git a/core/src/main/resources/i18n/displayStrings_fr.properties b/core/src/main/resources/i18n/displayStrings_fr.properties index 462bcef554f..8d3b4ce4689 100644 --- a/core/src/main/resources/i18n/displayStrings_fr.properties +++ b/core/src/main/resources/i18n/displayStrings_fr.properties @@ -849,6 +849,7 @@ funds.withdrawal.inputs=Sélection de la valeur à saisir funds.withdrawal.useAllInputs=Utiliser toutes les valeurs disponibles funds.withdrawal.useCustomInputs=Utiliser une valeur de saisie personnalisée funds.withdrawal.receiverAmount=Montant du destinataire +funds.withdrawal.sendMax=Envoyer max disponible funds.withdrawal.senderAmount=Montant de l'expéditeur funds.withdrawal.feeExcluded=Montant excluant les frais de minage funds.withdrawal.feeIncluded=Montant incluant frais de minage diff --git a/core/src/main/resources/i18n/displayStrings_it.properties b/core/src/main/resources/i18n/displayStrings_it.properties index 97b7fb6b15e..044873db1aa 100644 --- a/core/src/main/resources/i18n/displayStrings_it.properties +++ b/core/src/main/resources/i18n/displayStrings_it.properties @@ -847,6 +847,7 @@ funds.withdrawal.inputs=Selezione input funds.withdrawal.useAllInputs=Utilizza tutti gli input disponibili funds.withdrawal.useCustomInputs=Utilizza input personalizzati funds.withdrawal.receiverAmount=Importo del destinatario +funds.withdrawal.sendMax=Inviare massimo disponibile funds.withdrawal.senderAmount=Importo del mittente funds.withdrawal.feeExcluded=L'importo esclude la commissione di mining funds.withdrawal.feeIncluded=L'importo include la commissione di mining diff --git a/desktop/src/main/java/haveno/desktop/main/funds/withdrawal/WithdrawalView.java b/desktop/src/main/java/haveno/desktop/main/funds/withdrawal/WithdrawalView.java index abdcde0b1b5..0a653083107 100644 --- a/desktop/src/main/java/haveno/desktop/main/funds/withdrawal/WithdrawalView.java +++ b/desktop/src/main/java/haveno/desktop/main/funds/withdrawal/WithdrawalView.java @@ -35,7 +35,7 @@ package haveno.desktop.main.funds.withdrawal; import com.google.inject.Inject; -import haveno.common.util.Tuple4; +import haveno.common.util.Tuple3; import haveno.core.locale.Res; import haveno.core.trade.HavenoUtils; import haveno.core.trade.TradeManager; @@ -48,6 +48,7 @@ import haveno.desktop.common.view.ActivatableView; import haveno.desktop.common.view.FxmlView; import haveno.desktop.components.BusyAnimation; +import haveno.desktop.components.HyperlinkWithIcon; import haveno.desktop.components.TitledGroupBg; import haveno.desktop.main.overlays.popups.Popup; import haveno.desktop.main.overlays.windows.TxDetails; @@ -60,9 +61,6 @@ import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.control.TextField; -import javafx.scene.control.RadioButton; -import javafx.scene.control.ToggleGroup; -import javafx.scene.control.Toggle; import javafx.scene.control.Button; import javafx.scene.layout.GridPane; import javafx.scene.layout.StackPane; @@ -90,7 +88,6 @@ public class WithdrawalView extends ActivatableView { private Label amountLabel; private TextField amountTextField, withdrawToTextField, withdrawMemoTextField; - private RadioButton feeExcludedRadioButton, feeIncludedRadioButton; private final XmrWalletService xmrWalletService; private final TradeManager tradeManager; @@ -100,9 +97,6 @@ public class WithdrawalView extends ActivatableView { private BigInteger amount = BigInteger.ZERO; private ChangeListener amountListener; private ChangeListener amountFocusListener; - private ChangeListener feeToggleGroupListener; - private ToggleGroup feeToggleGroup; - private boolean feeExcluded; private int rowIndex = 0; private final static int MAX_ATTEMPTS = 3; @@ -141,20 +135,15 @@ public void initialize() { withdrawToTextField = addTopLabelInputTextField(gridPane, ++rowIndex, Res.get("funds.withdrawal.toLabel", Res.getBaseCurrencyCode())).second; - feeToggleGroup = new ToggleGroup(); - - final Tuple4 feeTuple3 = FormBuilder.addTopLabelTextFieldRadioButtonRadioButton(gridPane, ++rowIndex, feeToggleGroup, + final Tuple3 feeTuple3 = FormBuilder.addTopLabelTextFieldHyperLink(gridPane, ++rowIndex, "", Res.get("funds.withdrawal.receiverAmount", Res.getBaseCurrencyCode()), - "", - Res.get("funds.withdrawal.feeExcluded"), - Res.get("funds.withdrawal.feeIncluded"), + Res.get("funds.withdrawal.sendMax"), 0); amountLabel = feeTuple3.first; amountTextField = feeTuple3.second; amountTextField.setMinWidth(180); - feeExcludedRadioButton = feeTuple3.third; - feeIncludedRadioButton = feeTuple3.fourth; + HyperlinkWithIcon sendMaxLink = feeTuple3.third; withdrawMemoTextField = addTopLabelInputTextField(gridPane, ++rowIndex, Res.get("funds.withdrawal.memoLabel", Res.getBaseCurrencyCode())).second; @@ -175,6 +164,11 @@ public void initialize() { }).start(); }); + sendMaxLink.setOnAction(event -> { + amount = xmrWalletService.getAvailableBalance(); + amountTextField.setText(Res.get("funds.withdrawal.maximum")); + }); + balanceListener = new XmrBalanceListener() { @Override public void onBalanceChanged(BigInteger balance) { @@ -199,14 +193,6 @@ public void onBalanceChanged(BigInteger balance) { } }; amountLabel.setText(Res.get("funds.withdrawal.receiverAmount")); - feeExcludedRadioButton.setToggleGroup(feeToggleGroup); - feeIncludedRadioButton.setToggleGroup(feeToggleGroup); - feeToggleGroupListener = (observable, oldValue, newValue) -> { - feeExcluded = newValue == feeExcludedRadioButton; - amountLabel.setText(feeExcluded ? - Res.get("funds.withdrawal.receiverAmount") : - Res.get("funds.withdrawal.senderAmount")); - }; } @@ -229,9 +215,6 @@ protected void activate() { amountTextField.textProperty().addListener(amountListener); amountTextField.focusedProperty().addListener(amountFocusListener); xmrWalletService.addBalanceListener(balanceListener); - feeToggleGroup.selectedToggleProperty().addListener(feeToggleGroupListener); - - if (feeToggleGroup.getSelectedToggle() == null) feeToggleGroup.selectToggle(feeExcludedRadioButton); GUIUtil.requestFocus(withdrawToTextField); } @@ -242,7 +225,6 @@ protected void deactivate() { xmrWalletService.removeBalanceListener(balanceListener); amountTextField.textProperty().removeListener(amountListener); amountTextField.focusedProperty().removeListener(amountFocusListener); - feeToggleGroup.selectedToggleProperty().removeListener(feeToggleGroupListener); } @@ -254,12 +236,13 @@ private void onWithdraw() { if (GUIUtil.isReadyForTxBroadcastOrShowPopup(xmrWalletService)) { try { - // get withdraw address - final String withdrawToAddress = withdrawToTextField.getText(); - // check sufficient available balance if (amount.compareTo(BigInteger.ZERO) <= 0) throw new RuntimeException(Res.get("portfolio.pending.step5_buyer.amountTooLow")); + // collect info + final String withdrawToAddress = withdrawToTextField.getText(); + boolean subtractFee = amount.equals(xmrWalletService.getAvailableBalance()); + // create tx MoneroTxWallet tx = null; for (int i = 0; i < MAX_ATTEMPTS; i++) { @@ -270,7 +253,7 @@ private void onWithdraw() { .setAccountIndex(0) .setAmount(amount) .setAddress(withdrawToAddress) - .setSubtractFeeFrom(feeExcluded ? null : Arrays.asList(0))); + .setSubtractFeeFrom(subtractFee ? Arrays.asList(0) : null)); log.info("Done creating withdraw tx in {} ms", System.currentTimeMillis() - startTime); break; } catch (Exception e) { diff --git a/desktop/src/main/java/haveno/desktop/util/FormBuilder.java b/desktop/src/main/java/haveno/desktop/util/FormBuilder.java index 57c09c2f134..e6a6b2965d2 100644 --- a/desktop/src/main/java/haveno/desktop/util/FormBuilder.java +++ b/desktop/src/main/java/haveno/desktop/util/FormBuilder.java @@ -1129,35 +1129,27 @@ public static Tuple3 addTopLabelRadioButtonRadi } /////////////////////////////////////////////////////////////////////////////////////////// - // Label + TextField + RadioButton + RadioButton + // Label + TextField + HyperlinkWithIcon /////////////////////////////////////////////////////////////////////////////////////////// - public static Tuple4 addTopLabelTextFieldRadioButtonRadioButton(GridPane gridPane, - int rowIndex, - ToggleGroup toggleGroup, - String title, - String textFieldTitle, - String radioButtonTitle1, - String radioButtonTitle2, - double top) { + public static Tuple3 addTopLabelTextFieldHyperLink(GridPane gridPane, + int rowIndex, + String title, + String textFieldTitle, + String maxButtonTitle, + double top) { TextField textField = new HavenoTextField(); textField.setPromptText(textFieldTitle); - RadioButton radioButton1 = new AutoTooltipRadioButton(radioButtonTitle1); - radioButton1.setToggleGroup(toggleGroup); - radioButton1.setPadding(new Insets(6, 0, 0, 0)); - - RadioButton radioButton2 = new AutoTooltipRadioButton(radioButtonTitle2); - radioButton2.setToggleGroup(toggleGroup); - radioButton2.setPadding(new Insets(6, 0, 0, 0)); + HyperlinkWithIcon maxButton = new ExternalHyperlink(maxButtonTitle); HBox hBox = new HBox(); hBox.setSpacing(10); - hBox.getChildren().addAll(textField, radioButton1, radioButton2); + hBox.getChildren().addAll(textField, maxButton); final Tuple2 labelVBoxTuple2 = addTopLabelWithVBox(gridPane, rowIndex, title, hBox, top); - return new Tuple4<>(labelVBoxTuple2.first, textField, radioButton1, radioButton2); + return new Tuple3<>(labelVBoxTuple2.first, textField, maxButton); }