95: EMC: Display Perps positions in a tree table using dummy data

This commit is contained in:
2026-10-19 12:55:34 +02:00
parent cc7003ac94
commit 2dce841cf4
9 changed files with 297 additions and 1 deletions
@@ -161,7 +161,7 @@ public final class EvelynMissionControlImpl implements EvelynMissionControl, Nen
TabPane tabs = new TabPane(
createOverviewTab(color, statusIndexChart),
createMissionControlTab("Portfolio", color),
createMissionControlTab("Perps", color),
PerpsTab.create(color),
createMissionControlTab("Spot", color),
createMissionControlTab("Liquidity Pools", color),
createMissionControlTab("Alarms", color),
@@ -0,0 +1,129 @@
package com.r35157.evelyn.emc.impl.ref;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableRow;
import javafx.scene.control.TreeTableView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Locale;
final class PerpsTab {
static Tab create(String environmentColor) {
NumberFormat usdFormat = NumberFormat.getCurrencyInstance(Locale.US);
TreeTableColumn<PositionRow, String> position = new TreeTableColumn<>("Position");
position.setCellValueFactory(cell -> new ReadOnlyStringWrapper(cell.getValue().getValue().label()));
position.setPrefWidth(260);
position.setMinWidth(180);
position.setSortable(false);
TreeTableColumn<PositionRow, String> direction = new TreeTableColumn<>("Direction");
direction.setCellValueFactory(cell -> {
Direction value = cell.getValue().getValue().direction();
return new ReadOnlyStringWrapper(value == null ? "" : value.label);
});
direction.setPrefWidth(90);
direction.setMinWidth(80);
direction.setSortable(false);
TreeTableColumn<PositionRow, String> size = new TreeTableColumn<>("Position size, USD");
size.setCellValueFactory(cell -> {
ΩAmountΩ value = cell.getValue().getValue().sizeUsd();
return new ReadOnlyStringWrapper(value == null ? "" : usdFormat.format(value));
});
size.setPrefWidth(170);
size.setMinWidth(155);
size.setStyle("-fx-alignment: CENTER-RIGHT;");
size.setSortable(false);
TreeTableView<PositionRow> table = new TreeTableView<>(createSampleRoot());
table.setShowRoot(false);
table.setTreeColumn(position);
table.getColumns().add(position);
table.getColumns().add(direction);
table.getColumns().add(size);
table.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN);
table.setRowFactory(view -> new TreeTableRow<>() {
@Override
protected void updateItem(PositionRow item, boolean empty) {
super.updateItem(item, empty);
setStyle(empty || item == null || item.direction() == null
? ""
: item.direction().rowStyle);
}
});
Label sampleNotice = new Label(
"Sample data only — not live positions. Phoenix rows are illustrative; no Phoenix integration exists."
);
sampleNotice.setWrapText(true);
sampleNotice.setMinHeight(VBox.USE_PREF_SIZE);
VBox content = new VBox(8, sampleNotice, table);
content.setPadding(new Insets(10));
content.setStyle("-fx-background-color: " + environmentColor + ";");
VBox.setVgrow(table, Priority.ALWAYS);
Tab tab = new Tab("Perps", content);
tab.setStyle("-fx-background-color: " + environmentColor + ";");
return tab;
}
private static TreeItem<PositionRow> createSampleRoot() {
return group("Sample positions",
group("Sample wallet A",
group("Jupiter",
position("SOL-PERP", Direction.LONG, "12500.00"),
position("BTC-PERP", Direction.SHORT, "8250.50")),
group("Phoenix",
position("SOL-PERP", Direction.SHORT, "3200.75"),
position("ETH-PERP", Direction.LONG, "5400.00"))),
group("Sample wallet B",
group("Jupiter",
position("ETH-PERP", Direction.LONG, "1875.25"),
position("SOL-PERP", Direction.SHORT, "950.00")),
group("Phoenix",
position("BTC-PERP", Direction.LONG, "21000.00"),
position("SOL-PERP", Direction.SHORT, "640.50"))));
}
@SafeVarargs
private static TreeItem<PositionRow> group(String label, TreeItem<PositionRow>... children) {
TreeItem<PositionRow> item = new TreeItem<>(new PositionRow(label, null, null));
item.getChildren().addAll(children);
item.setExpanded(true);
return item;
}
private static TreeItem<PositionRow> position(String label, Direction direction, String sizeUsd) {
return new TreeItem<>(new PositionRow(label, direction, new BigDecimal(sizeUsd)));
}
private record PositionRow(String label, Direction direction, ΩAmountΩ sizeUsd) {
}
private enum Direction {
LONG("Long", "#e6f4ea"),
SHORT("Short", "#fce8e6");
Direction(String label, String background) {
this.label = label;
this.rowStyle = "-fx-control-inner-background: " + background + ";"
+ "-fx-control-inner-background-alt: " + background + ";";
}
private final String label;
private final String rowStyle;
}
private PerpsTab() {
}
}