mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 15:00:30 +01:00
Merge pull request #2566 from ripcurlx/ui-dao-improvements
DAO UI improvements
This commit is contained in:
commit
2a46133292
23 changed files with 878 additions and 472 deletions
|
@ -1681,6 +1681,7 @@ dao.proposal.active.remove.confirm=Are you sure you want to remove that proposal
|
|||
The already paid proposal fee will be lost.
|
||||
dao.proposal.active.remove.doRemove=Yes, remove my proposal
|
||||
dao.proposal.active.remove.failed=Could not remove proposal.
|
||||
dao.proposal.myVote.title=Voting
|
||||
dao.proposal.myVote.accept=Accept proposal
|
||||
dao.proposal.myVote.reject=Reject proposal
|
||||
dao.proposal.myVote.removeMyVote=Ignore proposal
|
||||
|
@ -1688,10 +1689,12 @@ dao.proposal.myVote.merit=Vote weight from earned BSQ
|
|||
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.myVote.stake.prompt=Max. available stake for voting: {0}
|
||||
dao.proposal.votes.header=Set stake for voting and publish your votes
|
||||
dao.proposal.myVote.button=Publish votes
|
||||
dao.proposal.myVote.setStake.description=After voting on all proposals you have to set your stake for voting by locking up \
|
||||
BSQ. The more BSQ you lock up, the more weight your vote will have. \n\n\
|
||||
BSQ locked up for voting will be unlocked again during the vote reveal phase.
|
||||
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
|
||||
|
|
|
@ -320,6 +320,20 @@ bg color of non edit textFields: fafafa
|
|||
-fx-padding: 0 10 0 10;
|
||||
}
|
||||
|
||||
.text-button {
|
||||
-fx-background-color: transparent;
|
||||
-fx-underline: true;
|
||||
-fx-padding: 0 10 0 10;
|
||||
-fx-pref-height: 28;
|
||||
-fx-min-height: -fx-pref-height;
|
||||
}
|
||||
|
||||
.text-button:hover {
|
||||
-fx-text-fill: -bs-rd-black;
|
||||
-fx-background-color: transparent;
|
||||
-fx-underline: false;
|
||||
}
|
||||
|
||||
.jfx-checkbox {
|
||||
-jfx-checked-color: -bs-rd-green;
|
||||
-fx-font-size: 0.692em;
|
||||
|
|
|
@ -93,7 +93,7 @@ public class BondsView extends ActivatableView<GridPane, Void> {
|
|||
|
||||
@Override
|
||||
public void initialize() {
|
||||
tableView = FormBuilder.addTableViewWithHeader(root, ++gridRow, Res.get("dao.bond.allBonds.header"));
|
||||
tableView = FormBuilder.addTableViewWithHeader(root, ++gridRow, Res.get("dao.bond.allBonds.header"), "last");
|
||||
tableView.setItems(sortedList);
|
||||
addColumns();
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ public class BondingDashboardView extends ActivatableView<GridPane, Void> {
|
|||
|
||||
public void initialize() {
|
||||
gridRow = bsqBalanceUtil.addGroup(root, gridRow);
|
||||
gridRow = bsqBalanceUtil.addBondBalanceGroup(root, gridRow);
|
||||
gridRow = bsqBalanceUtil.addBondBalanceGroup(root, gridRow, "last");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -144,7 +144,7 @@ public class MyReputationView extends ActivatableView<GridPane, Void> implements
|
|||
|
||||
lockupButton = addButtonAfterGroup(root, ++gridRow, Res.get("dao.bond.reputation.lockupButton"));
|
||||
|
||||
tableView = FormBuilder.addTableViewWithHeader(root, ++gridRow, Res.get("dao.bond.reputation.table.header"), 20);
|
||||
tableView = FormBuilder.addTableViewWithHeader(root, ++gridRow, Res.get("dao.bond.reputation.table.header"), 20, "last");
|
||||
createColumns();
|
||||
tableView.setItems(sortedList);
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ public class RolesView extends ActivatableView<GridPane, Void> {
|
|||
@Override
|
||||
public void initialize() {
|
||||
int gridRow = 0;
|
||||
tableView = FormBuilder.addTableViewWithHeader(root, gridRow, Res.get("dao.bond.bondedRoles"));
|
||||
tableView = FormBuilder.addTableViewWithHeader(root, gridRow, Res.get("dao.bond.bondedRoles"), "last");
|
||||
createColumns();
|
||||
tableView.setItems(sortedList);
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ public class AssetFeeView extends ActivatableView<GridPane, Void> implements Bsq
|
|||
|
||||
payFeeButton = addButtonAfterGroup(root, ++gridRow, Res.get("dao.burnBsq.payFee"));
|
||||
|
||||
tableView = FormBuilder.addTableViewWithHeader(root, ++gridRow, Res.get("dao.burnBsq.allAssets"), 20);
|
||||
tableView = FormBuilder.addTableViewWithHeader(root, ++gridRow, Res.get("dao.burnBsq.allAssets"), 20, "last");
|
||||
createColumns();
|
||||
tableView.setItems(sortedList);
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ public class ProofOfBurnView extends ActivatableView<GridPane, Void> implements
|
|||
createColumnsForMyItems();
|
||||
myItemsTableView.setItems(myItemsSortedList);
|
||||
|
||||
allTxsTableView = FormBuilder.addTableViewWithHeader(root, ++gridRow, Res.get("dao.proofOfBurn.allTxs"), 30);
|
||||
allTxsTableView = FormBuilder.addTableViewWithHeader(root, ++gridRow, Res.get("dao.proofOfBurn.allTxs"), 30, "last");
|
||||
createColumnsForAllTxs();
|
||||
allTxsTableView.setItems(allItemsSortedList);
|
||||
|
||||
|
|
|
@ -140,9 +140,10 @@ public class ProposalDisplay {
|
|||
private final ChangeListener<Object> inputListener;
|
||||
private ChangeListener<Param> paramChangeListener;
|
||||
private ChangeListener<BondedRoleType> requiredBondForRoleListener;
|
||||
private TitledGroupBg titledGroupBg;
|
||||
private TitledGroupBg myVoteTitledGroup;
|
||||
private int titledGroupBgRowSpan;
|
||||
private VBox linkWithIconContainer, comboBoxValueContainer, myVoteBox, voteResultBox;
|
||||
private int votingBoxRowSpan;
|
||||
|
||||
public ProposalDisplay(GridPane gridPane,
|
||||
BsqFormatter bsqFormatter,
|
||||
|
@ -176,6 +177,11 @@ public class ProposalDisplay {
|
|||
|
||||
public void createAllFields(String title, int gridRowStartIndex, double top, ProposalType proposalType,
|
||||
boolean isMakeProposalScreen) {
|
||||
createAllFields(title, gridRowStartIndex, top, proposalType, isMakeProposalScreen, null);
|
||||
}
|
||||
|
||||
public void createAllFields(String title, int gridRowStartIndex, double top, ProposalType proposalType,
|
||||
boolean isMakeProposalScreen, String titledGroupStyle) {
|
||||
removeAllFields();
|
||||
this.gridRowStartIndex = gridRowStartIndex;
|
||||
this.gridRow = gridRowStartIndex;
|
||||
|
@ -200,12 +206,26 @@ public class ProposalDisplay {
|
|||
break;
|
||||
}
|
||||
|
||||
titledGroupBg = addTitledGroupBg(gridPane, gridRow, titledGroupBgRowSpan, title, top);
|
||||
double proposalTypeTop = top == Layout.GROUP_DISTANCE ? Layout.FIRST_ROW_AND_GROUP_DISTANCE : Layout.FIRST_ROW_DISTANCE;
|
||||
TitledGroupBg titledGroupBg = addTitledGroupBg(gridPane, gridRow, titledGroupBgRowSpan, title, top);
|
||||
|
||||
if (titledGroupStyle != null) titledGroupBg.getStyleClass().add(titledGroupStyle);
|
||||
|
||||
double proposalTypeTop;
|
||||
|
||||
if (top == Layout.GROUP_DISTANCE_WITHOUT_SEPARATOR) {
|
||||
proposalTypeTop = Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE_WITHOUT_SEPARATOR;
|
||||
} else if (top == Layout.GROUP_DISTANCE) {
|
||||
proposalTypeTop = Layout.FIRST_ROW_AND_GROUP_DISTANCE;
|
||||
} else if (top == 0) {
|
||||
proposalTypeTop = Layout.FIRST_ROW_DISTANCE;
|
||||
} else {
|
||||
proposalTypeTop = Layout.FIRST_ROW_DISTANCE + top;
|
||||
}
|
||||
|
||||
proposalTypeTextField = addTopLabelTextField(gridPane, gridRow,
|
||||
Res.get("dao.proposal.display.type"), proposalType.getDisplayName(), proposalTypeTop).second;
|
||||
|
||||
nameTextField = addInputTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.name"), Layout.FIRST_ROW_DISTANCE);
|
||||
nameTextField = addInputTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.name"));
|
||||
if (isMakeProposalScreen)
|
||||
nameTextField.setValidator(new InputValidator());
|
||||
inputControls.add(nameTextField);
|
||||
|
@ -317,7 +337,7 @@ public class ProposalDisplay {
|
|||
}
|
||||
});
|
||||
comboBoxes.add(bondedRoleTypeComboBox);
|
||||
requiredBondForRoleTextField = addTopLabelTextField(gridPane, ++gridRow,
|
||||
requiredBondForRoleTextField = addTopLabelReadOnlyTextField(gridPane, ++gridRow,
|
||||
Res.get("dao.proposal.display.requiredBondForRole.label")).second;
|
||||
|
||||
requiredBondForRoleListener = (observable, oldValue, newValue) -> {
|
||||
|
@ -398,15 +418,18 @@ public class ProposalDisplay {
|
|||
proposalFeeTextField.setText(bsqFormatter.formatCoinWithCode(daoFacade.getProposalFee(daoFacade.getChainHeight())));
|
||||
}
|
||||
|
||||
Tuple3<Label, TextField, VBox> tuple3 = addTopLabelTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.myVote"));
|
||||
votingBoxRowSpan = 4;
|
||||
|
||||
myVoteTitledGroup = addTitledGroupBg(gridPane, ++gridRow, 4, Res.get("dao.proposal.myVote.title"), Layout.COMPACT_FIRST_ROW_DISTANCE);
|
||||
|
||||
Tuple3<Label, TextField, VBox> tuple3 = addTopLabelTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.myVote"), Layout.COMPACT_FIRST_ROW_DISTANCE);
|
||||
|
||||
myVoteBox = tuple3.third;
|
||||
myVoteBox.setVisible(false);
|
||||
myVoteBox.setManaged(false);
|
||||
setMyVoteBoxVisibility(false);
|
||||
|
||||
myVoteTextField = tuple3.second;
|
||||
|
||||
tuple3 = addTopLabelTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.voteResult"));
|
||||
tuple3 = addTopLabelReadOnlyTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.voteResult"));
|
||||
|
||||
voteResultBox = tuple3.third;
|
||||
voteResultBox.setVisible(false);
|
||||
|
@ -427,12 +450,10 @@ public class ProposalDisplay {
|
|||
}
|
||||
myVoteTextField.setText(myVote);
|
||||
|
||||
myVoteBox.setVisible(isNotNull);
|
||||
myVoteBox.setManaged(isNotNull);
|
||||
setMyVoteBoxVisibility(isNotNull);
|
||||
}
|
||||
|
||||
public void applyEvaluatedProposal(@Nullable EvaluatedProposal evaluatedProposal) {
|
||||
GridPane.setRowSpan(titledGroupBg, titledGroupBgRowSpan + 1);
|
||||
|
||||
boolean isEvaluatedProposalNotNull = evaluatedProposal != null;
|
||||
if (isEvaluatedProposalNotNull) {
|
||||
|
@ -468,11 +489,12 @@ public class ProposalDisplay {
|
|||
String myVoteSummary = Res.get("dao.proposal.myVote.summary", myVote,
|
||||
weight, meritString, stakeString);
|
||||
myVoteTextField.setText(myVoteSummary);
|
||||
|
||||
GridPane.setRowSpan(myVoteTitledGroup, votingBoxRowSpan - 1);
|
||||
}
|
||||
|
||||
boolean show = ballotIsNotNull && hasVoted;
|
||||
myVoteBox.setVisible(show);
|
||||
myVoteBox.setManaged(show);
|
||||
setMyVoteBoxVisibility(show);
|
||||
}
|
||||
|
||||
public void setIsVoteIncludedInResult(boolean isVoteIncludedInResult) {
|
||||
|
@ -658,4 +680,11 @@ public class ProposalDisplay {
|
|||
|
||||
return scrollPane;
|
||||
}
|
||||
|
||||
private void setMyVoteBoxVisibility(boolean visibility) {
|
||||
myVoteTitledGroup.setVisible(visibility);
|
||||
myVoteTitledGroup.setManaged(visibility);
|
||||
myVoteBox.setVisible(visibility);
|
||||
myVoteBox.setManaged(visibility);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package bisq.desktop.main.dao.governance.dashboard;
|
|||
|
||||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.main.dao.governance.PhasesView;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
|
@ -69,7 +70,8 @@ public class GovernanceDashboardView extends ActivatableView<GridPane, Void> imp
|
|||
public void initialize() {
|
||||
gridRow = phasesView.addGroup(root, gridRow);
|
||||
|
||||
addTitledGroupBg(root, ++gridRow, 6, Res.get("dao.cycle.overview.headline"), Layout.GROUP_DISTANCE);
|
||||
TitledGroupBg titledGroupBg = addTitledGroupBg(root, ++gridRow, 6, Res.get("dao.cycle.overview.headline"), Layout.GROUP_DISTANCE);
|
||||
titledGroupBg.getStyleClass().add("last");
|
||||
currentBlockHeightTextField = addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.cycle.currentBlockHeight"),
|
||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
currentPhaseTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.cycle.currentPhase")).second;
|
||||
|
|
|
@ -161,6 +161,7 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
|
|||
gridRow = phasesView.addGroup(root, gridRow);
|
||||
|
||||
proposalTitledGroup = addTitledGroupBg(root, ++gridRow, 2, proposalGroupTitle.get(), Layout.GROUP_DISTANCE);
|
||||
proposalTitledGroup.getStyleClass().add("last");
|
||||
final Tuple3<Label, TextField, VBox> nextProposalPhaseTuple = addTopLabelReadOnlyTextField(root, gridRow,
|
||||
Res.get("dao.cycle.proposal.next"),
|
||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
|
@ -444,7 +445,7 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
|
|||
if (selectedProposalType != null) {
|
||||
proposalDisplay = new ProposalDisplay(root, bsqFormatter, daoFacade, changeParamValidator, navigation, null);
|
||||
|
||||
proposalDisplay.createAllFields(Res.get("dao.proposal.create.new"), alwaysVisibleGridRowIndex, Layout.GROUP_DISTANCE,
|
||||
proposalDisplay.createAllFields(Res.get("dao.proposal.create.new"), alwaysVisibleGridRowIndex, Layout.GROUP_DISTANCE_WITHOUT_SEPARATOR,
|
||||
selectedProposalType, true);
|
||||
|
||||
final Tuple4<Button, BusyAnimation, Label, HBox> makeProposalTuple = addButtonBusyAnimationLabelAfterGroup(root,
|
||||
|
|
|
@ -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,
|
||||
@Nullable EvaluatedProposal evaluatedProposal) {
|
||||
proposalDisplayView.setVisible(true);
|
||||
proposalDisplayView.setManaged(true);
|
||||
private void showVoteOnProposalWindow(Proposal proposal, @Nullable Ballot ballot,
|
||||
@Nullable EvaluatedProposal evaluatedProposal) {
|
||||
|
||||
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);
|
||||
applyMerit();
|
||||
} else {
|
||||
hideProposalDisplay();
|
||||
showVoteOnProposalWindow(selectedItem.getProposal(), selectedItem.getBallot(), evaluatedProposal);
|
||||
}
|
||||
onPhaseChanged(daoFacade.phaseProperty().get());
|
||||
|
||||
updateViews();
|
||||
onPhaseChanged(daoFacade.phaseProperty().get());
|
||||
}
|
||||
|
||||
private void applyMerit() {
|
||||
|
@ -479,20 +422,31 @@ 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();
|
||||
|
||||
showHowToSetStakeForVotingPopup();
|
||||
}
|
||||
|
||||
private void showHowToSetStakeForVotingPopup() {
|
||||
String id = "explainHowToSetStakeForVoting";
|
||||
if (preferences.showAgain(id))
|
||||
new Popup<>().information(Res.get("dao.proposal.myVote.setStake.description"))
|
||||
.dontShowAgainId(id).show();
|
||||
}
|
||||
|
||||
private void onReject() {
|
||||
daoFacade.setVote(getBallotListItem().getBallot(), new Vote(false));
|
||||
proposalDisplay.applyBallot(getBallotListItem().getBallot());
|
||||
updateStateAfterVote();
|
||||
tableView.getSelectionModel().clearSelection();
|
||||
showHowToSetStakeForVotingPopup();
|
||||
}
|
||||
|
||||
private void onIgnore() {
|
||||
daoFacade.setVote(getBallotListItem().getBallot(), null);
|
||||
proposalDisplay.applyBallot(getBallotListItem().getBallot());
|
||||
updateStateAfterVote();
|
||||
tableView.getSelectionModel().clearSelection();
|
||||
showHowToSetStakeForVotingPopup();
|
||||
}
|
||||
|
||||
private void onVote() {
|
||||
|
@ -545,13 +499,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 +507,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 +533,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 +597,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,25 +609,17 @@ 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);
|
||||
|
||||
Tuple3<Label, TextField, VBox> meritTuple = addTopLabelTextField(root, gridRow,
|
||||
|
@ -866,7 +795,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();
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package bisq.desktop.main.dao.governance.result;
|
||||
|
||||
import bisq.desktop.Navigation;
|
||||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.AutoTooltipLabel;
|
||||
|
@ -25,9 +24,9 @@ import bisq.desktop.components.AutoTooltipTableColumn;
|
|||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.components.TableGroupHeadline;
|
||||
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.DaoTestingFeedbackWindow;
|
||||
import bisq.desktop.main.overlays.windows.ProposalResultsWindow;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
@ -63,11 +62,9 @@ import bisq.core.dao.state.model.governance.RoleProposal;
|
|||
import bisq.core.dao.state.model.governance.Vote;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.user.DontShowAgainLookup;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.util.Tuple2;
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
@ -79,21 +76,18 @@ import com.google.gson.JsonObject;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;
|
||||
|
||||
import javafx.stage.Stage;
|
||||
|
||||
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;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Priority;
|
||||
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
|
@ -118,6 +112,8 @@ import java.util.Optional;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.addButton;
|
||||
|
||||
@FxmlView
|
||||
public class VoteResultView extends ActivatableView<GridPane, Void> implements DaoStateListener {
|
||||
private final DaoFacade daoFacade;
|
||||
|
@ -128,11 +124,10 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
private final ProposalService proposalService;
|
||||
private final PeriodService periodService;
|
||||
private final BsqWalletService bsqWalletService;
|
||||
private final Preferences preferences;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final Navigation navigation;
|
||||
private final MyProposalListService myProposalListService;
|
||||
private final MyBlindVoteListService myBlindVoteListService;
|
||||
private ProposalResultsWindow proposalResultsWindow;
|
||||
private Button exportButton;
|
||||
|
||||
private int gridRow = 0;
|
||||
|
@ -152,7 +147,6 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
private ChangeListener<CycleListItem> selectedVoteResultListItemListener;
|
||||
private ResultsOfCycle resultsOfCycle;
|
||||
private ProposalListItem selectedProposalListItem;
|
||||
private TableView<VoteListItem> votesTableView;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -168,11 +162,10 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
ProposalService proposalService,
|
||||
PeriodService periodService,
|
||||
BsqWalletService bsqWalletService,
|
||||
Preferences preferences,
|
||||
BsqFormatter bsqFormatter,
|
||||
Navigation navigation,
|
||||
MyProposalListService myProposalListService,
|
||||
MyBlindVoteListService myBlindVoteListService) {
|
||||
MyBlindVoteListService myBlindVoteListService,
|
||||
ProposalResultsWindow proposalResultsWindow) {
|
||||
this.daoFacade = daoFacade;
|
||||
this.phasesView = phasesView;
|
||||
this.daoStateService = daoStateService;
|
||||
|
@ -181,11 +174,10 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
this.proposalService = proposalService;
|
||||
this.periodService = periodService;
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
this.preferences = preferences;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
this.navigation = navigation;
|
||||
this.myProposalListService = myProposalListService;
|
||||
this.myBlindVoteListService = myBlindVoteListService;
|
||||
this.proposalResultsWindow = proposalResultsWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -195,8 +187,9 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
selectedVoteResultListItemListener = (observable, oldValue, newValue) -> onResultsListItemSelected(newValue);
|
||||
|
||||
createCyclesTable();
|
||||
exportButton = FormBuilder.addButton(root, ++gridRow, Res.get("shared.exportJSON"));
|
||||
GridPane.setMargin(exportButton, new Insets(20, -10, -40, 0));
|
||||
exportButton = addButton(root, ++gridRow, Res.get("shared.exportJSON"));
|
||||
exportButton.getStyleClass().add("text-button");
|
||||
GridPane.setMargin(exportButton, new Insets(10, -10, -50, 0));
|
||||
GridPane.setColumnSpan(exportButton, 2);
|
||||
GridPane.setHalignment(exportButton, HPos.RIGHT);
|
||||
}
|
||||
|
@ -216,12 +209,9 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
GUIUtil.exportJSON("voteResultsHistory.json", cyclesJsonArray, (Stage) root.getScene().getWindow());
|
||||
});
|
||||
if (proposalsTableView != null) {
|
||||
GUIUtil.setFitToRowsForTableView(proposalsTableView, 25, 28, 2, 4);
|
||||
GUIUtil.setFitToRowsForTableView(proposalsTableView, 25, 28, 6, 6);
|
||||
}
|
||||
if (votesTableView != null) {
|
||||
GUIUtil.setFitToRowsForTableView(votesTableView, 25, 28, 2, 4);
|
||||
}
|
||||
GUIUtil.setFitToRowsForTableView(cyclesTableView, 25, 28, 2, 4);
|
||||
GUIUtil.setFitToRowsForTableView(cyclesTableView, 25, 28, 6, 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -336,17 +326,30 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
Optional<Ballot> optionalBallot = daoFacade.getAllValidBallots().stream()
|
||||
.filter(ballot -> ballot.getTxId().equals(evaluatedProposal.getProposalTxId()))
|
||||
.findAny();
|
||||
Ballot ballot = optionalBallot.orElse(null);
|
||||
ProposalDisplay proposalDisplay = createProposalDisplay(evaluatedProposal, ballot);
|
||||
createVotesTable();
|
||||
|
||||
Ballot ballot = optionalBallot.orElse(null);
|
||||
// Check if my vote is included in result
|
||||
boolean isVoteIncludedInResult = voteListItemList.stream()
|
||||
.anyMatch(voteListItem -> bsqWalletService.getTransaction(voteListItem.getBlindVoteTxId()) != null);
|
||||
proposalDisplay.setIsVoteIncludedInResult(isVoteIncludedInResult);
|
||||
|
||||
voteListItemList.clear();
|
||||
resultsOfCycle.getEvaluatedProposals().stream()
|
||||
.filter(evProposal -> evProposal.getProposal().equals(selectedProposalListItem.getEvaluatedProposal().getProposal()))
|
||||
.forEach(evProposal -> resultsOfCycle.getDecryptedVotesForCycle().forEach(decryptedBallotsWithMerits ->
|
||||
voteListItemList.add(new VoteListItem(evProposal.getProposal(), decryptedBallotsWithMerits,
|
||||
daoStateService, bsqFormatter))));
|
||||
|
||||
voteListItemList.sort(Comparator.comparing(VoteListItem::getBlindVoteTxId));
|
||||
|
||||
showProposalResultWindow(evaluatedProposal, ballot, isVoteIncludedInResult, sortedVoteListItemList);
|
||||
}
|
||||
}
|
||||
|
||||
private void showProposalResultWindow(EvaluatedProposal evaluatedProposal, Ballot ballot,
|
||||
boolean isVoteIncludedInResult, SortedList<VoteListItem> sortedVoteListItemList) {
|
||||
proposalResultsWindow.show(evaluatedProposal, ballot, isVoteIncludedInResult, sortedVoteListItemList);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Fill lists: Cycle
|
||||
|
@ -386,7 +389,7 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
|
||||
maybeShowDaoTestingFeedbackWindow();
|
||||
|
||||
GUIUtil.setFitToRowsForTableView(cyclesTableView, 25, 28, 2, 4);
|
||||
GUIUtil.setFitToRowsForTableView(cyclesTableView, 25, 28, 6, 6);
|
||||
}
|
||||
|
||||
private void maybeShowDaoTestingFeedbackWindow() {
|
||||
|
@ -450,7 +453,7 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
createProposalsColumns(proposalsTableView);
|
||||
|
||||
GridPane.setRowIndex(proposalsTableView, gridRow);
|
||||
GridPane.setMargin(proposalsTableView, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, -10, 5, -10));
|
||||
GridPane.setMargin(proposalsTableView, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, -10, 0, -10));
|
||||
GridPane.setColumnSpan(proposalsTableView, 2);
|
||||
root.getChildren().add(proposalsTableView);
|
||||
|
||||
|
@ -477,81 +480,9 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
ballotByProposalTxIdMap.get(evaluatedProposal.getProposalTxId()),
|
||||
bsqFormatter))
|
||||
.collect(Collectors.toList()));
|
||||
GUIUtil.setFitToRowsForTableView(proposalsTableView, 25, 28, 2, 4);
|
||||
GUIUtil.setFitToRowsForTableView(proposalsTableView, 25, 28, 6, 6);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Create views: proposalDisplay
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private ProposalDisplay createProposalDisplay(EvaluatedProposal evaluatedProposal, Ballot ballot) {
|
||||
Proposal proposal = evaluatedProposal.getProposal();
|
||||
ProposalDisplay proposalDisplay = new ProposalDisplay(new GridPane(), bsqFormatter,
|
||||
daoFacade, null, navigation, preferences);
|
||||
|
||||
ScrollPane proposalDisplayView = proposalDisplay.getView();
|
||||
GridPane.setMargin(proposalDisplayView, new Insets(0, -10, -15, -10));
|
||||
GridPane.setRowIndex(proposalDisplayView, ++gridRow);
|
||||
GridPane.setColumnSpan(proposalDisplayView, 2);
|
||||
GridPane.setHgrow(proposalDisplayView, Priority.ALWAYS);
|
||||
root.getChildren().add(proposalDisplayView);
|
||||
|
||||
proposalDisplay.createAllFields(Res.get("dao.proposal.selectedProposal"), 0, 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);
|
||||
return proposalDisplay;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Create views: votesTableView
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void createVotesTable() {
|
||||
TableGroupHeadline votesTableHeader = new TableGroupHeadline(Res.get("dao.results.proposals.voting.detail.header"));
|
||||
GridPane.setRowIndex(votesTableHeader, ++gridRow);
|
||||
GridPane.setMargin(votesTableHeader, new Insets(Layout.GROUP_DISTANCE, -10, -10, -10));
|
||||
GridPane.setColumnSpan(votesTableHeader, 2);
|
||||
root.getChildren().add(votesTableHeader);
|
||||
|
||||
votesTableView = new TableView<>();
|
||||
votesTableView.setPlaceholder(new AutoTooltipLabel(Res.get("table.placeholder.noData")));
|
||||
votesTableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
|
||||
createColumns(votesTableView);
|
||||
GridPane.setRowIndex(votesTableView, gridRow);
|
||||
GridPane.setMargin(votesTableView, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, -10, -15, -10));
|
||||
GridPane.setColumnSpan(votesTableView, 2);
|
||||
root.getChildren().add(votesTableView);
|
||||
|
||||
votesTableView.setItems(sortedVoteListItemList);
|
||||
sortedVoteListItemList.comparatorProperty().bind(votesTableView.comparatorProperty());
|
||||
|
||||
voteListItemList.clear();
|
||||
resultsOfCycle.getEvaluatedProposals().stream()
|
||||
.filter(evaluatedProposal -> evaluatedProposal.getProposal().equals(selectedProposalListItem.getEvaluatedProposal().getProposal()))
|
||||
.forEach(evaluatedProposal -> {
|
||||
resultsOfCycle.getDecryptedVotesForCycle().forEach(decryptedBallotsWithMerits -> {
|
||||
voteListItemList.add(new VoteListItem(evaluatedProposal.getProposal(), decryptedBallotsWithMerits,
|
||||
daoStateService, bsqFormatter));
|
||||
});
|
||||
});
|
||||
|
||||
voteListItemList.sort(Comparator.comparing(VoteListItem::getBlindVoteTxId));
|
||||
GUIUtil.setFitToRowsForTableView(votesTableView, 25, 28, 2, 4);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TableColumns: CycleListItem
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -879,117 +810,6 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
votesTableView.getColumns().add(column);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TableColumns: VoteListItem
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void createColumns(TableView<VoteListItem> votesTableView) {
|
||||
TableColumn<VoteListItem, VoteListItem> column;
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.results.votes.table.header.vote"));
|
||||
column.setSortable(false);
|
||||
column.setMinWidth(50);
|
||||
column.setMaxWidth(column.getMinWidth());
|
||||
column.getStyleClass().add("first-column");
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<VoteListItem, VoteListItem> call(
|
||||
TableColumn<VoteListItem, VoteListItem> column) {
|
||||
return new TableCell<>() {
|
||||
private Label icon;
|
||||
|
||||
@Override
|
||||
public void updateItem(final VoteListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
Tuple2<AwesomeIcon, String> iconStyleTuple = item.getIconStyleTuple();
|
||||
icon = new Label();
|
||||
AwesomeDude.setIcon(icon, iconStyleTuple.first);
|
||||
icon.getStyleClass().add(iconStyleTuple.second);
|
||||
setGraphic(icon);
|
||||
} else {
|
||||
setGraphic(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
votesTableView.getColumns().add(column);
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.results.votes.table.header.stakeAndMerit"));
|
||||
column.setSortable(false);
|
||||
column.setMinWidth(100);
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<VoteListItem, VoteListItem> call(
|
||||
TableColumn<VoteListItem, VoteListItem> column) {
|
||||
return new TableCell<>() {
|
||||
@Override
|
||||
public void updateItem(final VoteListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(item.getMeritAndStake());
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
votesTableView.getColumns().add(column);
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.results.votes.table.header.merit"));
|
||||
column.setSortable(false);
|
||||
column.setMinWidth(100);
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<VoteListItem, VoteListItem> call(
|
||||
TableColumn<VoteListItem, VoteListItem> column) {
|
||||
return new TableCell<>() {
|
||||
@Override
|
||||
public void updateItem(final VoteListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(item.getMerit());
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
votesTableView.getColumns().add(column);
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.results.votes.table.header.stake"));
|
||||
column.setSortable(false);
|
||||
column.setMinWidth(100);
|
||||
column.getStyleClass().add("last-column");
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<VoteListItem, VoteListItem> call(
|
||||
TableColumn<VoteListItem, VoteListItem> column) {
|
||||
return new TableCell<>() {
|
||||
@Override
|
||||
public void updateItem(final VoteListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(item.getStake());
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
votesTableView.getColumns().add(column);
|
||||
}
|
||||
|
||||
private JsonElement getVotingHistoryJson() {
|
||||
JsonArray cyclesArray = new JsonArray();
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package bisq.desktop.main.dao.wallet;
|
||||
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
|
@ -176,10 +177,12 @@ public class BsqBalanceUtil implements BsqBalanceListener, DaoStateListener {
|
|||
return gridRow;
|
||||
}
|
||||
|
||||
public int addBondBalanceGroup(GridPane gridPane, int gridRow) {
|
||||
addTitledGroupBg(gridPane, ++gridRow, 2,
|
||||
public int addBondBalanceGroup(GridPane gridPane, int gridRow, String groupStyle) {
|
||||
TitledGroupBg titledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 2,
|
||||
Res.get("dao.bond.dashboard.bondsHeadline"), Layout.GROUP_DISTANCE);
|
||||
|
||||
if (groupStyle != null) titledGroupBg.getStyleClass().add(groupStyle);
|
||||
|
||||
lockupAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(gridPane, gridRow,
|
||||
Res.get("dao.bond.dashboard.lockupAmount"),
|
||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
|
|
|
@ -20,6 +20,7 @@ package bisq.desktop.main.dao.wallet.dashboard;
|
|||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.main.dao.wallet.BsqBalanceUtil;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
@ -96,24 +97,24 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
|
|||
|
||||
int startRow = gridRow;
|
||||
addTitledGroupBg(root, ++gridRow, 5, Res.get("dao.wallet.dashboard.distribution"), Layout.GROUP_DISTANCE);
|
||||
genesisIssueAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.wallet.dashboard.genesisIssueAmount"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
compRequestIssueAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.compRequestIssueAmount")).second;
|
||||
reimbursementAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.reimbursementAmount")).second;
|
||||
burntAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.burntAmount")).second;
|
||||
availableAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.availableAmount")).second;
|
||||
genesisIssueAmountTextField = addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.wallet.dashboard.genesisIssueAmount"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
compRequestIssueAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.compRequestIssueAmount")).second;
|
||||
reimbursementAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.reimbursementAmount")).second;
|
||||
burntAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.burntAmount")).second;
|
||||
availableAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.availableAmount")).second;
|
||||
|
||||
gridRow = startRow;
|
||||
addTitledGroupBg(root, ++gridRow, columnIndex, 5, Res.get("dao.wallet.dashboard.locked"), Layout.GROUP_DISTANCE);
|
||||
totalLockedUpAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalLockedUpAmount"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
totalUnlockingAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalUnlockingAmount")).second;
|
||||
totalUnlockedAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalUnlockedAmount")).second;
|
||||
totalConfiscatedAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalConfiscatedAmount")).second;
|
||||
totalLockedUpAmountTextField = addTopLabelReadOnlyTextField(root, gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalLockedUpAmount"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
totalUnlockingAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalUnlockingAmount")).second;
|
||||
totalUnlockedAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalUnlockedAmount")).second;
|
||||
totalConfiscatedAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalConfiscatedAmount")).second;
|
||||
gridRow++;
|
||||
|
||||
startRow = gridRow;
|
||||
addTitledGroupBg(root, ++gridRow, 2, Res.get("dao.wallet.dashboard.market"), Layout.GROUP_DISTANCE);
|
||||
priceTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.wallet.dashboard.price"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
marketCapTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.marketCap")).second;
|
||||
priceTextField = addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.wallet.dashboard.price"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
marketCapTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.marketCap")).second;
|
||||
|
||||
gridRow = startRow;
|
||||
addTitledGroupBg(root, ++gridRow, columnIndex, 2, Res.get("dao.wallet.dashboard.genesis"), Layout.GROUP_DISTANCE);
|
||||
|
@ -130,19 +131,21 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
|
|||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", genesisTxId)));
|
||||
|
||||
startRow = gridRow;
|
||||
addTitledGroupBg(root, ++gridRow, 3, Res.get("dao.wallet.dashboard.txDetails"), Layout.GROUP_DISTANCE);
|
||||
allTxTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.wallet.dashboard.allTx"),
|
||||
TitledGroupBg titledGroupBgTxDetails = addTitledGroupBg(root, ++gridRow, 3, Res.get("dao.wallet.dashboard.txDetails"), Layout.GROUP_DISTANCE);
|
||||
titledGroupBgTxDetails.getStyleClass().add("last");
|
||||
allTxTextField = addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.wallet.dashboard.allTx"),
|
||||
genTxHeight, Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
utxoTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.utxo")).second;
|
||||
compensationIssuanceTxTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow,
|
||||
utxoTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.utxo")).second;
|
||||
compensationIssuanceTxTextField = addTopLabelReadOnlyTextField(root, ++gridRow,
|
||||
Res.get("dao.wallet.dashboard.compensationIssuanceTx")).second;
|
||||
|
||||
gridRow = startRow;
|
||||
addTitledGroupBg(root, ++gridRow, columnIndex, 3, "", Layout.GROUP_DISTANCE);
|
||||
reimbursementIssuanceTxTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, columnIndex,
|
||||
TitledGroupBg titledGroupBgReImbursement = addTitledGroupBg(root, ++gridRow, columnIndex, 3, "", Layout.GROUP_DISTANCE);
|
||||
titledGroupBgReImbursement.getStyleClass().add("last");
|
||||
reimbursementIssuanceTxTextField = addTopLabelReadOnlyTextField(root, gridRow, columnIndex,
|
||||
Res.get("dao.wallet.dashboard.reimbursementIssuanceTx"),
|
||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
burntTxTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex,
|
||||
burntTxTextField = addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex,
|
||||
Res.get("dao.wallet.dashboard.burntTx")).second;
|
||||
++gridRow;
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ public class BsqReceiveView extends ActivatableView<GridPane, Void> {
|
|||
|
||||
TitledGroupBg titledGroupBg = addTitledGroupBg(root, ++gridRow, 1,
|
||||
Res.get("dao.wallet.receive.fundYourWallet"), Layout.GROUP_DISTANCE);
|
||||
titledGroupBg.getStyleClass().add("last");
|
||||
GridPane.setColumnSpan(titledGroupBg, 3);
|
||||
Tuple3<Label, BsqAddressTextField, VBox> tuple = addLabelBsqAddressTextField(root, gridRow,
|
||||
Res.get("dao.wallet.receive.bsqAddress"),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -60,6 +60,7 @@ import javafx.scene.layout.GridPane;
|
|||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.transform.Rotate;
|
||||
|
||||
|
@ -499,7 +500,7 @@ public abstract class Overlay<T extends Overlay> {
|
|||
if (owner != null) {
|
||||
Scene rootScene = owner.getScene();
|
||||
if (rootScene != null) {
|
||||
Scene scene = new Scene(gridPane);
|
||||
Scene scene = new Scene(getRootContainer());
|
||||
scene.getStylesheets().setAll(rootScene.getStylesheets());
|
||||
scene.setFill(Color.TRANSPARENT);
|
||||
|
||||
|
@ -544,6 +545,11 @@ public abstract class Overlay<T extends Overlay> {
|
|||
}
|
||||
}
|
||||
|
||||
protected Region getRootContainer() {
|
||||
return gridPane;
|
||||
}
|
||||
|
||||
|
||||
protected void setupKeyHandler(Scene scene) {
|
||||
if (!hideCloseButton) {
|
||||
scene.setOnKeyPressed(e -> {
|
||||
|
@ -556,66 +562,68 @@ public abstract class Overlay<T extends Overlay> {
|
|||
}
|
||||
|
||||
protected void animateDisplay() {
|
||||
gridPane.setOpacity(0);
|
||||
Region rootContainer = this.getRootContainer();
|
||||
|
||||
rootContainer.setOpacity(0);
|
||||
Interpolator interpolator = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
||||
double duration = getDuration(400);
|
||||
Timeline timeline = new Timeline();
|
||||
ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
|
||||
|
||||
if (type.animationType == AnimationType.SlideDownFromCenterTop) {
|
||||
double startY = -gridPane.getHeight();
|
||||
double startY = -rootContainer.getHeight();
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.translateYProperty(), startY, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(rootContainer.translateYProperty(), startY, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.translateYProperty(), -50, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(rootContainer.translateYProperty(), -50, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.ScaleFromCenter) {
|
||||
double startScale = 0.25;
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), startScale, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), startScale, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(rootContainer.scaleXProperty(), startScale, interpolator),
|
||||
new KeyValue(rootContainer.scaleYProperty(), startScale, interpolator)
|
||||
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(rootContainer.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(rootContainer.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.ScaleYFromCenter) {
|
||||
double startYScale = 0.25;
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), startYScale, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(rootContainer.scaleYProperty(), startYScale, interpolator)
|
||||
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(rootContainer.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.ScaleDownToCenter) {
|
||||
double startScale = 1.1;
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), startScale, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), startScale, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(rootContainer.scaleXProperty(), startScale, interpolator),
|
||||
new KeyValue(rootContainer.scaleYProperty(), startScale, interpolator)
|
||||
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(rootContainer.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(rootContainer.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.FadeInAtCenter) {
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 0, interpolator)
|
||||
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 1, interpolator)
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -628,15 +636,16 @@ public abstract class Overlay<T extends Overlay> {
|
|||
Timeline timeline = new Timeline();
|
||||
ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
|
||||
|
||||
Region rootContainer = getRootContainer();
|
||||
if (type.animationType == AnimationType.SlideDownFromCenterTop) {
|
||||
double endY = -gridPane.getHeight();
|
||||
double endY = -rootContainer.getHeight();
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.translateYProperty(), -10, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(rootContainer.translateYProperty(), -10, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.translateYProperty(), endY, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(rootContainer.translateYProperty(), endY, interpolator)
|
||||
));
|
||||
|
||||
timeline.setOnFinished(e -> onFinishedHandler.run());
|
||||
|
@ -644,44 +653,44 @@ public abstract class Overlay<T extends Overlay> {
|
|||
} else if (type.animationType == AnimationType.ScaleFromCenter) {
|
||||
double endScale = 0.25;
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(rootContainer.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(rootContainer.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), endScale, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), endScale, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(rootContainer.scaleXProperty(), endScale, interpolator),
|
||||
new KeyValue(rootContainer.scaleYProperty(), endScale, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.ScaleYFromCenter) {
|
||||
gridPane.setRotationAxis(Rotate.X_AXIS);
|
||||
gridPane.getScene().setCamera(new PerspectiveCamera());
|
||||
rootContainer.setRotationAxis(Rotate.X_AXIS);
|
||||
rootContainer.getScene().setCamera(new PerspectiveCamera());
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.rotateProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator)
|
||||
new KeyValue(rootContainer.rotateProperty(), 0, interpolator),
|
||||
new KeyValue(rootContainer.opacityProperty(), 1, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.rotateProperty(), -90, interpolator),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator)
|
||||
new KeyValue(rootContainer.rotateProperty(), -90, interpolator),
|
||||
new KeyValue(rootContainer.opacityProperty(), 0, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.ScaleDownToCenter) {
|
||||
double endScale = 0.1;
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(rootContainer.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(rootContainer.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), endScale, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), endScale, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(rootContainer.scaleXProperty(), endScale, interpolator),
|
||||
new KeyValue(rootContainer.scaleYProperty(), endScale, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.FadeInAtCenter) {
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 1, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator)
|
||||
new KeyValue(rootContainer.opacityProperty(), 0, interpolator)
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -718,10 +727,11 @@ public abstract class Overlay<T extends Overlay> {
|
|||
|
||||
|
||||
protected void applyStyles() {
|
||||
Region rootContainer = getRootContainer();
|
||||
if (type.animationType == AnimationType.SlideDownFromCenterTop) {
|
||||
gridPane.getStyleClass().add("popup-bg-top");
|
||||
rootContainer.getStyleClass().add("popup-bg-top");
|
||||
} else {
|
||||
gridPane.getStyleClass().add("popup-bg");
|
||||
rootContainer.getStyleClass().add("popup-bg");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package bisq.desktop.main.overlays;
|
||||
|
||||
import com.jfoenix.controls.JFXTabPane;
|
||||
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
public abstract class TabbedOverlay<T extends TabbedOverlay> extends Overlay {
|
||||
|
||||
protected JFXTabPane tabPane;
|
||||
|
||||
protected void createTabPane() {
|
||||
this.tabPane = new JFXTabPane();
|
||||
tabPane.setMinWidth(width);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Region getRootContainer() {
|
||||
return tabPane;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,326 @@
|
|||
package bisq.desktop.main.overlays.windows;
|
||||
|
||||
import bisq.desktop.Navigation;
|
||||
import bisq.desktop.components.AutoTooltipLabel;
|
||||
import bisq.desktop.components.AutoTooltipTableColumn;
|
||||
import bisq.desktop.components.TableGroupHeadline;
|
||||
import bisq.desktop.main.dao.governance.ProposalDisplay;
|
||||
import bisq.desktop.main.dao.governance.result.VoteListItem;
|
||||
import bisq.desktop.main.overlays.TabbedOverlay;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.proposal.param.ChangeParamValidator;
|
||||
import bisq.core.dao.state.model.governance.Ballot;
|
||||
import bisq.core.dao.state.model.governance.EvaluatedProposal;
|
||||
import bisq.core.dao.state.model.governance.Proposal;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import bisq.common.util.Tuple2;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.layout.ColumnConstraints;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
|
||||
import javafx.collections.transformation.SortedList;
|
||||
|
||||
import javafx.util.Callback;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.addButtonAfterGroup;
|
||||
|
||||
@Slf4j
|
||||
public class ProposalResultsWindow extends TabbedOverlay<ProposalResultsWindow> {
|
||||
|
||||
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 EvaluatedProposal evaluatedProposal;
|
||||
private Ballot ballot;
|
||||
private boolean isVoteIncludedInResult;
|
||||
private SortedList<VoteListItem> sortedVotes;
|
||||
private Tab proposalTab, votesTab;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public ProposalResultsWindow(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(EvaluatedProposal evaluatedProposal, Ballot ballot,
|
||||
boolean isVoteIncludedInResult, SortedList<VoteListItem> sortedVotes) {
|
||||
|
||||
this.evaluatedProposal = evaluatedProposal;
|
||||
this.ballot = ballot;
|
||||
this.isVoteIncludedInResult = isVoteIncludedInResult;
|
||||
this.sortedVotes = sortedVotes;
|
||||
|
||||
rowIndex = 0;
|
||||
width = 1000;
|
||||
createTabPane();
|
||||
createGridPane();
|
||||
addContent(evaluatedProposal, ballot);
|
||||
|
||||
display();
|
||||
}
|
||||
|
||||
private void createTabs() {
|
||||
proposalTab = new Tab("PROPOSAL");
|
||||
votesTab = new Tab("VOTES");
|
||||
|
||||
tabPane.getTabs().addAll(proposalTab, votesTab);
|
||||
|
||||
tabPane.getSelectionModel().selectedItemProperty().addListener((ov, oldValue, newValue) -> {
|
||||
if (newValue != oldValue) {
|
||||
stage.sizeToScene();
|
||||
layout();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@Override
|
||||
protected void onShow() {
|
||||
super.onShow();
|
||||
|
||||
setupCloseKeyHandler(stage.getScene());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createGridPane() {
|
||||
super.createGridPane();
|
||||
gridPane.getColumnConstraints().remove(1);
|
||||
}
|
||||
|
||||
private void addContent(EvaluatedProposal evaluatedProposal, Ballot ballot) {
|
||||
Proposal proposal = evaluatedProposal.getProposal();
|
||||
ProposalDisplay proposalDisplay = new ProposalDisplay(gridPane, bsqFormatter, daoFacade, null,
|
||||
navigation, preferences);
|
||||
proposalDisplay.createAllFields("", rowIndex, -Layout.FIRST_ROW_DISTANCE, proposal.getType(),
|
||||
false, "last");
|
||||
proposalDisplay.setEditable(false);
|
||||
|
||||
proposalDisplay.applyProposalPayload(proposal);
|
||||
proposalDisplay.applyEvaluatedProposal(evaluatedProposal);
|
||||
proposalDisplay.setIsVoteIncludedInResult(isVoteIncludedInResult);
|
||||
|
||||
Tuple2<Long, Long> meritAndStakeTuple = daoFacade.getMeritAndStakeForProposal(proposal.getTxId());
|
||||
long merit = meritAndStakeTuple.first;
|
||||
long stake = meritAndStakeTuple.second;
|
||||
proposalDisplay.applyBallotAndVoteWeight(ballot, merit, stake);
|
||||
|
||||
Region spacer = new Region();
|
||||
GridPane.setVgrow(spacer, Priority.ALWAYS);
|
||||
GridPane.setRowIndex(spacer, proposalDisplay.incrementAndGetGridRow());
|
||||
gridPane.getChildren().add(spacer);
|
||||
|
||||
addCloseButton(gridPane, proposalDisplay.incrementAndGetGridRow());
|
||||
|
||||
createTabs();
|
||||
|
||||
gridPane.setPadding(new Insets(0, 15, 15, 15));
|
||||
proposalTab.setContent(gridPane);
|
||||
votesTab.setContent(createVotesTable());
|
||||
}
|
||||
|
||||
private Button addCloseButton(GridPane gridPane, int rowIndex) {
|
||||
Button closeButton = addButtonAfterGroup(gridPane, rowIndex, Res.get("shared.close"));
|
||||
closeButton.setOnAction(event -> doClose());
|
||||
return closeButton;
|
||||
}
|
||||
|
||||
private GridPane createVotesTable() {
|
||||
GridPane votesGridPane = new GridPane();
|
||||
votesGridPane.setHgap(5);
|
||||
votesGridPane.setVgap(5);
|
||||
votesGridPane.setPadding(new Insets(15));
|
||||
|
||||
ColumnConstraints columnConstraints1 = new ColumnConstraints();
|
||||
columnConstraints1.setHalignment(HPos.RIGHT);
|
||||
columnConstraints1.setHgrow(Priority.ALWAYS);
|
||||
votesGridPane.getColumnConstraints().addAll(columnConstraints1);
|
||||
|
||||
int gridRow = 0;
|
||||
|
||||
TableGroupHeadline votesTableHeader = new TableGroupHeadline(Res.get("dao.results.proposals.voting.detail.header"));
|
||||
GridPane.setRowIndex(votesTableHeader, gridRow);
|
||||
GridPane.setMargin(votesTableHeader, new Insets(8, 0, 0, 0));
|
||||
GridPane.setColumnSpan(votesTableHeader, 2);
|
||||
votesGridPane.getChildren().add(votesTableHeader);
|
||||
|
||||
TableView votesTableView = new TableView<>();
|
||||
votesTableView.setPlaceholder(new AutoTooltipLabel(Res.get("table.placeholder.noData")));
|
||||
votesTableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
|
||||
createColumns(votesTableView);
|
||||
GridPane.setRowIndex(votesTableView, gridRow);
|
||||
GridPane.setMargin(votesTableView, new Insets(Layout.FIRST_ROW_DISTANCE, 0, 0, 0));
|
||||
GridPane.setColumnSpan(votesTableView, 2);
|
||||
GridPane.setVgrow(votesTableView, Priority.ALWAYS);
|
||||
votesGridPane.getChildren().add(votesTableView);
|
||||
|
||||
votesTableView.setItems(sortedVotes);
|
||||
|
||||
addCloseButton(votesGridPane, ++gridRow);
|
||||
|
||||
return votesGridPane;
|
||||
}
|
||||
|
||||
private void createColumns(TableView<VoteListItem> votesTableView) {
|
||||
TableColumn<VoteListItem, VoteListItem> column;
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.results.votes.table.header.vote"));
|
||||
column.setSortable(false);
|
||||
column.setMinWidth(50);
|
||||
column.setMaxWidth(column.getMinWidth());
|
||||
column.getStyleClass().add("first-column");
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<VoteListItem, VoteListItem> call(
|
||||
TableColumn<VoteListItem, VoteListItem> column) {
|
||||
return new TableCell<>() {
|
||||
private Label icon;
|
||||
|
||||
@Override
|
||||
public void updateItem(final VoteListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
Tuple2<AwesomeIcon, String> iconStyleTuple = item.getIconStyleTuple();
|
||||
icon = new Label();
|
||||
AwesomeDude.setIcon(icon, iconStyleTuple.first);
|
||||
icon.getStyleClass().add(iconStyleTuple.second);
|
||||
setGraphic(icon);
|
||||
} else {
|
||||
setGraphic(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
votesTableView.getColumns().add(column);
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.results.votes.table.header.stakeAndMerit"));
|
||||
column.setSortable(false);
|
||||
column.setMinWidth(100);
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<VoteListItem, VoteListItem> call(
|
||||
TableColumn<VoteListItem, VoteListItem> column) {
|
||||
return new TableCell<>() {
|
||||
@Override
|
||||
public void updateItem(final VoteListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(item.getMeritAndStake());
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
votesTableView.getColumns().add(column);
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.results.votes.table.header.merit"));
|
||||
column.setSortable(false);
|
||||
column.setMinWidth(100);
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<VoteListItem, VoteListItem> call(
|
||||
TableColumn<VoteListItem, VoteListItem> column) {
|
||||
return new TableCell<>() {
|
||||
@Override
|
||||
public void updateItem(final VoteListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(item.getMerit());
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
votesTableView.getColumns().add(column);
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.results.votes.table.header.stake"));
|
||||
column.setSortable(false);
|
||||
column.setMinWidth(100);
|
||||
column.getStyleClass().add("last-column");
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<VoteListItem, VoteListItem> call(
|
||||
TableColumn<VoteListItem, VoteListItem> column) {
|
||||
return new TableCell<>() {
|
||||
@Override
|
||||
public void updateItem(final VoteListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(item.getStake());
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
votesTableView.getColumns().add(column);
|
||||
}
|
||||
|
||||
private void setupCloseKeyHandler(Scene scene) {
|
||||
scene.setOnKeyPressed(e -> {
|
||||
if (e.getCode() == KeyCode.ESCAPE || e.getCode() == KeyCode.ENTER) {
|
||||
e.consume();
|
||||
doClose();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
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.desktop.util.Layout;
|
||||
|
||||
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, -Layout.FIRST_ROW_DISTANCE, proposal.getType(),
|
||||
false, "last");
|
||||
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();
|
||||
|
||||
DaoPhase.Phase currentPhase = daoFacade.phaseProperty().get();
|
||||
|
||||
if (currentPhase == 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 (currentPhase == DaoPhase.Phase.BLIND_VOTE &&
|
||||
!hasAlreadyVoted &&
|
||||
daoFacade.isInPhaseButNotLastBlock(currentPhase)) {
|
||||
int rowIndexForVoting = proposalDisplay.incrementAndGetGridRow();
|
||||
Tuple3<Button, Button, Button> tuple = add3ButtonsAfterGroup(gridPane,
|
||||
rowIndexForVoting,
|
||||
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();
|
||||
});
|
||||
|
||||
Button closeButton = addButtonAfterGroup(gridPane, ++rowIndexForVoting, Res.get("shared.close"));
|
||||
closeButton.setOnAction(event -> 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();
|
||||
}
|
||||
}
|
|
@ -1743,11 +1743,21 @@ public class FormBuilder {
|
|||
}
|
||||
|
||||
public static <T> TableView<T> addTableViewWithHeader(GridPane gridPane, int rowIndex, String headerText) {
|
||||
return addTableViewWithHeader(gridPane, rowIndex, headerText, 0);
|
||||
return addTableViewWithHeader(gridPane, rowIndex, headerText, 0, null);
|
||||
}
|
||||
|
||||
public static <T> TableView<T> addTableViewWithHeader(GridPane gridPane, int rowIndex, String headerText, String groupStyle) {
|
||||
return addTableViewWithHeader(gridPane, rowIndex, headerText, 0, groupStyle);
|
||||
}
|
||||
|
||||
public static <T> TableView<T> addTableViewWithHeader(GridPane gridPane, int rowIndex, String headerText, int top) {
|
||||
addTitledGroupBg(gridPane, rowIndex, 1, headerText, top);
|
||||
return addTableViewWithHeader(gridPane, rowIndex, headerText, top, null);
|
||||
}
|
||||
|
||||
public static <T> TableView<T> addTableViewWithHeader(GridPane gridPane, int rowIndex, String headerText, int top, String groupStyle) {
|
||||
TitledGroupBg titledGroupBg = addTitledGroupBg(gridPane, rowIndex, 1, headerText, top);
|
||||
|
||||
if (groupStyle != null) titledGroupBg.getStyleClass().add(groupStyle);
|
||||
|
||||
TableView<T> tableView = new TableView<>();
|
||||
GridPane.setRowIndex(tableView, rowIndex);
|
||||
|
|
|
@ -28,9 +28,11 @@ public class Layout {
|
|||
public static final double FLOATING_LABEL_DISTANCE = 20d;
|
||||
public static final double GROUP_DISTANCE = 40d;
|
||||
public static final double COMPACT_GROUP_DISTANCE = 30d;
|
||||
public static final double GROUP_DISTANCE_WITHOUT_SEPARATOR = 20d;
|
||||
public static final double FIRST_ROW_AND_GROUP_DISTANCE = GROUP_DISTANCE + FIRST_ROW_DISTANCE;
|
||||
public static final double COMPACT_FIRST_ROW_AND_GROUP_DISTANCE = COMPACT_GROUP_DISTANCE + FIRST_ROW_DISTANCE;
|
||||
public static final double COMPACT_FIRST_ROW_AND_COMPACT_GROUP_DISTANCE = COMPACT_GROUP_DISTANCE + COMPACT_FIRST_ROW_DISTANCE;
|
||||
public static final double COMPACT_FIRST_ROW_AND_GROUP_DISTANCE_WITHOUT_SEPARATOR = GROUP_DISTANCE_WITHOUT_SEPARATOR + COMPACT_FIRST_ROW_DISTANCE;
|
||||
public static final double TWICE_FIRST_ROW_AND_GROUP_DISTANCE = GROUP_DISTANCE + TWICE_FIRST_ROW_DISTANCE;
|
||||
public static final double PADDING_WINDOW = 20d;
|
||||
public static double PADDING = 10d;
|
||||
|
|
Loading…
Add table
Reference in a new issue