mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 15:00:30 +01:00
Move display of selected proposal into popup instead of showing it inline
This commit is contained in:
parent
0099c9c5e3
commit
4ba8342f20
4 changed files with 302 additions and 163 deletions
|
@ -1689,9 +1689,8 @@ dao.proposal.myVote.stake=Vote weight from stake
|
|||
dao.proposal.myVote.blindVoteTxId=Blind vote transaction ID
|
||||
dao.proposal.myVote.revealTxId=Vote reveal transaction ID
|
||||
dao.proposal.myVote.stake.prompt=Max. available balance for voting: {0}
|
||||
dao.proposal.votes.header=Vote on all proposals
|
||||
dao.proposal.votes.header.voted=My vote
|
||||
dao.proposal.myVote.button=Vote on all proposals
|
||||
dao.proposal.votes.header=Set weight for all votes and publish them
|
||||
dao.proposal.myVote.button=Publish votes
|
||||
dao.proposal.create.selectProposalType=Select proposal type
|
||||
dao.proposal.create.phase.inactive=Please wait until the next proposal phase
|
||||
dao.proposal.create.proposalType=Proposal type
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package bisq.desktop.main.dao.governance.proposals;
|
||||
|
||||
import bisq.desktop.Navigation;
|
||||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.AutoTooltipLabel;
|
||||
|
@ -29,8 +28,8 @@ import bisq.desktop.components.TableGroupHeadline;
|
|||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.components.TxIdTextField;
|
||||
import bisq.desktop.main.dao.governance.PhasesView;
|
||||
import bisq.desktop.main.dao.governance.ProposalDisplay;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.main.overlays.windows.SelectProposalWindow;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
import bisq.desktop.util.validation.BsqValidator;
|
||||
|
@ -42,7 +41,6 @@ import bisq.core.btc.wallet.BsqWalletService;
|
|||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.blindvote.BlindVoteConsensus;
|
||||
import bisq.core.dao.governance.myvote.MyVote;
|
||||
import bisq.core.dao.governance.proposal.param.ChangeParamValidator;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
|
@ -71,7 +69,6 @@ import com.jfoenix.controls.JFXButton;
|
|||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
|
@ -101,11 +98,13 @@ import java.util.ArrayList;
|
|||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.*;
|
||||
import static bisq.desktop.util.Layout.INITIAL_WINDOW_HEIGHT;
|
||||
|
||||
@FxmlView
|
||||
public class ProposalsView extends ActivatableView<GridPane, Void> implements BsqBalanceListener, DaoStateListener {
|
||||
|
@ -113,11 +112,10 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
private final BsqWalletService bsqWalletService;
|
||||
private final PhasesView phasesView;
|
||||
private final DaoStateService daoStateService;
|
||||
private final ChangeParamValidator changeParamValidator;
|
||||
private final Preferences preferences;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final BSFormatter btcFormatter;
|
||||
private final Navigation navigation;
|
||||
private final SelectProposalWindow selectProposalWindow;
|
||||
|
||||
private final ObservableList<ProposalsListItem> listItems = FXCollections.observableArrayList();
|
||||
private final SortedList<ProposalsListItem> sortedList = new SortedList<>(listItems);
|
||||
|
@ -125,20 +123,15 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
private final List<Node> voteFields = new ArrayList<>();
|
||||
|
||||
private TableView<ProposalsListItem> tableView;
|
||||
private TitledGroupBg voteTitledGroupBg;
|
||||
private Label voteButtonInfoLabel;
|
||||
private TxIdTextField revealTxIdTextField, blindVoteTxIdTextField;
|
||||
private TextField meritTextField;
|
||||
private VBox blindVoteTxIdContainer, revealTxIdContainer;
|
||||
private Button removeProposalButton, acceptButton, rejectButton, ignoreButton, voteButton;
|
||||
private Button voteButton;
|
||||
private InputTextField stakeInputTextField;
|
||||
private ScrollPane proposalDisplayView;
|
||||
private GridPane proposalDisplayGridPane;
|
||||
private BusyAnimation voteButtonBusyAnimation;
|
||||
private ProposalDisplay proposalDisplay;
|
||||
|
||||
private int gridRow = 0;
|
||||
private boolean proposalDisplayInitialized;
|
||||
private ProposalsListItem selectedItem;
|
||||
private DaoPhase.Phase currentPhase;
|
||||
private ListChangeListener<Proposal> proposalListChangeListener;
|
||||
|
@ -147,6 +140,16 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
private Subscription selectedProposalSubscription, phaseSubscription;
|
||||
private boolean areVoteButtonsVisible;
|
||||
private TableColumn<ProposalsListItem, ProposalsListItem> lastColumn;
|
||||
private String shownVoteOnProposalWindowForTxId = "";
|
||||
|
||||
private final double initialProposalTableViewHeight = 180;
|
||||
private final double pixelsPerProposalTableRow = (initialProposalTableViewHeight - 28) / 4.0;
|
||||
private final Function<Double, Double> proposalTableViewHeight = (screenSize) -> {
|
||||
int extraRows = screenSize <= INITIAL_WINDOW_HEIGHT ? 0 : (int) ((screenSize - INITIAL_WINDOW_HEIGHT) / pixelsPerProposalTableRow);
|
||||
return extraRows == 0 ? initialProposalTableViewHeight : Math.ceil(initialProposalTableViewHeight + (extraRows * pixelsPerProposalTableRow));
|
||||
};
|
||||
private ChangeListener<Number> bisqWindowVerticalSizeListener;
|
||||
private TableGroupHeadline proposalsHeadline;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -158,20 +161,18 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
BsqWalletService bsqWalletService,
|
||||
PhasesView phasesView,
|
||||
DaoStateService daoStateService,
|
||||
ChangeParamValidator changeParamValidator,
|
||||
Preferences preferences,
|
||||
BsqFormatter bsqFormatter,
|
||||
BSFormatter btcFormatter,
|
||||
Navigation navigation) {
|
||||
SelectProposalWindow selectProposalWindow) {
|
||||
this.daoFacade = daoFacade;
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
this.phasesView = phasesView;
|
||||
this.daoStateService = daoStateService;
|
||||
this.changeParamValidator = changeParamValidator;
|
||||
this.preferences = preferences;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
this.btcFormatter = btcFormatter;
|
||||
this.navigation = navigation;
|
||||
this.selectProposalWindow = selectProposalWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -180,15 +181,21 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
|
||||
gridRow = phasesView.addGroup(root, gridRow);
|
||||
|
||||
proposalDisplayGridPane = new GridPane();
|
||||
|
||||
createProposalsTableView();
|
||||
createEmptyProposalDisplay();
|
||||
createVoteView();
|
||||
|
||||
ballotListChangeListener = c -> updateListItems();
|
||||
proposalListChangeListener = c -> updateListItems();
|
||||
|
||||
bisqWindowVerticalSizeListener = (observable, oldValue, newValue) -> {
|
||||
double newTableViewHeight = proposalTableViewHeight.apply(newValue.doubleValue());
|
||||
if (tableView.getHeight() != newTableViewHeight) {
|
||||
tableView.setMinHeight(newTableViewHeight);
|
||||
double diff = newTableViewHeight - tableView.getHeight();
|
||||
proposalsHeadline.setMaxHeight(proposalsHeadline.getHeight() + diff);
|
||||
}
|
||||
};
|
||||
|
||||
stakeListener = (observable, oldValue, newValue) -> updateViews();
|
||||
}
|
||||
|
||||
|
@ -218,8 +225,10 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
bsqWalletService.getUnlockingBondsBalance());
|
||||
|
||||
updateListItems();
|
||||
GUIUtil.setFitToRowsForTableView(tableView, 38, 28, 2, 6);
|
||||
GUIUtil.setFitToRowsForTableView(tableView, 38, 28, 4, 4);
|
||||
updateViews();
|
||||
|
||||
root.getScene().heightProperty().addListener(bisqWindowVerticalSizeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -242,8 +251,6 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
}
|
||||
if (voteButton != null)
|
||||
voteButton.setOnAction(null);
|
||||
if (removeProposalButton != null)
|
||||
removeProposalButton.setOnAction(null);
|
||||
|
||||
listItems.forEach(ProposalsListItem::cleanup);
|
||||
tableView.getSelectionModel().clearSelection();
|
||||
|
@ -316,89 +323,39 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
listItems.clear();
|
||||
|
||||
fillListItems();
|
||||
|
||||
if (listItems.isEmpty())
|
||||
hideProposalDisplay();
|
||||
|
||||
|
||||
if (!tableView.getItems().isEmpty()) {
|
||||
onSelectProposal(tableView.getItems().get(0));
|
||||
onSelectProposal(null);
|
||||
}
|
||||
|
||||
GUIUtil.setFitToRowsForTableView(tableView, 38, 28, 2, 6);
|
||||
}
|
||||
|
||||
private void createAllFieldsOnProposalDisplay(Proposal proposal, @Nullable Ballot ballot,
|
||||
private void showVoteOnProposalWindow(Proposal proposal, @Nullable Ballot ballot,
|
||||
@Nullable EvaluatedProposal evaluatedProposal) {
|
||||
proposalDisplayView.setVisible(true);
|
||||
proposalDisplayView.setManaged(true);
|
||||
|
||||
proposalDisplay.createAllFields(Res.get("dao.proposal.selectedProposal"), 0, 0, proposal.getType(),
|
||||
false);
|
||||
proposalDisplay.setEditable(false);
|
||||
if (!shownVoteOnProposalWindowForTxId.equals(proposal.getTxId())) {
|
||||
shownVoteOnProposalWindowForTxId = proposal.getTxId();
|
||||
|
||||
proposalDisplay.applyProposalPayload(proposal);
|
||||
selectProposalWindow.show(proposal, evaluatedProposal, ballot);
|
||||
selectProposalWindow.onAccept(() -> {
|
||||
shownVoteOnProposalWindowForTxId = "";
|
||||
onAccept();
|
||||
});
|
||||
selectProposalWindow.onReject(() -> {
|
||||
shownVoteOnProposalWindowForTxId = "";
|
||||
onReject();
|
||||
});
|
||||
selectProposalWindow.onIgnore(() -> {
|
||||
shownVoteOnProposalWindowForTxId = "";
|
||||
onIgnore();
|
||||
});
|
||||
selectProposalWindow.onRemove(() -> {
|
||||
shownVoteOnProposalWindowForTxId = "";
|
||||
onRemoveProposal();
|
||||
});
|
||||
|
||||
proposalDisplay.applyEvaluatedProposal(evaluatedProposal);
|
||||
|
||||
Tuple2<Long, Long> meritAndStakeTuple = daoFacade.getMeritAndStakeForProposal(proposal.getTxId());
|
||||
long merit = meritAndStakeTuple.first;
|
||||
long stake = meritAndStakeTuple.second;
|
||||
proposalDisplay.applyBallotAndVoteWeight(ballot, merit, stake);
|
||||
|
||||
proposalDisplayInitialized = true;
|
||||
|
||||
removeProposalButton = addButtonAfterGroup(proposalDisplayGridPane, proposalDisplay.incrementAndGetGridRow(), Res.get("shared.remove"));
|
||||
removeProposalButton.setOnAction(event -> onRemoveProposal());
|
||||
onPhaseChanged(daoFacade.phaseProperty().get());
|
||||
|
||||
Tuple3<Button, Button, Button> tuple = add3ButtonsAfterGroup(proposalDisplayGridPane,
|
||||
proposalDisplay.incrementAndGetGridRow(),
|
||||
Res.get("dao.proposal.myVote.accept"),
|
||||
Res.get("dao.proposal.myVote.reject"),
|
||||
Res.get("dao.proposal.myVote.removeMyVote"));
|
||||
acceptButton = tuple.first;
|
||||
acceptButton.setDefaultButton(false);
|
||||
rejectButton = tuple.second;
|
||||
ignoreButton = tuple.third;
|
||||
acceptButton.setOnAction(event -> onAccept());
|
||||
rejectButton.setOnAction(event -> onReject());
|
||||
ignoreButton.setOnAction(event -> onIgnore());
|
||||
|
||||
voteButtons.clear();
|
||||
voteButtons.add(voteButton);
|
||||
voteButtons.add(acceptButton);
|
||||
voteButtons.add(rejectButton);
|
||||
voteButtons.add(ignoreButton);
|
||||
}
|
||||
|
||||
private void hideProposalDisplay() {
|
||||
if (proposalDisplayInitialized) {
|
||||
proposalDisplay.removeAllFields();
|
||||
proposalDisplayView.setVisible(false);
|
||||
proposalDisplayView.setManaged(false);
|
||||
}
|
||||
if (removeProposalButton != null) {
|
||||
removeProposalButton.setManaged(false);
|
||||
removeProposalButton.setVisible(false);
|
||||
}
|
||||
|
||||
if (acceptButton != null) {
|
||||
acceptButton.setManaged(false);
|
||||
acceptButton.setVisible(false);
|
||||
}
|
||||
if (rejectButton != null) {
|
||||
rejectButton.setManaged(false);
|
||||
rejectButton.setVisible(false);
|
||||
}
|
||||
if (ignoreButton != null) {
|
||||
ignoreButton.setManaged(false);
|
||||
ignoreButton.setVisible(false);
|
||||
selectProposalWindow.onClose(() -> {
|
||||
shownVoteOnProposalWindowForTxId = "";
|
||||
tableView.getSelectionModel().clearSelection();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Handlers
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -407,15 +364,6 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
if (phase != null && !phase.equals(currentPhase)) {
|
||||
currentPhase = phase;
|
||||
stakeInputTextField.clear();
|
||||
onSelectProposal(selectedItem);
|
||||
}
|
||||
|
||||
if (removeProposalButton != null) {
|
||||
boolean doShowRemoveButton = phase == DaoPhase.Phase.PROPOSAL &&
|
||||
selectedItem != null &&
|
||||
daoFacade.isMyProposal(selectedItem.getProposal());
|
||||
removeProposalButton.setVisible(doShowRemoveButton);
|
||||
removeProposalButton.setManaged(doShowRemoveButton);
|
||||
}
|
||||
|
||||
updateViews();
|
||||
|
@ -427,9 +375,7 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
new Popup<>().warning(Res.get("dao.proposal.active.remove.confirm"))
|
||||
.actionButtonText(Res.get("dao.proposal.active.remove.doRemove"))
|
||||
.onAction(() -> {
|
||||
if (daoFacade.removeMyProposal(proposal)) {
|
||||
hideProposalDisplay();
|
||||
} else {
|
||||
if (!daoFacade.removeMyProposal(proposal)) {
|
||||
new Popup<>().warning(Res.get("dao.proposal.active.remove.failed")).show();
|
||||
}
|
||||
tableView.getSelectionModel().clearSelection();
|
||||
|
@ -448,14 +394,11 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
.findAny()
|
||||
.orElse(null);
|
||||
|
||||
createAllFieldsOnProposalDisplay(selectedItem.getProposal(), selectedItem.getBallot(), evaluatedProposal);
|
||||
showVoteOnProposalWindow(selectedItem.getProposal(), selectedItem.getBallot(), evaluatedProposal);
|
||||
applyMerit();
|
||||
} else {
|
||||
hideProposalDisplay();
|
||||
}
|
||||
onPhaseChanged(daoFacade.phaseProperty().get());
|
||||
|
||||
updateViews();
|
||||
onPhaseChanged(daoFacade.phaseProperty().get());
|
||||
}
|
||||
|
||||
private void applyMerit() {
|
||||
|
@ -479,20 +422,20 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
|
||||
private void onAccept() {
|
||||
daoFacade.setVote(getBallotListItem().getBallot(), new Vote(true));
|
||||
proposalDisplay.applyBallot(getBallotListItem().getBallot());
|
||||
updateStateAfterVote();
|
||||
tableView.getSelectionModel().clearSelection();
|
||||
}
|
||||
|
||||
private void onReject() {
|
||||
daoFacade.setVote(getBallotListItem().getBallot(), new Vote(false));
|
||||
proposalDisplay.applyBallot(getBallotListItem().getBallot());
|
||||
updateStateAfterVote();
|
||||
tableView.getSelectionModel().clearSelection();
|
||||
}
|
||||
|
||||
private void onIgnore() {
|
||||
daoFacade.setVote(getBallotListItem().getBallot(), null);
|
||||
proposalDisplay.applyBallot(getBallotListItem().getBallot());
|
||||
updateStateAfterVote();
|
||||
tableView.getSelectionModel().clearSelection();
|
||||
}
|
||||
|
||||
private void onVote() {
|
||||
|
@ -545,13 +488,6 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
return selectedItem;
|
||||
}
|
||||
|
||||
private Optional<Vote> getVote(@Nullable Ballot ballot) {
|
||||
if (ballot == null)
|
||||
return Optional.empty();
|
||||
else
|
||||
return ballot.getVoteAsOptional();
|
||||
}
|
||||
|
||||
private void updateViews() {
|
||||
boolean isBlindVotePhaseButNotLastBlock = isBlindVotePhaseButNotLastBlock();
|
||||
boolean hasVotedOnProposal = hasVotedOnProposal();
|
||||
|
@ -560,17 +496,8 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
|
||||
List<MyVote> myVoteListForCycle = daoFacade.getMyVoteListForCycle();
|
||||
boolean hasAlreadyVoted = !myVoteListForCycle.isEmpty();
|
||||
if (selectedItem != null && acceptButton != null) {
|
||||
Optional<Vote> optionalVote = getVote(selectedItem.getBallot());
|
||||
boolean isPresent = optionalVote.isPresent();
|
||||
boolean isAccepted = isPresent && optionalVote.get().isAccepted();
|
||||
acceptButton.setDisable((isPresent && isAccepted));
|
||||
rejectButton.setDisable((isPresent && !isAccepted));
|
||||
ignoreButton.setDisable(!isPresent);
|
||||
|
||||
if (selectedItem != null) {
|
||||
stakeInputTextField.setMouseTransparent(hasAlreadyVoted || !isBlindVotePhaseButNotLastBlock);
|
||||
} else {
|
||||
stakeInputTextField.setMouseTransparent(true);
|
||||
}
|
||||
|
||||
boolean hasProposals = !daoFacade.getActiveOrMyUnconfirmedProposals().isEmpty();
|
||||
|
@ -595,7 +522,6 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
revealTxIdContainer.setManaged(false);
|
||||
|
||||
if (hasAlreadyVoted) {
|
||||
voteTitledGroupBg.setText(Res.get("dao.proposal.votes.header.voted"));
|
||||
if (myVoteListForCycle.size() == 1) {
|
||||
Optional<MyVote> optionalMyVote = myVoteListForCycle.stream()
|
||||
.filter(myVote -> daoFacade.isTxInCorrectCycle(myVote.getHeight(), daoFacade.getChainHeight()))
|
||||
|
@ -660,7 +586,7 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void createProposalsTableView() {
|
||||
TableGroupHeadline proposalsHeadline = new TableGroupHeadline(Res.get("dao.proposal.active.header"));
|
||||
proposalsHeadline = new TableGroupHeadline(Res.get("dao.proposal.active.header"));
|
||||
GridPane.setRowIndex(proposalsHeadline, ++gridRow);
|
||||
GridPane.setMargin(proposalsHeadline, new Insets(Layout.GROUP_DISTANCE, -10, -10, -10));
|
||||
root.getChildren().add(proposalsHeadline);
|
||||
|
@ -672,24 +598,15 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
createProposalColumns();
|
||||
GridPane.setRowIndex(tableView, gridRow);
|
||||
GridPane.setHgrow(tableView, Priority.ALWAYS);
|
||||
GridPane.setVgrow(tableView, Priority.SOMETIMES);
|
||||
GridPane.setMargin(tableView, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, -10, 5, -10));
|
||||
root.getChildren().add(tableView);
|
||||
|
||||
tableView.setItems(sortedList);
|
||||
}
|
||||
|
||||
private void createEmptyProposalDisplay() {
|
||||
proposalDisplay = new ProposalDisplay(proposalDisplayGridPane, bsqFormatter, daoFacade,
|
||||
changeParamValidator, navigation, preferences);
|
||||
proposalDisplayView = proposalDisplay.getView();
|
||||
GridPane.setMargin(proposalDisplayView, new Insets(0, -10, 0, -10));
|
||||
GridPane.setRowIndex(proposalDisplayView, ++gridRow);
|
||||
GridPane.setHgrow(proposalDisplayView, Priority.ALWAYS);
|
||||
root.getChildren().add(proposalDisplayView);
|
||||
}
|
||||
|
||||
private void createVoteView() {
|
||||
voteTitledGroupBg = addTitledGroupBg(root, ++gridRow, 4,
|
||||
TitledGroupBg voteTitledGroupBg = addTitledGroupBg(root, ++gridRow, 4,
|
||||
Res.get("dao.proposal.votes.header"), 20);
|
||||
voteTitledGroupBg.getStyleClass().add("last");
|
||||
voteFields.add(voteTitledGroupBg);
|
||||
|
@ -867,7 +784,7 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
JFXButton iconButton = item.getIconButton();
|
||||
if (iconButton != null) {
|
||||
iconButton.setOnAction(e -> {
|
||||
onSelectProposal(item);
|
||||
selectedItem = item;
|
||||
if (areVoteButtonsVisible) {
|
||||
if (iconButton.getUserData() == ProposalsListItem.IconButtonTypes.ACCEPT)
|
||||
onReject();
|
||||
|
|
|
@ -125,6 +125,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
int extraRows = screenSize <= INITIAL_WINDOW_HEIGHT ? 0 : (int) ((screenSize - INITIAL_WINDOW_HEIGHT) / pixelsPerOfferTableRow);
|
||||
return extraRows == 0 ? initialOfferTableViewHeight : Math.ceil(initialOfferTableViewHeight + ((extraRows + 1) * pixelsPerOfferTableRow));
|
||||
};
|
||||
private ChangeListener<Number> bisqWindowVerticalSizeListener;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, lifecycle
|
||||
|
@ -141,12 +142,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
|
||||
@Override
|
||||
public void initialize() {
|
||||
changeListener = c -> updateChartData();
|
||||
|
||||
currencyListItemsListener = c -> {
|
||||
if (model.getSelectedCurrencyListItem().isPresent())
|
||||
currencyComboBox.getSelectionModel().select(model.getSelectedCurrencyListItem().get());
|
||||
};
|
||||
createListener();
|
||||
|
||||
final Tuple3<VBox, Label, ComboBox<CurrencyListItem>> currencyComboBoxTuple = addTopLabelComboBox(Res.get("shared.currency"),
|
||||
Res.get("list.currency.select"), 0);
|
||||
|
@ -268,6 +264,23 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
|
||||
buyOfferTableView.setItems(model.getTopBuyOfferList());
|
||||
sellOfferTableView.setItems(model.getTopSellOfferList());
|
||||
|
||||
buyOfferTableView.getSelectionModel().selectedItemProperty().addListener(buyTableRowSelectionListener);
|
||||
sellOfferTableView.getSelectionModel().selectedItemProperty().addListener(sellTableRowSelectionListener);
|
||||
|
||||
root.getScene().heightProperty().addListener(bisqWindowVerticalSizeListener);
|
||||
|
||||
updateChartData();
|
||||
}
|
||||
|
||||
private void createListener() {
|
||||
changeListener = c -> updateChartData();
|
||||
|
||||
currencyListItemsListener = c -> {
|
||||
if (model.getSelectedCurrencyListItem().isPresent())
|
||||
currencyComboBox.getSelectionModel().select(model.getSelectedCurrencyListItem().get());
|
||||
};
|
||||
|
||||
buyTableRowSelectionListener = (observable, oldValue, newValue) -> {
|
||||
model.preferences.setSellScreenCurrencyCode(model.getCurrencyCode());
|
||||
navigation.navigateTo(MainView.class, SellOfferView.class);
|
||||
|
@ -276,19 +289,14 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
model.preferences.setBuyScreenCurrencyCode(model.getCurrencyCode());
|
||||
navigation.navigateTo(MainView.class, BuyOfferView.class);
|
||||
};
|
||||
buyOfferTableView.getSelectionModel().selectedItemProperty().addListener(buyTableRowSelectionListener);
|
||||
sellOfferTableView.getSelectionModel().selectedItemProperty().addListener(sellTableRowSelectionListener);
|
||||
|
||||
ChangeListener<Number> bisqWindowVerticalSizeListener = (observable, oldValue, newValue) -> {
|
||||
bisqWindowVerticalSizeListener = (observable, oldValue, newValue) -> {
|
||||
double newTableViewHeight = offerTableViewHeight.apply(newValue.doubleValue());
|
||||
if (buyOfferTableView.getHeight() != newTableViewHeight) {
|
||||
buyOfferTableView.setMinHeight(newTableViewHeight);
|
||||
sellOfferTableView.setMinHeight(newTableViewHeight);
|
||||
}
|
||||
};
|
||||
root.getScene().heightProperty().addListener(bisqWindowVerticalSizeListener);
|
||||
|
||||
updateChartData();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
package bisq.desktop.main.overlays.windows;
|
||||
|
||||
import bisq.desktop.Navigation;
|
||||
import bisq.desktop.main.dao.governance.ProposalDisplay;
|
||||
import bisq.desktop.main.overlays.Overlay;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.myvote.MyVote;
|
||||
import bisq.core.dao.governance.proposal.param.ChangeParamValidator;
|
||||
import bisq.core.dao.state.model.governance.Ballot;
|
||||
import bisq.core.dao.state.model.governance.DaoPhase;
|
||||
import bisq.core.dao.state.model.governance.EvaluatedProposal;
|
||||
import bisq.core.dao.state.model.governance.Proposal;
|
||||
import bisq.core.dao.state.model.governance.Vote;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import bisq.common.util.Tuple2;
|
||||
import bisq.common.util.Tuple3;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.input.KeyCode;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.add2ButtonsAfterGroup;
|
||||
import static bisq.desktop.util.FormBuilder.add3ButtonsAfterGroup;
|
||||
import static bisq.desktop.util.FormBuilder.addButtonAfterGroup;
|
||||
|
||||
@Slf4j
|
||||
public class SelectProposalWindow extends Overlay<SelectProposalWindow> {
|
||||
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final DaoFacade daoFacade;
|
||||
private final ChangeParamValidator changeParamValidator;
|
||||
private final Navigation navigation;
|
||||
private final Preferences preferences;
|
||||
private Optional<Runnable> acceptHandlerOptional;
|
||||
private Optional<Runnable> rejectHandlerOptional;
|
||||
private Optional<Runnable> ignoreHandlerOptional;
|
||||
private Optional<Runnable> removeHandlerOptional;
|
||||
private Proposal proposal;
|
||||
private EvaluatedProposal evaluatedProposal;
|
||||
private Ballot ballot;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public SelectProposalWindow(BsqFormatter bsqFormatter, DaoFacade daoFacade,
|
||||
ChangeParamValidator changeParamValidator, Navigation navigation,
|
||||
Preferences preferences) {
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
this.daoFacade = daoFacade;
|
||||
this.changeParamValidator = changeParamValidator;
|
||||
this.navigation = navigation;
|
||||
this.preferences = preferences;
|
||||
}
|
||||
|
||||
public void show(Proposal proposal, EvaluatedProposal evaluatedProposal, Ballot ballot) {
|
||||
|
||||
this.proposal = proposal;
|
||||
this.evaluatedProposal = evaluatedProposal;
|
||||
this.ballot = ballot;
|
||||
|
||||
rowIndex = 0;
|
||||
width = 1000;
|
||||
createGridPane();
|
||||
headLine(Res.get("dao.proposal.selectedProposal"));
|
||||
message("");
|
||||
hideCloseButton();
|
||||
super.show();
|
||||
}
|
||||
|
||||
public void onAccept(Runnable acceptHandler) {
|
||||
this.acceptHandlerOptional = Optional.of(acceptHandler);
|
||||
}
|
||||
|
||||
public void onReject(Runnable rejectHandler) {
|
||||
this.rejectHandlerOptional = Optional.of(rejectHandler);
|
||||
}
|
||||
|
||||
public void onIgnore(Runnable ignoreHandler) {
|
||||
this.ignoreHandlerOptional = Optional.of(ignoreHandler);
|
||||
}
|
||||
|
||||
public void onRemove(Runnable removeHandler) {
|
||||
this.removeHandlerOptional = Optional.of(removeHandler);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@Override
|
||||
protected void createGridPane() {
|
||||
super.createGridPane();
|
||||
gridPane.getColumnConstraints().remove(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShow() {
|
||||
|
||||
display();
|
||||
|
||||
setupCloseKeyHandler(stage.getScene());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addMessage() {
|
||||
super.addMessage();
|
||||
|
||||
addContent(proposal, evaluatedProposal, ballot);
|
||||
}
|
||||
|
||||
private void addContent(Proposal proposal, EvaluatedProposal evaluatedProposal, Ballot ballot) {
|
||||
ProposalDisplay proposalDisplay = new ProposalDisplay(gridPane, bsqFormatter, daoFacade, changeParamValidator,
|
||||
navigation, preferences);
|
||||
proposalDisplay.createAllFields("", rowIndex, 0, proposal.getType(),
|
||||
false);
|
||||
proposalDisplay.setEditable(false);
|
||||
proposalDisplay.applyProposalPayload(proposal);
|
||||
proposalDisplay.applyEvaluatedProposal(evaluatedProposal);
|
||||
|
||||
Tuple2<Long, Long> meritAndStakeTuple = daoFacade.getMeritAndStakeForProposal(proposal.getTxId());
|
||||
long merit = meritAndStakeTuple.first;
|
||||
long stake = meritAndStakeTuple.second;
|
||||
proposalDisplay.applyBallotAndVoteWeight(ballot, merit, stake);
|
||||
|
||||
|
||||
List<MyVote> myVoteListForCycle = daoFacade.getMyVoteListForCycle();
|
||||
boolean hasAlreadyVoted = !myVoteListForCycle.isEmpty();
|
||||
|
||||
if (daoFacade.phaseProperty().get() == DaoPhase.Phase.PROPOSAL) {
|
||||
|
||||
Tuple2<Button, Button> proposalPhaseButtonsTuple = add2ButtonsAfterGroup(gridPane, proposalDisplay.incrementAndGetGridRow(), Res.get("shared.remove"), Res.get("shared.close"));
|
||||
Button removeProposalButton = proposalPhaseButtonsTuple.first;
|
||||
|
||||
boolean doShowRemoveButton = daoFacade.isMyProposal(proposal);
|
||||
|
||||
removeProposalButton.setOnAction(event -> {
|
||||
removeHandlerOptional.ifPresent(Runnable::run);
|
||||
doClose();
|
||||
});
|
||||
removeProposalButton.setVisible(doShowRemoveButton);
|
||||
removeProposalButton.setManaged(doShowRemoveButton);
|
||||
|
||||
proposalPhaseButtonsTuple.second.setOnAction(event -> doClose());
|
||||
|
||||
} else if (daoFacade.phaseProperty().get() == DaoPhase.Phase.BLIND_VOTE && !hasAlreadyVoted) {
|
||||
Tuple3<Button, Button, Button> tuple = add3ButtonsAfterGroup(gridPane,
|
||||
proposalDisplay.incrementAndGetGridRow(),
|
||||
Res.get("dao.proposal.myVote.accept"),
|
||||
Res.get("dao.proposal.myVote.reject"),
|
||||
Res.get("dao.proposal.myVote.removeMyVote"));
|
||||
Button acceptButton = tuple.first;
|
||||
acceptButton.setDefaultButton(false);
|
||||
Button rejectButton = tuple.second;
|
||||
Button ignoreButton = tuple.third;
|
||||
|
||||
// show if already voted
|
||||
proposalDisplay.applyBallot(ballot);
|
||||
|
||||
Optional<Vote> optionalVote = getVote(ballot);
|
||||
boolean isPresent = optionalVote.isPresent();
|
||||
boolean isAccepted = isPresent && optionalVote.get().isAccepted();
|
||||
acceptButton.setDisable((isPresent && isAccepted));
|
||||
rejectButton.setDisable((isPresent && !isAccepted));
|
||||
ignoreButton.setDisable(!isPresent);
|
||||
|
||||
acceptButton.setOnAction(event -> {
|
||||
acceptHandlerOptional.ifPresent(Runnable::run);
|
||||
doClose();
|
||||
});
|
||||
rejectButton.setOnAction(event -> {
|
||||
rejectHandlerOptional.ifPresent(Runnable::run);
|
||||
doClose();
|
||||
});
|
||||
ignoreButton.setOnAction(event -> {
|
||||
ignoreHandlerOptional.ifPresent(Runnable::run);
|
||||
doClose();
|
||||
});
|
||||
} else {
|
||||
Button closeButton = addButtonAfterGroup(gridPane, proposalDisplay.incrementAndGetGridRow(), Res.get("shared.close"));
|
||||
closeButton.setOnAction(event -> doClose());
|
||||
}
|
||||
}
|
||||
|
||||
private void setupCloseKeyHandler(Scene scene) {
|
||||
scene.setOnKeyPressed(e -> {
|
||||
if (e.getCode() == KeyCode.ESCAPE || e.getCode() == KeyCode.ENTER) {
|
||||
e.consume();
|
||||
doClose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Optional<Vote> getVote(@Nullable Ballot ballot) {
|
||||
if (ballot == null)
|
||||
return Optional.empty();
|
||||
else
|
||||
return ballot.getVoteAsOptional();
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue