revise transaction pane

This commit is contained in:
Craig Raw 2020-03-28 13:39:21 +02:00
parent b6b18a2a7c
commit 7a2e503624
4 changed files with 157 additions and 108 deletions

View file

@ -8,6 +8,8 @@ import javafx.fxml.Initializable;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.layout.GridPane; import javafx.scene.layout.GridPane;
import tornadofx.control.DateTimePicker; import tornadofx.control.DateTimePicker;
import tornadofx.control.Field;
import tornadofx.control.Fieldset;
import java.net.URL; import java.net.URL;
import java.time.*; import java.time.*;
@ -22,43 +24,46 @@ public class HeadersController implements Initializable, TransactionListener {
private GridPane layout; private GridPane layout;
@FXML @FXML
private TextField idField; private TextField id;
@FXML @FXML
private Spinner<Integer> versionField; private Spinner<Integer> version;
@FXML @FXML
private Label segwitField; private TextField segwit;
@FXML @FXML
private Label segwitVersionLabel; private ToggleGroup locktimeType;
@FXML @FXML
private Spinner<Integer> segwitVersionField; private ToggleButton locktimeBlockType;
@FXML @FXML
private ToggleGroup locktimeTypeField; private ToggleButton locktimeDateType;
@FXML @FXML
private ToggleButton locktimeBlockTypeField; private Fieldset locktimeFieldset;
@FXML @FXML
private ToggleButton locktimeDateTypeField; private Field locktimeBlockField;
@FXML @FXML
private Spinner<Integer> locktimeBlockField; private Field locktimeDateField;
@FXML @FXML
private DateTimePicker locktimeDateField; private Spinner<Integer> locktimeBlock;
@FXML @FXML
private Label feeField; private DateTimePicker locktimeDate;
@FXML @FXML
private Label sizeField; private TextField fee;
@FXML @FXML
private Label virtualSizeField; private TextField size;
@FXML
private TextField virtualSize;
@Override @Override
public void initialize(URL location, ResourceBundle resources) { public void initialize(URL location, ResourceBundle resources) {
@ -71,38 +76,38 @@ public class HeadersController implements Initializable, TransactionListener {
updateTxId(); updateTxId();
versionField.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 2, (int)tx.getVersion())); version.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 2, (int)tx.getVersion()));
versionField.valueProperty().addListener((obs, oldValue, newValue) -> { version.valueProperty().addListener((obs, oldValue, newValue) -> {
tx.setVersion(newValue); tx.setVersion(newValue);
EventManager.get().notify(tx); EventManager.get().notify(tx);
}); });
segwitField.setText(tx.isSegwit() ? "Segwit" : "Legacy" ); String type = "Legacy";
if(tx.isSegwit()) { if(tx.isSegwit()) {
segwitVersionField.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 2, tx.getSegwitVersion())); type = "Segwit";
segwitVersionField.valueProperty().addListener((obs, oldValue, newValue) -> { if(tx.getSegwitVersion() == 2) {
tx.setSegwitVersion(newValue); type = "Taproot";
EventManager.get().notify(tx); }
});
} else {
layout.getChildren().removeAll(segwitVersionLabel, segwitVersionField);
} }
segwit.setText(type);
locktimeTypeField.selectedToggleProperty().addListener((ov, old_toggle, new_toggle) -> { locktimeType.selectedToggleProperty().addListener((ov, old_toggle, new_toggle) -> {
if(locktimeTypeField.getSelectedToggle() != null) { if(locktimeType.getSelectedToggle() != null) {
String selection = locktimeTypeField.getSelectedToggle().getUserData().toString(); String selection = locktimeType.getSelectedToggle().getUserData().toString();
if(selection.equals("block")) { if(selection.equals("block")) {
locktimeBlockField.setVisible(true); locktimeFieldset.getChildren().remove(locktimeDateField);
locktimeDateField.setVisible(false); locktimeFieldset.getChildren().remove(locktimeBlockField);
Integer block = locktimeBlockField.getValue(); locktimeFieldset.getChildren().add(locktimeBlockField);
Integer block = locktimeBlock.getValue();
if(block != null) { if(block != null) {
tx.setLockTime(block); tx.setLockTime(block);
EventManager.get().notify(tx); EventManager.get().notify(tx);
} }
} else { } else {
locktimeBlockField.setVisible(false); locktimeFieldset.getChildren().remove(locktimeBlockField);
locktimeDateField.setVisible(true); locktimeFieldset.getChildren().remove(locktimeDateField);
LocalDateTime date = locktimeDateField.getDateTimeValue(); locktimeFieldset.getChildren().add(locktimeDateField);
LocalDateTime date = locktimeDate.getDateTimeValue();
if(date != null) { if(date != null) {
tx.setLockTime(date.toEpochSecond(OffsetDateTime.now(ZoneId.systemDefault()).getOffset())); tx.setLockTime(date.toEpochSecond(OffsetDateTime.now(ZoneId.systemDefault()).getOffset()));
EventManager.get().notify(tx); EventManager.get().notify(tx);
@ -112,42 +117,39 @@ public class HeadersController implements Initializable, TransactionListener {
}); });
if(tx.getLockTime() < MAX_BLOCK_LOCKTIME) { if(tx.getLockTime() < MAX_BLOCK_LOCKTIME) {
locktimeBlockField.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, (int)MAX_BLOCK_LOCKTIME-1, (int)tx.getLockTime())); locktimeBlock.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, (int)MAX_BLOCK_LOCKTIME-1, (int)tx.getLockTime()));
locktimeBlockField.setVisible(true); locktimeType.selectToggle(locktimeBlockType);
locktimeDateField.setVisible(false);
locktimeTypeField.selectToggle(locktimeBlockTypeField);
} else { } else {
locktimeBlock.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, (int)MAX_BLOCK_LOCKTIME-1));
LocalDateTime date = Instant.ofEpochSecond(tx.getLockTime()).atZone(ZoneId.systemDefault()).toLocalDateTime(); LocalDateTime date = Instant.ofEpochSecond(tx.getLockTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
locktimeDateField.setDateTimeValue(date); locktimeDate.setDateTimeValue(date);
locktimeBlockField.setVisible(false); locktimeType.selectToggle(locktimeDateType);
locktimeDateField.setVisible(true);
locktimeTypeField.selectToggle(locktimeDateTypeField);
} }
locktimeBlockField.valueProperty().addListener((obs, oldValue, newValue) -> { locktimeBlock.valueProperty().addListener((obs, oldValue, newValue) -> {
tx.setLockTime(newValue); tx.setLockTime(newValue);
EventManager.get().notify(tx); EventManager.get().notify(tx);
}); });
locktimeDateField.setFormat("yyyy-MM-dd HH:mm:ss"); locktimeDate.setFormat("yyyy-MM-dd HH:mm:ss");
locktimeDateField.dateTimeValueProperty().addListener((obs, oldValue, newValue) -> { locktimeDate.dateTimeValueProperty().addListener((obs, oldValue, newValue) -> {
tx.setLockTime(newValue.toEpochSecond(OffsetDateTime.now(ZoneId.systemDefault()).getOffset())); tx.setLockTime(newValue.toEpochSecond(OffsetDateTime.now(ZoneId.systemDefault()).getOffset()));
EventManager.get().notify(tx); EventManager.get().notify(tx);
}); });
if(form.getPsbt() != null) { if(form.getPsbt() != null) {
feeField.setText(form.getPsbt().getFee().toString() + " sats"); fee.setText(form.getPsbt().getFee().toString() + " sats");
} else { } else {
feeField.setText("Unknown"); fee.setText("Unknown");
} }
sizeField.setText(tx.getSize() + " B"); size.setText(tx.getSize() + " B");
virtualSizeField.setText(tx.getVirtualSize() + " vB"); virtualSize.setText(tx.getVirtualSize() + " vB");
} }
private void updateTxId() { private void updateTxId() {
idField.setText(headersForm.getTransaction().calculateTxId(false).toString()); id.setText(headersForm.getTransaction().calculateTxId(false).toString());
} }
@Override @Override

