mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2025-11-05 11:56:37 +00:00
Improve pool selection ui
This commit is contained in:
parent
25f1ca2529
commit
865e3b8ee6
4 changed files with 310 additions and 93 deletions
|
|
@ -3,6 +3,9 @@ package com.sparrowwallet.sparrow.joinstr;
|
|||
import com.sparrowwallet.sparrow.joinstr.control.JoinstrInfoPane;
|
||||
import com.sparrowwallet.sparrow.joinstr.control.JoinstrPoolList;
|
||||
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.TextField;
|
||||
|
|
@ -16,26 +19,100 @@ public class OtherPoolsController extends JoinstrFormController {
|
|||
@FXML
|
||||
private TextField searchTextField;
|
||||
|
||||
private JoinstrPoolList joinstrPoolList;
|
||||
private JoinstrInfoPane joinstrInfoPane;
|
||||
|
||||
@Override
|
||||
public void initializeView() {
|
||||
try {
|
||||
joinstrPoolList = new JoinstrPoolList(JoinstrAction.JOIN);
|
||||
|
||||
JoinstrPoolList joinstrPoolList = new JoinstrPoolList(JoinstrAction.JOIN);
|
||||
joinstrPoolList.configureWithJoinButtons();
|
||||
|
||||
JoinstrInfoPane joinstrInfoPane = new JoinstrInfoPane();
|
||||
// Add sample pool data
|
||||
addSamplePoolData();
|
||||
|
||||
joinstrInfoPane = new JoinstrInfoPane();
|
||||
joinstrInfoPane.initInfoPane();
|
||||
joinstrInfoPane.setVisible(false);
|
||||
joinstrInfoPane.setManaged(false);
|
||||
|
||||
joinstrPoolList.setOnPoolSelectedListener(pool -> {
|
||||
if (pool != null) {
|
||||
joinstrInfoPane.setVisible(true);
|
||||
joinstrInfoPane.setManaged(true);
|
||||
joinstrInfoPane.updatePoolInfo(pool);
|
||||
} else {
|
||||
joinstrInfoPane.setVisible(false);
|
||||
joinstrInfoPane.setManaged(false);
|
||||
}
|
||||
});
|
||||
|
||||
contentVBox.getChildren().addAll(joinstrPoolList, joinstrInfoPane);
|
||||
|
||||
searchTextField.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
filterPools(newValue);
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
if(e != null) {}
|
||||
if(e != null) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleSearchButton(ActionEvent e) {
|
||||
if(e.getSource()==searchTextField) {
|
||||
System.out.println(searchTextField.getText());
|
||||
};
|
||||
private void addSamplePoolData() {
|
||||
// Create the two sample pools
|
||||
JoinstrPool pool1 = new JoinstrPool(
|
||||
"relay.joinstr.xyz",
|
||||
"03ab4...e92f",
|
||||
"0.001 BTC",
|
||||
"4/5",
|
||||
"00:00:00 UTC"
|
||||
);
|
||||
|
||||
JoinstrPool pool2 = new JoinstrPool(
|
||||
"relay.joinstr.xyz",
|
||||
"02c4f...19a3",
|
||||
"0.005 BTC",
|
||||
"3/7",
|
||||
"00:00:00 UTC"
|
||||
);
|
||||
|
||||
joinstrPoolList.addPool(pool1);
|
||||
joinstrPoolList.addPool(pool2);
|
||||
}
|
||||
|
||||
}
|
||||
private void filterPools(String searchText) {
|
||||
joinstrPoolList.filterPools(searchText);
|
||||
}
|
||||
|
||||
public void handleSearchButton(ActionEvent e) {
|
||||
if(e.getSource() == searchTextField) {
|
||||
filterPools(searchTextField.getText());
|
||||
}
|
||||
}
|
||||
|
||||
public static class JoinstrPool {
|
||||
private final SimpleStringProperty relay;
|
||||
private final SimpleStringProperty pubkey;
|
||||
private final SimpleStringProperty denomination;
|
||||
private final SimpleStringProperty peers;
|
||||
private final SimpleStringProperty timeout;
|
||||
|
||||
public JoinstrPool(String relay, String pubkey, String denomination,
|
||||
String peers, String timeout) {
|
||||
this.relay = new SimpleStringProperty(relay);
|
||||
this.pubkey = new SimpleStringProperty(pubkey);
|
||||
this.denomination = new SimpleStringProperty(denomination);
|
||||
this.peers = new SimpleStringProperty(peers);
|
||||
this.timeout = new SimpleStringProperty(timeout);
|
||||
}
|
||||
|
||||
public String getRelay() { return relay.get(); }
|
||||
public String getPubkey() { return pubkey.get(); }
|
||||
public String getDenomination() { return denomination.get(); }
|
||||
public String getPeers() { return peers.get(); }
|
||||
public String getTimeout() { return timeout.get(); }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +1,81 @@
|
|||
package com.sparrowwallet.sparrow.joinstr.control;
|
||||
|
||||
import com.sparrowwallet.sparrow.joinstr.OtherPoolsController.JoinstrPool;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.ColumnConstraints;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
public class JoinstrInfoPane extends AnchorPane {
|
||||
public class JoinstrInfoPane extends VBox {
|
||||
|
||||
public JoinstrInfoPane() { super(); }
|
||||
private Label titleLabel;
|
||||
private Label relayLabel;
|
||||
private Label pubkeyLabel;
|
||||
private Label denominationLabel;
|
||||
private Label relayValueLabel;
|
||||
private Label pubkeyValueLabel;
|
||||
private Label denominationValueLabel;
|
||||
|
||||
public void initInfoPane() {
|
||||
|
||||
GridPane mainGridPane = new GridPane();
|
||||
|
||||
Label relayTitleLabel = new Label();
|
||||
relayTitleLabel.setText("Relay:");
|
||||
GridPane.setRowIndex(relayTitleLabel, 0);
|
||||
GridPane.setColumnIndex(relayTitleLabel, 0);
|
||||
|
||||
Label pubkeyTitleLabel = new Label();
|
||||
pubkeyTitleLabel.setText("Pubkey:");
|
||||
GridPane.setRowIndex(pubkeyTitleLabel, 1);
|
||||
GridPane.setColumnIndex(pubkeyTitleLabel, 0);
|
||||
|
||||
Label denominationTitleLabel = new Label();
|
||||
denominationTitleLabel.setText("Denomination:");
|
||||
GridPane.setRowIndex(denominationTitleLabel, 2);
|
||||
GridPane.setColumnIndex(denominationTitleLabel, 0);
|
||||
|
||||
|
||||
Label relayDescLabel = new Label();
|
||||
relayDescLabel.setText("Relay desc");
|
||||
GridPane.setRowIndex(relayDescLabel, 0);
|
||||
GridPane.setColumnIndex(relayDescLabel, 1);
|
||||
|
||||
Label pubkeyDescLabel = new Label();
|
||||
pubkeyDescLabel.setText("Pubkey desc");
|
||||
GridPane.setRowIndex(pubkeyDescLabel, 1);
|
||||
GridPane.setColumnIndex(pubkeyDescLabel, 1);
|
||||
|
||||
Label denominationDescLabel = new Label();
|
||||
denominationDescLabel.setText("Denomination desc");
|
||||
GridPane.setRowIndex(denominationDescLabel, 2);
|
||||
GridPane.setColumnIndex(denominationDescLabel, 1);
|
||||
|
||||
getChildren().add(mainGridPane);
|
||||
public JoinstrInfoPane() {
|
||||
setStyle("-fx-background-color: #222222; -fx-padding: 15;");
|
||||
setSpacing(10);
|
||||
}
|
||||
|
||||
}
|
||||
public void initInfoPane() {
|
||||
titleLabel = new Label("Selected Pool Details");
|
||||
titleLabel.setStyle("-fx-font-size: 16px; -fx-text-fill: white; -fx-font-weight: bold;");
|
||||
getChildren().add(titleLabel);
|
||||
|
||||
GridPane detailsGrid = new GridPane();
|
||||
detailsGrid.setHgap(10);
|
||||
detailsGrid.setVgap(10);
|
||||
|
||||
ColumnConstraints column1 = new ColumnConstraints();
|
||||
column1.setPrefWidth(100);
|
||||
ColumnConstraints column2 = new ColumnConstraints();
|
||||
column2.setPrefWidth(400);
|
||||
detailsGrid.getColumnConstraints().addAll(column1, column2);
|
||||
|
||||
relayLabel = new Label("Relay:");
|
||||
relayLabel.setStyle("-fx-text-fill: #aaaaaa;");
|
||||
relayValueLabel = new Label();
|
||||
relayValueLabel.setStyle("-fx-text-fill: white;");
|
||||
|
||||
pubkeyLabel = new Label("Pubkey:");
|
||||
pubkeyLabel.setStyle("-fx-text-fill: #aaaaaa;");
|
||||
pubkeyValueLabel = new Label();
|
||||
pubkeyValueLabel.setStyle("-fx-text-fill: white;");
|
||||
|
||||
denominationLabel = new Label("Denomination:");
|
||||
denominationLabel.setStyle("-fx-text-fill: #aaaaaa;");
|
||||
denominationValueLabel = new Label();
|
||||
denominationValueLabel.setStyle("-fx-text-fill: white;");
|
||||
|
||||
detailsGrid.add(relayLabel, 0, 0);
|
||||
detailsGrid.add(relayValueLabel, 1, 0);
|
||||
detailsGrid.add(pubkeyLabel, 0, 1);
|
||||
detailsGrid.add(pubkeyValueLabel, 1, 1);
|
||||
detailsGrid.add(denominationLabel, 0, 2);
|
||||
detailsGrid.add(denominationValueLabel, 1, 2);
|
||||
|
||||
getChildren().add(detailsGrid);
|
||||
}
|
||||
|
||||
public void updatePoolInfo(JoinstrPool pool) {
|
||||
if (pool != null) {
|
||||
relayValueLabel.setText(pool.getRelay());
|
||||
pubkeyValueLabel.setText(pool.getPubkey());
|
||||
denominationValueLabel.setText(pool.getDenomination());
|
||||
} else {
|
||||
clearPoolInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearPoolInfo() {
|
||||
relayValueLabel.setText("");
|
||||
pubkeyValueLabel.setText("");
|
||||
denominationValueLabel.setText("");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +1,149 @@
|
|||
package com.sparrowwallet.sparrow.joinstr.control;
|
||||
|
||||
import com.sparrowwallet.sparrow.joinstr.JoinstrAction;
|
||||
import com.sparrowwallet.sparrow.joinstr.JoinstrPool;
|
||||
import com.sparrowwallet.sparrow.joinstr.OtherPoolsController.JoinstrPool;
|
||||
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.collections.transformation.FilteredList;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Callback;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class JoinstrPoolList extends VBox {
|
||||
|
||||
private final JoinstrAction action;
|
||||
private TableView<JoinstrPool> poolTableView;
|
||||
private ObservableList<JoinstrPool> poolData;
|
||||
private FilteredList<JoinstrPool> filteredData;
|
||||
private Consumer<JoinstrPool> onPoolSelectedListener;
|
||||
|
||||
public JoinstrPoolList(JoinstrAction action) {
|
||||
super();
|
||||
this.action = action;
|
||||
initialize();
|
||||
}
|
||||
|
||||
setPrefHeight(500);
|
||||
setPrefWidth(500);
|
||||
setSpacing(10);
|
||||
private void initialize() {
|
||||
// Create the table
|
||||
poolTableView = new TableView<>();
|
||||
poolTableView.setStyle("-fx-background-color: #222222; -fx-text-fill: white;");
|
||||
|
||||
setMaxWidth(Double.MAX_VALUE);
|
||||
setMaxHeight(Double.MAX_VALUE);
|
||||
// Create data storage
|
||||
poolData = FXCollections.observableArrayList();
|
||||
filteredData = new FilteredList<>(poolData, p -> true);
|
||||
poolTableView.setItems(filteredData);
|
||||
|
||||
JoinstrPoolListRow header = new JoinstrPoolListRow();
|
||||
getChildren().add(header);
|
||||
// Create standard columns
|
||||
TableColumn<JoinstrPool, String> relayColumn = new TableColumn<>("Relay");
|
||||
relayColumn.setCellValueFactory(new PropertyValueFactory<>("relay"));
|
||||
relayColumn.setPrefWidth(150);
|
||||
|
||||
JoinstrPool[] poolsDummy = getDummyData();
|
||||
TableColumn<JoinstrPool, String> pubkeyColumn = new TableColumn<>("Pubkey");
|
||||
pubkeyColumn.setCellValueFactory(new PropertyValueFactory<>("pubkey"));
|
||||
pubkeyColumn.setPrefWidth(200);
|
||||
|
||||
for (JoinstrPool joinstrPool : poolsDummy) {
|
||||
JoinstrPoolListRow joinstrRow = new JoinstrPoolListRow(joinstrPool, action);
|
||||
getChildren().add(joinstrRow);
|
||||
TableColumn<JoinstrPool, String> denominationColumn = new TableColumn<>("Denomination");
|
||||
denominationColumn.setCellValueFactory(new PropertyValueFactory<>("denomination"));
|
||||
denominationColumn.setPrefWidth(150);
|
||||
|
||||
TableColumn<JoinstrPool, String> peersColumn = new TableColumn<>("Peers");
|
||||
peersColumn.setCellValueFactory(new PropertyValueFactory<>("peers"));
|
||||
peersColumn.setPrefWidth(80);
|
||||
|
||||
TableColumn<JoinstrPool, String> timeoutColumn = new TableColumn<>("Timeout");
|
||||
timeoutColumn.setCellValueFactory(new PropertyValueFactory<>("timeout"));
|
||||
timeoutColumn.setPrefWidth(100);
|
||||
|
||||
poolTableView.getColumns().addAll(
|
||||
relayColumn,
|
||||
pubkeyColumn,
|
||||
denominationColumn,
|
||||
peersColumn,
|
||||
timeoutColumn
|
||||
);
|
||||
|
||||
poolTableView.getSelectionModel().selectedItemProperty().addListener(
|
||||
(obs, oldSelection, newSelection) -> {
|
||||
if (onPoolSelectedListener != null) {
|
||||
onPoolSelectedListener.accept(newSelection);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
getChildren().add(poolTableView);
|
||||
setVgrow(poolTableView, javafx.scene.layout.Priority.ALWAYS);
|
||||
}
|
||||
|
||||
public void configureWithJoinButtons() {
|
||||
TableColumn<JoinstrPool, Void> joinButtonColumn = new TableColumn<>("");
|
||||
joinButtonColumn.setPrefWidth(100);
|
||||
|
||||
joinButtonColumn.setCellFactory(new Callback<>() {
|
||||
@Override
|
||||
public TableCell<JoinstrPool, Void> call(final TableColumn<JoinstrPool, Void> param) {
|
||||
return new TableCell<>() {
|
||||
private final Button joinButton = new Button("Join");
|
||||
{
|
||||
joinButton.setStyle(
|
||||
"-fx-background-color: #2196F3; " +
|
||||
"-fx-text-fill: white; " +
|
||||
"-fx-cursor: hand;"
|
||||
);
|
||||
|
||||
joinButton.setOnAction(event -> {
|
||||
JoinstrPool pool = getTableView().getItems().get(getIndex());
|
||||
System.out.println("Join button clicked for pool: " + pool.getPubkey());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateItem(Void item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (empty) {
|
||||
setGraphic(null);
|
||||
} else {
|
||||
setGraphic(joinButton);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
poolTableView.getColumns().add(joinButtonColumn);
|
||||
}
|
||||
|
||||
public void addPool(JoinstrPool pool) {
|
||||
poolData.add(pool);
|
||||
}
|
||||
|
||||
public void clearPools() {
|
||||
poolData.clear();
|
||||
}
|
||||
|
||||
public void filterPools(String searchText) {
|
||||
if (searchText == null || searchText.isEmpty()) {
|
||||
filteredData.setPredicate(p -> true);
|
||||
} else {
|
||||
String lowercaseFilter = searchText.toLowerCase();
|
||||
filteredData.setPredicate(pool ->
|
||||
pool.getRelay().toLowerCase().contains(lowercaseFilter) ||
|
||||
pool.getPubkey().toLowerCase().contains(lowercaseFilter) ||
|
||||
pool.getDenomination().toLowerCase().contains(lowercaseFilter)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private JoinstrPool[] getDummyData() {
|
||||
|
||||
return new JoinstrPool[]{ new JoinstrPool("Relay1", 1234, "pubkey1", 0.001),
|
||||
new JoinstrPool("Relay2", 1234, "pubkey2", 0.002),
|
||||
new JoinstrPool("Relay3", 1234, "pubkey3", 0.005)};
|
||||
public void setOnPoolSelectedListener(Consumer<JoinstrPool> listener) {
|
||||
this.onPoolSelectedListener = listener;
|
||||
}
|
||||
|
||||
}
|
||||
public JoinstrPool getSelectedPool() {
|
||||
return poolTableView.getSelectionModel().getSelectedItem();
|
||||
}
|
||||
}
|
||||
|
|
@ -4,28 +4,26 @@
|
|||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
|
||||
<?import com.sparrowwallet.sparrow.joinstr.control.JoinstrPoolList ?>
|
||||
<?import com.sparrowwallet.sparrow.joinstr.control.JoinstrInfoPane ?>
|
||||
<HBox xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.joinstr.OtherPoolsController">
|
||||
|
||||
<BorderPane stylesheets="@joinstr.css, @../wallet/wallet.css, @../general.css" styleClass="wallet-pane" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.joinstr.OtherPoolsController">
|
||||
<padding>
|
||||
<Insets top="30" right="30" bottom="30" left="30"/>
|
||||
</padding>
|
||||
<center>
|
||||
<VBox maxWidth="Infinity" HBox.hgrow="ALWAYS" fx:id="contentVBox">
|
||||
<GridPane maxWidth="Infinity" HBox.hgrow="ALWAYS" hgap="10.0" vgap="10.0">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints percentWidth="80" />
|
||||
<ColumnConstraints percentWidth="20" />
|
||||
</columnConstraints>
|
||||
<children>
|
||||
<VBox maxWidth="Infinity" HBox.hgrow="ALWAYS" GridPane.rowIndex="0" GridPane.columnIndex="0">
|
||||
<Label styleClass="title">Available Pools</Label>
|
||||
<Label styleClass="sub-title">Select a pool to join</Label>
|
||||
</VBox>
|
||||
<TextField GridPane.rowIndex="0" GridPane.columnIndex="1" fx:id="searchTextField" promptText="Search pools..." onAction="#handleSearchButton" />
|
||||
</children>
|
||||
</GridPane>
|
||||
</VBox>
|
||||
</center>
|
||||
</BorderPane>
|
||||
<BorderPane HBox.hgrow="ALWAYS" style="-fx-background-color: #333333;">
|
||||
<padding>
|
||||
<Insets top="20" right="20" bottom="20" left="20"/>
|
||||
</padding>
|
||||
<top>
|
||||
<VBox spacing="10">
|
||||
<HBox alignment="CENTER_LEFT" spacing="20">
|
||||
<Label text="Available Pools" style="-fx-font-size: 24px; -fx-text-fill: white;"/>
|
||||
<Region HBox.hgrow="ALWAYS" />
|
||||
<TextField fx:id="searchTextField" promptText="Search pools..." prefWidth="250" style="-fx-background-color: #444444; -fx-text-fill: white; -fx-prompt-text-fill: #888888;" onAction="#handleSearchButton"/>
|
||||
</HBox>
|
||||
<Label text="Select a pool to join" style="-fx-font-size: 14px; -fx-text-fill: #aaaaaa;"/>
|
||||
</VBox>
|
||||
</top>
|
||||
|
||||
<center>
|
||||
<VBox fx:id="contentVBox" spacing="10">
|
||||
</VBox>
|
||||
</center>
|
||||
</BorderPane>
|
||||
</HBox>
|
||||
Loading…
Reference in a new issue