diff --git a/src/main/java/bisq/desktop/main/dao/BaseProposalView.java b/src/main/java/bisq/desktop/main/dao/BaseProposalView.java index ec228a74ac..f5ec48252b 100644 --- a/src/main/java/bisq/desktop/main/dao/BaseProposalView.java +++ b/src/main/java/bisq/desktop/main/dao/BaseProposalView.java @@ -285,30 +285,6 @@ public abstract class BaseProposalView extends ActivatableView { nameColumn.setComparator(Comparator.comparing(o2 -> o2.getProposal().getName())); tableView.getColumns().add(nameColumn); - TableColumn titleColumn = new AutoTooltipTableColumn<>(Res.get("dao.proposal.title")); - titleColumn.setPrefWidth(100); - titleColumn.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue())); - titleColumn.setCellFactory( - new Callback, TableCell>() { - @Override - public TableCell call( - TableColumn column) { - return new TableCell() { - @Override - public void updateItem(final BaseProposalListItem item, boolean empty) { - super.updateItem(item, empty); - if (item != null) - setText(item.getProposal().getTitle()); - else - setText(""); - } - }; - } - }); - titleColumn.setComparator(Comparator.comparing(o2 -> o2.getProposal().getTitle())); - tableView.getColumns().add(titleColumn); - TableColumn uidColumn = new AutoTooltipTableColumn<>(Res.get("shared.id")); uidColumn.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue())); uidColumn.setCellFactory( diff --git a/src/main/java/bisq/desktop/main/dao/bonding/roles/BondedRolesView.java b/src/main/java/bisq/desktop/main/dao/bonding/roles/BondedRolesView.java index 88213225fa..e4d54c2bf2 100644 --- a/src/main/java/bisq/desktop/main/dao/bonding/roles/BondedRolesView.java +++ b/src/main/java/bisq/desktop/main/dao/bonding/roles/BondedRolesView.java @@ -217,7 +217,7 @@ public class BondedRolesView extends ActivatableView implements public void updateItem(final BondedRolesListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { - String link = item.getBondedRole().getLinkToAccount(); + String link = item.getBondedRole().getLink(); hyperlinkWithIcon = new HyperlinkWithIcon(link, AwesomeIcon.EXTERNAL_LINK); hyperlinkWithIcon.setOnAction(event -> GUIUtil.openWebPage(link)); hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("shared.openURL", link))); diff --git a/src/main/java/bisq/desktop/main/dao/proposal/ProposalDisplay.java b/src/main/java/bisq/desktop/main/dao/proposal/ProposalDisplay.java index 82275f9ee4..8a5e218707 100644 --- a/src/main/java/bisq/desktop/main/dao/proposal/ProposalDisplay.java +++ b/src/main/java/bisq/desktop/main/dao/proposal/ProposalDisplay.java @@ -20,7 +20,6 @@ package bisq.desktop.main.dao.proposal; import bisq.desktop.components.HyperlinkWithIcon; import bisq.desktop.components.InputTextField; import bisq.desktop.components.TxIdTextField; -import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.util.GUIUtil; import bisq.desktop.util.Layout; import bisq.desktop.util.validation.BsqAddressValidator; @@ -33,7 +32,6 @@ import bisq.core.dao.role.BondedRoleType; import bisq.core.dao.state.blockchain.Tx; import bisq.core.dao.state.ext.Param; import bisq.core.dao.voting.proposal.Proposal; -import bisq.core.dao.voting.proposal.ProposalConsensus; import bisq.core.dao.voting.proposal.ProposalType; import bisq.core.dao.voting.proposal.compensation.CompensationConsensus; import bisq.core.dao.voting.proposal.compensation.CompensationProposal; @@ -42,14 +40,16 @@ import bisq.core.dao.voting.proposal.param.ChangeParamProposal; import bisq.core.dao.voting.proposal.role.BondedRoleProposal; import bisq.core.locale.Res; import bisq.core.util.BsqFormatter; +import bisq.core.util.validation.InputValidator; +import bisq.core.util.validation.IntegerValidator; import bisq.common.util.Tuple2; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; -import javafx.scene.control.TextArea; import javafx.scene.control.TextField; +import javafx.scene.control.TextInputControl; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.ColumnConstraints; import javafx.scene.layout.GridPane; @@ -63,8 +63,10 @@ import javafx.collections.FXCollections; import javafx.util.StringConverter; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; @@ -79,7 +81,6 @@ import static com.google.common.base.Preconditions.checkNotNull; @Slf4j public class ProposalDisplay { private final GridPane gridPane; - private final int maxLengthDescriptionText; private final BsqFormatter bsqFormatter; private final BsqWalletService bsqWalletService; private final DaoFacade daoFacade; @@ -88,8 +89,6 @@ public class ProposalDisplay { private TextField uidTextField; private TextField proposalFeeTextField, proposalTypeTextField; public InputTextField nameTextField; - @Nullable - public InputTextField titleTextField; public InputTextField linkInputTextField; @Nullable public InputTextField requestedBsqTextField, bsqAddressTextField, paramValueTextField; @@ -102,14 +101,17 @@ public class ProposalDisplay { @Getter private int gridRow; - @Nullable - public TextArea descriptionTextArea; private HyperlinkWithIcon linkHyperlinkWithIcon; @Nullable private TxIdTextField txIdTextField; - private final ChangeListener descriptionTextAreaListener; private int gridRowStartIndex; - private Label linkLabel; + private List inputChangedListeners = new ArrayList<>(); + @Getter + private List inputControls = new ArrayList<>(); + @Getter + private List comboBoxes = new ArrayList<>(); + private final ChangeListener focusOutListener; + private final ChangeListener inputListener; // TODO get that warning at closing the window... @@ -123,15 +125,21 @@ public class ProposalDisplay { this.bsqWalletService = bsqWalletService; this.daoFacade = daoFacade; - maxLengthDescriptionText = ProposalConsensus.getMaxLengthDescriptionText(); + // focusOutListener = observable -> inputChangedListeners.forEach(Runnable::run); - descriptionTextAreaListener = (observable, oldValue, newValue) -> { - if (!ProposalConsensus.isDescriptionSizeValid(newValue)) { - new Popup<>().warning(Res.get("dao.proposal.display.description.tooLong", maxLengthDescriptionText)).show(); - if (descriptionTextArea != null) - descriptionTextArea.setText(newValue.substring(0, maxLengthDescriptionText)); - } + focusOutListener = (observable, oldValue, newValue) -> { + if (oldValue && !newValue) + inputChangedListeners.forEach(Runnable::run); }; + inputListener = (observable, oldValue, newValue) -> inputChangedListeners.forEach(Runnable::run); + } + + public void addInputChangedListener(Runnable listener) { + inputChangedListeners.add(listener); + } + + public void removeInputChangedListener(Runnable listener) { + inputChangedListeners.remove(listener); } public void createAllFields(String title, int gridRowStartIndex, double top, ProposalType proposalType, @@ -140,27 +148,23 @@ public class ProposalDisplay { this.gridRowStartIndex = gridRowStartIndex; this.gridRow = gridRowStartIndex; int rowSpan = 5; - boolean showTitle = true; - boolean showDescription = true; switch (proposalType) { case COMPENSATION_REQUEST: - rowSpan = 8; + rowSpan = 6; break; case BONDED_ROLE: rowSpan = 5; - showTitle = false; - showDescription = false; break; case REMOVE_ALTCOIN: break; case CHANGE_PARAM: - rowSpan = 8; + rowSpan = 6; break; case GENERIC: break; case CONFISCATE_BOND: - rowSpan = 7; + rowSpan = 5; break; } // for already created proposals we show the uid and tx id so we add 2 rows @@ -172,30 +176,19 @@ public class ProposalDisplay { proposalTypeTextField = addLabelTextField(gridPane, gridRow, Res.getWithCol("dao.proposal.display.type"), proposalType.getDisplayName(), proposalTypeTop).second; - if (!isMakeProposalScreen) { + if (!isMakeProposalScreen) uidTextField = addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.id")).second; - nameTextField = addLabelInputTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.name")).second; - } else { - nameTextField = addLabelInputTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.name")).second; - } - if (showTitle) - titleTextField = addLabelInputTextField(gridPane, ++gridRow, Res.getWithCol("dao.proposal.title")).second; - - if (showDescription) { - descriptionTextArea = addLabelTextArea(gridPane, ++gridRow, Res.get("dao.proposal.display.description"), - Res.get("dao.proposal.display.description.prompt", maxLengthDescriptionText)).second; - descriptionTextArea.setMaxHeight(42); // for 2 lines - descriptionTextArea.setMinHeight(descriptionTextArea.getMaxHeight()); - if (isMakeProposalScreen) - descriptionTextArea.textProperty().addListener(descriptionTextAreaListener); - } + nameTextField = addLabelInputTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.name")).second; + nameTextField.setValidator(new InputValidator()); + inputControls.add(nameTextField); Tuple2 tuple = addLabelInputTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.link")); - linkLabel = tuple.first; linkInputTextField = tuple.second; linkInputTextField.setPromptText(Res.get("dao.proposal.display.link.prompt")); + linkInputTextField.setValidator(new InputValidator()); + inputControls.add(linkInputTextField); linkHyperlinkWithIcon = addLabelHyperlinkWithIcon(gridPane, gridRow, "", "", "").second; @@ -210,16 +203,17 @@ public class ProposalDisplay { bsqValidator.setMinValue(CompensationConsensus.getMinCompensationRequestAmount()); checkNotNull(requestedBsqTextField, "requestedBsqTextField must not be null"); requestedBsqTextField.setValidator(bsqValidator); + inputControls.add(requestedBsqTextField); + // TODO validator, addressTF bsqAddressTextField = addLabelInputTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.bsqAddress")).second; checkNotNull(bsqAddressTextField, "bsqAddressTextField must not be null"); bsqAddressTextField.setText("B" + bsqWalletService.getUnusedAddress().toBase58()); bsqAddressTextField.setValidator(new BsqAddressValidator(bsqFormatter)); + inputControls.add(bsqAddressTextField); break; case BONDED_ROLE: - linkLabel.setText(Res.get("dao.proposal.display.link.bondRole")); - linkInputTextField.setPromptText(Res.get("dao.proposal.display.link.bondRole.prompt")); bondedRoleTypeComboBox = addLabelComboBox(gridPane, ++gridRow, Res.getWithCol("dao.proposal.display.bondedRoleComboBox.label")).second; checkNotNull(bondedRoleTypeComboBox, "bondedRoleTypeComboBox must not be null"); @@ -228,7 +222,7 @@ public class ProposalDisplay { bondedRoleTypeComboBox.setConverter(new StringConverter() { @Override public String toString(BondedRoleType bondedRoleType) { - return bondedRoleType.getDisplayString(); + return bondedRoleType != null ? bondedRoleType.getDisplayString() : ""; } @Override @@ -236,6 +230,7 @@ public class ProposalDisplay { return null; } }); + comboBoxes.add(bondedRoleTypeComboBox); break; case REMOVE_ALTCOIN: break; @@ -252,7 +247,7 @@ public class ProposalDisplay { paramComboBox.setConverter(new StringConverter() { @Override public String toString(Param param) { - return param.toDisplayString(); + return param != null ? param.getDisplayString() : ""; } @Override @@ -260,8 +255,11 @@ public class ProposalDisplay { return null; } }); + comboBoxes.add(paramComboBox); paramValueTextField = addLabelInputTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.paramValue")).second; + paramValueTextField.setValidator(new IntegerValidator()); + inputControls.add(paramValueTextField); break; case GENERIC: break; @@ -274,7 +272,7 @@ public class ProposalDisplay { confiscateBondComboBox.setConverter(new StringConverter() { @Override public String toString(BondedRole bondedRole) { - return bondedRole.getDisplayString(); + return bondedRole != null ? bondedRole.getDisplayString() : ""; } @Override @@ -282,6 +280,7 @@ public class ProposalDisplay { return null; } }); + comboBoxes.add(confiscateBondComboBox); break; } @@ -292,6 +291,8 @@ public class ProposalDisplay { proposalFeeTextField = addLabelTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.proposalFee")).second; if (isMakeProposalScreen) proposalFeeTextField.setText(bsqFormatter.formatCoinWithCode(daoFacade.getProposalFee(daoFacade.getChainHeight()))); + + addListeners(); } public void applyProposalPayload(Proposal proposal) { @@ -300,10 +301,6 @@ public class ProposalDisplay { uidTextField.setText(proposal.getUid()); nameTextField.setText(proposal.getName()); - if (titleTextField != null) - titleTextField.setText(proposal.getTitle()); - if (descriptionTextArea != null) - descriptionTextArea.setText(proposal.getDescription()); linkInputTextField.setVisible(false); linkInputTextField.setManaged(false); linkHyperlinkWithIcon.setVisible(true); @@ -344,65 +341,47 @@ public class ProposalDisplay { proposalFeeTextField.setText(bsqFormatter.formatCoinWithCode(daoFacade.getProposalFee(chainHeight))); } - public void clearForm() { - if (uidTextField != null) uidTextField.clear(); - if (nameTextField != null) nameTextField.clear(); - if (titleTextField != null) titleTextField.clear(); - if (descriptionTextArea != null) descriptionTextArea.clear(); - if (linkInputTextField != null) linkInputTextField.clear(); - if (linkHyperlinkWithIcon != null) linkHyperlinkWithIcon.clear(); - if (requestedBsqTextField != null) requestedBsqTextField.clear(); - if (bsqAddressTextField != null) bsqAddressTextField.clear(); - if (paramComboBox != null) paramComboBox.getSelectionModel().clearSelection(); - if (paramValueTextField != null) paramValueTextField.clear(); - if (bondedRoleTypeComboBox != null) bondedRoleTypeComboBox.getSelectionModel().clearSelection(); - if (confiscateBondComboBox != null) confiscateBondComboBox.getSelectionModel().clearSelection(); - if (txIdTextField != null) txIdTextField.cleanup(); - if (descriptionTextArea != null) descriptionTextArea.textProperty().removeListener(descriptionTextAreaListener); + private void addListeners() { + inputControls.stream() + .filter(Objects::nonNull).forEach(inputControl -> { + inputControl.textProperty().addListener(inputListener); + inputControl.focusedProperty().addListener(focusOutListener); + }); + comboBoxes.stream() + .filter(Objects::nonNull).forEach(comboBox -> { + comboBox.getSelectionModel().selectedItemProperty().addListener(inputListener); + }); } - public void fillWithMock() { - if (uidTextField != null) - uidTextField.setText(UUID.randomUUID().toString()); - nameTextField.setText("Manfred Karrer"); - if (titleTextField != null) - titleTextField.setText("Development work November 2017"); - if (descriptionTextArea != null) - descriptionTextArea.setText("Development work"); - linkInputTextField.setText("https://github.com/bisq-network/compensation/issues/12"); - if (requestedBsqTextField != null) - requestedBsqTextField.setText("14000"); - if (bsqAddressTextField != null) - bsqAddressTextField.setText("B" + bsqWalletService.getUnusedAddress().toBase58()); + public void removeListeners() { + inputControls.stream() + .filter(Objects::nonNull).forEach(inputControl -> { + inputControl.textProperty().removeListener(inputListener); + inputControl.focusedProperty().removeListener(focusOutListener); + }); + comboBoxes.stream() + .filter(Objects::nonNull).forEach(comboBox -> { + comboBox.getSelectionModel().selectedItemProperty().removeListener(inputListener); + }); + } - if (paramComboBox != null) - paramComboBox.getSelectionModel().select(8); // PROPOSAL_FEE - if (paramValueTextField != null) - paramValueTextField.setText("333"); + public void clearForm() { + inputControls.stream().filter(Objects::nonNull).forEach(TextInputControl::clear); + + if (uidTextField != null) uidTextField.clear(); + if (linkHyperlinkWithIcon != null) linkHyperlinkWithIcon.clear(); + if (txIdTextField != null) txIdTextField.cleanup(); + + comboBoxes.stream() + .filter(Objects::nonNull).forEach(comboBox -> { + comboBox.getSelectionModel().clearSelection(); + }); } public void setEditable(boolean isEditable) { - nameTextField.setEditable(isEditable); - if (titleTextField != null) - titleTextField.setEditable(isEditable); - if (descriptionTextArea != null) - descriptionTextArea.setEditable(isEditable); - linkInputTextField.setEditable(isEditable); - if (requestedBsqTextField != null) - requestedBsqTextField.setEditable(isEditable); - if (bsqAddressTextField != null) - bsqAddressTextField.setEditable(isEditable); - - if (paramComboBox != null) - paramComboBox.setDisable(!isEditable); - if (paramValueTextField != null) - paramValueTextField.setEditable(isEditable); - - if (confiscateBondComboBox != null) - confiscateBondComboBox.setDisable(!isEditable); - - if (bondedRoleTypeComboBox != null) - bondedRoleTypeComboBox.setDisable(!isEditable); + inputControls.stream().filter(Objects::nonNull).forEach(e -> e.setEditable(!isEditable)); + comboBoxes.stream() + .filter(Objects::nonNull).forEach(comboBox -> comboBox.setEditable(!isEditable)); linkInputTextField.setVisible(true); linkInputTextField.setManaged(true); @@ -452,4 +431,20 @@ public class ProposalDisplay { return scrollPane; } + + public void fillWithMock() { + if (uidTextField != null) + uidTextField.setText(UUID.randomUUID().toString()); + nameTextField.setText("Manfred Karrer"); + linkInputTextField.setText("https://github.com/bisq-network/compensation/issues/12"); + if (requestedBsqTextField != null) + requestedBsqTextField.setText("14000"); + if (bsqAddressTextField != null) + bsqAddressTextField.setText("B" + bsqWalletService.getUnusedAddress().toBase58()); + + if (paramComboBox != null) + paramComboBox.getSelectionModel().select(8); // PROPOSAL_FEE + if (paramValueTextField != null) + paramValueTextField.setText("333"); + } } diff --git a/src/main/java/bisq/desktop/main/dao/proposal/make/MakeProposalView.java b/src/main/java/bisq/desktop/main/dao/proposal/make/MakeProposalView.java index ed626a24a5..887d62c1a9 100644 --- a/src/main/java/bisq/desktop/main/dao/proposal/make/MakeProposalView.java +++ b/src/main/java/bisq/desktop/main/dao/proposal/make/MakeProposalView.java @@ -19,6 +19,7 @@ package bisq.desktop.main.dao.proposal.make; import bisq.desktop.common.view.ActivatableView; import bisq.desktop.common.view.FxmlView; +import bisq.desktop.components.InputTextField; import bisq.desktop.main.dao.proposal.ProposalDisplay; import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.util.GUIUtil; @@ -37,7 +38,6 @@ import bisq.core.dao.state.ext.Param; import bisq.core.dao.state.period.DaoPhase; import bisq.core.dao.voting.ValidationException; import bisq.core.dao.voting.proposal.Proposal; -import bisq.core.dao.voting.proposal.ProposalConsensus; import bisq.core.dao.voting.proposal.ProposalType; import bisq.core.dao.voting.proposal.ProposalWithTransaction; import bisq.core.locale.Res; @@ -47,6 +47,8 @@ import bisq.core.util.BsqFormatter; import bisq.network.p2p.P2PService; +import bisq.common.app.DevEnv; + import org.bitcoinj.core.Coin; import org.bitcoinj.core.InsufficientMoneyException; import org.bitcoinj.core.Transaction; @@ -67,6 +69,8 @@ import java.io.IOException; import java.util.Arrays; import java.util.List; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import javax.annotation.Nullable; @@ -74,7 +78,6 @@ import javax.annotation.Nullable; import static bisq.desktop.util.FormBuilder.addButtonAfterGroup; import static bisq.desktop.util.FormBuilder.addLabelComboBox; import static bisq.desktop.util.FormBuilder.addTitledGroupBg; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @FxmlView @@ -232,7 +235,8 @@ public class MakeProposalView extends ActivatableView implements () -> { proposalDisplay.clearForm(); proposalTypeComboBox.getSelectionModel().clearSelection(); - new Popup<>().confirmation(Res.get("dao.tx.published.success")).show(); + if (!DevEnv.isDevMode()) + new Popup<>().confirmation(Res.get("dao.tx.published.success")).show(); }, errorMessage -> new Popup<>().warning(errorMessage).show()); } @@ -241,7 +245,6 @@ public class MakeProposalView extends ActivatableView implements throws InsufficientMoneyException, TransactionVerificationException, ValidationException, WalletException, IOException { - validateInputs(); BondedRole bondedRole; switch (type) { case COMPENSATION_REQUEST: @@ -249,13 +252,7 @@ public class MakeProposalView extends ActivatableView implements "proposalDisplay.requestedBsqTextField must not be null"); checkNotNull(proposalDisplay.bsqAddressTextField, "proposalDisplay.bsqAddressTextField must not be null"); - checkNotNull(proposalDisplay.titleTextField, - "proposalDisplay.titleTextField must not be null"); - checkNotNull(proposalDisplay.descriptionTextArea, - "proposalDisplay.descriptionTextArea must not be null"); return daoFacade.getCompensationProposalWithTransaction(proposalDisplay.nameTextField.getText(), - proposalDisplay.titleTextField.getText(), - proposalDisplay.descriptionTextArea.getText(), proposalDisplay.linkInputTextField.getText(), bsqFormatter.parseToCoin(proposalDisplay.requestedBsqTextField.getText()), proposalDisplay.bsqAddressTextField.getText()); @@ -274,10 +271,6 @@ public class MakeProposalView extends ActivatableView implements "proposalDisplay.paramComboBox must no tbe null"); checkNotNull(proposalDisplay.paramValueTextField, "proposalDisplay.paramValueTextField must no tbe null"); - checkNotNull(proposalDisplay.titleTextField, - "proposalDisplay.titleTextField must not be null"); - checkNotNull(proposalDisplay.descriptionTextArea, - "proposalDisplay.descriptionTextArea must not be null"); Param selectedParam = proposalDisplay.paramComboBox.getSelectionModel().getSelectedItem(); if (selectedParam == null) throw new ValidationException("selectedParam is null"); @@ -292,8 +285,6 @@ public class MakeProposalView extends ActivatableView implements } //TODO add more custom param validation return daoFacade.getParamProposalWithTransaction(proposalDisplay.nameTextField.getText(), - proposalDisplay.titleTextField.getText(), - proposalDisplay.descriptionTextArea.getText(), proposalDisplay.linkInputTextField.getText(), selectedParam, paramValue); @@ -303,14 +294,8 @@ public class MakeProposalView extends ActivatableView implements case CONFISCATE_BOND: checkNotNull(proposalDisplay.confiscateBondComboBox, "proposalDisplay.confiscateBondComboBox must not be null"); - checkNotNull(proposalDisplay.titleTextField, - "proposalDisplay.titleTextField must not be null"); - checkNotNull(proposalDisplay.descriptionTextArea, - "proposalDisplay.descriptionTextArea must not be null"); bondedRole = proposalDisplay.confiscateBondComboBox.getSelectionModel().getSelectedItem(); return daoFacade.getConfiscateBondProposalWithTransaction(proposalDisplay.nameTextField.getText(), - proposalDisplay.titleTextField.getText(), - proposalDisplay.descriptionTextArea.getText(), proposalDisplay.linkInputTextField.getText(), bondedRole.getHash()); default: @@ -330,6 +315,8 @@ public class MakeProposalView extends ActivatableView implements createButton = addButtonAfterGroup(root, proposalDisplay.incrementAndGetGridRow(), Res.get("dao.proposal.create.create.button")); setCreateButtonHandler(); + proposalDisplay.addInputChangedListener(this::updateButtonState); + updateButtonState(); } } @@ -337,13 +324,14 @@ public class MakeProposalView extends ActivatableView implements if (proposalDisplay != null) { proposalDisplay.removeAllFields(); GUIUtil.removeChildrenFromGridPaneRows(root, 1, proposalDisplay.getGridRow()); + proposalDisplay.removeInputChangedListener(this::updateButtonState); + proposalDisplay.removeListeners(); proposalDisplay = null; } } private void setCreateButtonHandler() { createButton.setOnAction(event -> { - // TODO break up in methods if (GUIUtil.isReadyForTxBroadcast(p2PService, walletsSetup)) { publishMyProposal(selectedProposalType); } else { @@ -352,14 +340,21 @@ public class MakeProposalView extends ActivatableView implements }); } - private void validateInputs() { - // We check in proposalDisplay that no invalid input as allowed - if (proposalDisplay.descriptionTextArea != null) { - checkArgument(ProposalConsensus.isDescriptionSizeValid(proposalDisplay.descriptionTextArea.getText()), - "descriptionText must not be longer than " + - ProposalConsensus.getMaxLengthDescriptionText() + " chars"); - } - // TODO add more checks for all input fields + private void updateButtonState() { + AtomicBoolean inputsValid = new AtomicBoolean(true); + proposalDisplay.getInputControls().stream() + .filter(Objects::nonNull).forEach(e -> { + if (e instanceof InputTextField) { + InputTextField inputTextField = (InputTextField) e; + inputsValid.set(inputsValid.get() && inputTextField.getValidator().validate(e.getText()).isValid); + } + }); + proposalDisplay.getComboBoxes().stream() + .filter(Objects::nonNull).forEach(comboBox -> { + inputsValid.set(inputsValid.get() && comboBox.getSelectionModel().getSelectedItem() != null); + }); + + createButton.setDisable(!inputsValid.get()); } } diff --git a/src/main/java/bisq/desktop/main/dao/results/ResultsView.java b/src/main/java/bisq/desktop/main/dao/results/ResultsView.java index 64d140ea41..4e0ac0170e 100644 --- a/src/main/java/bisq/desktop/main/dao/results/ResultsView.java +++ b/src/main/java/bisq/desktop/main/dao/results/ResultsView.java @@ -25,7 +25,6 @@ import bisq.desktop.components.AutoTooltipLabel; import bisq.desktop.components.AutoTooltipTableColumn; import bisq.desktop.components.TableGroupHeadline; import bisq.desktop.components.TitledGroupBg; -import bisq.desktop.main.dao.results.combo.VotesPerProposalTableView; import bisq.desktop.main.dao.results.model.ResultsOfCycle; import bisq.desktop.main.dao.results.proposals.ProposalResultsGridPane; import bisq.desktop.main.dao.results.votes.VoteResultsGridPane; @@ -58,7 +57,6 @@ import javax.inject.Inject; import javafx.fxml.FXML; -import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; @@ -105,20 +103,15 @@ public class ResultsView extends ActivatableViewAndModel tableView; - private final ObservableList itemList = FXCollections.observableArrayList(); private final SortedList sortedList = new SortedList<>(itemList); private ChangeListener selectedItemListener; - - private VotesPerProposalTableView votesPerProposalTableView; private ProposalResultsGridPane proposalResultsGridPane; private VoteResultsGridPane voteResultsGridPane; private GridPane gridPane; private HBox hBox; - private Label directionLabel; /////////////////////////////////////////////////////////////////////////////////////////// @@ -154,14 +147,10 @@ public class ResultsView extends ActivatableViewAndModel onResultsListItemSelected(newValue); } - @Override - public void onSelectedEvaluatedProposal(EvaluatedProposal evaluatedProposal) { - voteResultsGridPane.onSelectedEvaluatedProposal(evaluatedProposal); - } - - @Override - public void onSelectedDecryptedVote(DecryptedVote decryptedVote) { - proposalResultsGridPane.onSelectedDecryptedVote(decryptedVote); - } - @Override protected void activate() { tableView.getSelectionModel().selectedItemProperty().addListener(selectedItemListener); @@ -193,6 +172,21 @@ public class ResultsView extends ActivatableViewAndModel