View file

@ -2,81 +2,110 @@
<?import javafx.geometry.*?> <?import javafx.geometry.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?> <?import javafx.scene.control.TextField?>
<?import javafx.scene.control.Spinner?> <?import javafx.scene.control.Spinner?>
<?import javafx.scene.control.ToggleButton?> <?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.control.ToggleGroup?> <?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.control.Separator?> <?import javafx.scene.control.Separator?>
<?import tornadofx.control.DateTimePicker?> <?import tornadofx.control.DateTimePicker?>
<?import tornadofx.control.Form?>
<?import tornadofx.control.Fieldset?>
<?import tornadofx.control.Field?>
<GridPane fx:id="layout" hgap="10.0" prefHeight="350.0" prefWidth="600.0" vgap="10.0" alignment="CENTER" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.craigraw.sparrow.form.HeadersController" stylesheets="@../general.css"> <GridPane fx:id="layout" hgap="10.0" prefHeight="350.0" prefWidth="600.0" vgap="10.0" alignment="CENTER" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.craigraw.sparrow.form.HeadersController" stylesheets="@../general.css">
<padding> <padding>
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" /> <Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
</padding> </padding>
<columnConstraints> <columnConstraints>
<ColumnConstraints minWidth="100" prefWidth="100" <ColumnConstraints minWidth="290" prefWidth="290"
maxWidth="Infinity" halignment="RIGHT"> maxWidth="Infinity">
</ColumnConstraints> </ColumnConstraints>
<ColumnConstraints minWidth="200" prefWidth="200" <ColumnConstraints minWidth="290" prefWidth="290"
maxWidth="Infinity" hgrow="ALWAYS"> maxWidth="Infinity">
</ColumnConstraints> </ColumnConstraints>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints /> <RowConstraints />
</rowConstraints> </rowConstraints>
<!-- Add Header Label --> <Form GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="2">
<Label text="Headers" GridPane.columnIndex="0" <Fieldset text="Transaction" inputGrow="SOMETIMES">
GridPane.rowIndex="0" GridPane.columnSpan="2" <Field text="ID:">
GridPane.rowSpan="1" GridPane.halignment="LEFT" > <TextField fx:id="id" editable="false" styleClass="copyable-label, id" prefWidth="520" minWidth="520"/>
<font> </Field>
<Font name="Arial" size="24" ></Font> </Fieldset>
</font> </Form>
<GridPane.margin>
<Insets top="0" right="0" bottom="10" left="0"></Insets>
</GridPane.margin>
</Label>
<Label text="Transaction ID: " GridPane.columnIndex="0" GridPane.rowIndex="1" /> <Separator GridPane.columnIndex="0" GridPane.rowIndex="1" GridPane.columnSpan="2" styleClass="form-separator"/>
<TextField fx:id="idField" editable="false" styleClass="copyable-label" prefHeight="40" prefWidth="520" minWidth="520" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<Label text="Version: " GridPane.columnIndex="0" GridPane.rowIndex="2" /> <Form GridPane.columnIndex="0" GridPane.rowIndex="2">
<Spinner fx:id="versionField" prefHeight="40" prefWidth="60" editable="true" GridPane.columnIndex="1" GridPane.rowIndex="2" /> <Fieldset text="Headers" inputGrow="SOMETIMES">
<Field text="Version:">
<Spinner fx:id="version" prefWidth="60" editable="true" />
</Field>
<Field text="Type:">
<TextField fx:id="segwit" editable="false" styleClass="copyable-label"/>
</Field>
</Fieldset>
</Form>
<Label text="Type: " GridPane.columnIndex="0" GridPane.rowIndex="3" /> <Form GridPane.columnIndex="1" GridPane.rowIndex="2">
<Label fx:id="segwitField" prefHeight="40" GridPane.columnIndex="1" GridPane.rowIndex="3"/> <Fieldset fx:id="locktimeFieldset" text="Locktime" inputGrow="SOMETIMES">
<Field text="Type:">
<HBox fillHeight="true">
<children>
<ToggleButton fx:id="locktimeBlockType" text="Block" userData="block">
<toggleGroup>
<ToggleGroup fx:id="locktimeType" />
</toggleGroup>
</ToggleButton>
<ToggleButton fx:id="locktimeDateType" text="Date" toggleGroup="$locktimeType" userData="date" />
</children>
</HBox>
</Field>
<Field fx:id="locktimeBlockField" text="Block:">
<Spinner fx:id="locktimeBlock" prefWidth="120"/>
</Field>
<Field fx:id="locktimeDateField" text="Date:">
<DateTimePicker fx:id="locktimeDate" prefWidth="180"/>
</Field>
</Fieldset>
</Form>
<Label fx:id="segwitVersionLabel" text="Segwit Version: " GridPane.columnIndex="0" GridPane.rowIndex="4" /> <Separator GridPane.columnIndex="0" GridPane.rowIndex="3" GridPane.columnSpan="2" styleClass="form-separator"/>
<Spinner fx:id="segwitVersionField" prefWidth="60" prefHeight="40" GridPane.columnIndex="1" GridPane.rowIndex="4"/>
<Separator GridPane.columnIndex="0" GridPane.rowIndex="5" GridPane.columnSpan="2" GridPane.rowSpan="1" GridPane.halignment="LEFT" /> <Form GridPane.columnIndex="0" GridPane.rowIndex="4">
<Fieldset text="Size" inputGrow="SOMETIMES">
<Field text="Bytes:">
<TextField fx:id="size" editable="false" styleClass="copyable-label" prefWidth="120"/>
</Field>
<Field text="vBytes:">
<TextField fx:id="virtualSize" editable="false" styleClass="copyable-label" prefWidth="120"/>
</Field>
</Fieldset>
</Form>
<Label text="Locktime Type: " GridPane.columnIndex="0" GridPane.rowIndex="6" /> <Form GridPane.columnIndex="1" GridPane.rowIndex="4">
<HBox fillHeight="true" GridPane.columnIndex="1" GridPane.rowIndex="6"> <Fieldset text="Fee" inputGrow="SOMETIMES">
<children> <Field text="Amount:">
<ToggleButton fx:id="locktimeBlockTypeField" text="Block" userData="block"> <TextField fx:id="fee" editable="false" styleClass="copyable-label" prefWidth="120"/>
<toggleGroup> </Field>
<ToggleGroup fx:id="locktimeTypeField" /> <Field text="Rate:">
</toggleGroup> <TextField fx:id="feeRateField" editable="false" styleClass="copyable-label" prefWidth="120"/>
</ToggleButton> </Field>
<ToggleButton fx:id="locktimeDateTypeField" text="Date" toggleGroup="$locktimeTypeField" userData="date" /> </Fieldset>
</children> </Form>
</HBox>
<Label text="Locktime: " GridPane.columnIndex="0" GridPane.rowIndex="7" /> <Separator GridPane.columnIndex="0" GridPane.rowIndex="5" GridPane.columnSpan="2" styleClass="form-separator"/>
<Spinner fx:id="locktimeBlockField" prefHeight="40" prefWidth="120" GridPane.columnIndex="1" GridPane.rowIndex="7"/>
<DateTimePicker fx:id="locktimeDateField" visible="false" prefHeight="40" GridPane.columnIndex="1" GridPane.rowIndex="7"/>
<Separator GridPane.columnIndex="0" GridPane.rowIndex="8" GridPane.columnSpan="2" GridPane.rowSpan="1" GridPane.halignment="LEFT" /> <Form GridPane.columnIndex="0" GridPane.rowIndex="6">
<Fieldset text="Blockchain" inputGrow="SOMETIMES">
<Label text="Size: " GridPane.columnIndex="0" GridPane.rowIndex="9" /> <Field text="Status:">
<Label fx:id="sizeField" prefHeight="40" prefWidth="120" GridPane.columnIndex="1" GridPane.rowIndex="9"/> <TextField fx:id="blockStatusField" editable="false" styleClass="copyable-label" prefWidth="120"/>
</Field>
<Label text="Virtual Size: " GridPane.columnIndex="0" GridPane.rowIndex="10" /> <Field text="Block:">
<Label fx:id="virtualSizeField" prefHeight="40" prefWidth="120" GridPane.columnIndex="1" GridPane.rowIndex="10"/> <TextField fx:id="blockField" editable="false" styleClass="copyable-label" prefWidth="120"/>
</Field>
<Label text="Fee: " GridPane.columnIndex="0" GridPane.rowIndex="11" /> </Fieldset>
<Label fx:id="feeField" prefHeight="40" prefWidth="120" GridPane.columnIndex="1" GridPane.rowIndex="11"/> </Form>
</GridPane> </GridPane>

View file

@ -2,5 +2,22 @@
-fx-background-color: transparent ; -fx-background-color: transparent ;
-fx-background-insets: 0px ; -fx-background-insets: 0px ;
-fx-border :none; -fx-border :none;
-fx-padding: 0; -fx-padding: 5 0 5 0;
}
.form .fieldset:horizontal .label-container {
-fx-pref-width: 80px;
-fx-pref-height: 25px;
}
.form .field {
-fx-padding: 5 5;
}
.id {
-fx-font-family: Courier;
}
.form-separator {
-fx-padding: -15 0 0 0;
} }

View file

@ -1,21 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import org.fxmisc.richtext.*?>
<?import javafx.scene.text.TextFlow?> <?import org.fxmisc.flowless.VirtualizedScrollPane?>
<?import org.fxmisc.richtext.CodeArea?> <SplitPane dividerPositions="0.82" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" stylesheets="@transaction.css" VBox.vgrow="ALWAYS" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.craigraw.sparrow.TransactionController">
<SplitPane dividerPositions="0.7" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" VBox.vgrow="ALWAYS" fx:controller="com.craigraw.sparrow.TransactionController" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" stylesheets="@transaction.css">
<items> <items>
<SplitPane dividerPositions="0.2" prefHeight="160.0" prefWidth="200.0"> <SplitPane dividerPositions="0.2" prefHeight="160.0" prefWidth="200.0">
<items> <items>
<TreeView prefHeight="154.0" prefWidth="174.0" fx:id="txtree" /> <TreeView fx:id="txtree" prefHeight="154.0" prefWidth="174.0" />
<Pane fx:id="txpane" /> <Pane fx:id="txpane" />
</items> </items>
</SplitPane> </SplitPane>
<CodeArea fx:id="txhex" wrapText="true" editable="false" /> <VirtualizedScrollPane>
<content>
<CodeArea fx:id="txhex" editable="false" wrapText="true" />
</content>
</VirtualizedScrollPane>
</items> </items>
</SplitPane> </SplitPane>