mapview: saved some space by moving some topics to the head bar

This commit is contained in:
Marc Froehlich
2026-08-11 23:38:47 +02:00
parent 9cccdb73e9
commit 663f724c98
4 changed files with 1169 additions and 92 deletions
+1013
View File
File diff suppressed because it is too large Load Diff
@@ -79,6 +79,8 @@ public final class StationMapBridge {
stationMapView.setOnCallsignRawSelected(this::handleMapCallsignSelection); stationMapView.setOnCallsignRawSelected(this::handleMapCallsignSelection);
stationMapView.setOnTriggerClusterSpot(this::handleExplicitClusterSpot); stationMapView.setOnTriggerClusterSpot(this::handleExplicitClusterSpot);
stationMapView.setOnResetView(this::handleMapReset);
chatController.getLst_chatMemberSortedFilteredList().addListener( chatController.getLst_chatMemberSortedFilteredList().addListener(
(ListChangeListener<ChatMember>) change -> scheduleRefresh() (ListChangeListener<ChatMember>) change -> scheduleRefresh()
); );
@@ -98,6 +100,35 @@ public final class StationMapBridge {
requestImmediateRefresh(); requestImmediateRefresh();
} }
private void handleMapReset() {
Runnable resetAction = () -> {
/*
* Ignore an analysis result that may still arrive for the
* previously selected station.
*/
pathAnalysisGeneration.incrementAndGet();
lastPathAnalysisRequestSignature = "";
/*
* Clear the application's central station selection.
*/
chatController.getScoreService().setSelectedChatMember(null);
/*
* Keep the main station table synchronized with the central selection.
*/
chatMemberTable.getSelectionModel().clearSelection();
requestImmediateRefresh();
};
if (Platform.isFxApplicationThread()) {
resetAction.run();
} else {
Platform.runLater(resetAction);
}
}
public void showWindow() { public void showWindow() {
stationMapView.showWindow(); stationMapView.showWindow();
requestImmediateRefresh(); requestImmediateRefresh();
@@ -87,14 +87,15 @@ public final class StationMapView {
private final Button pathAnalysisVisibilityButton = new Button(); private final Button pathAnalysisVisibilityButton = new Button();
private final Tooltip pathAnalysisVisibilityTooltip = new Tooltip(); private final Tooltip pathAnalysisVisibilityTooltip = new Tooltip();
private final Button resetViewButton = new Button("Reset view");
private final Tooltip statusTooltip = new Tooltip();
private Runnable onResetView;
private double lastDetailDividerPosition = 0.65;
private final Label detailCallsignValue = new Label("-");
private final Label detailLocatorValue = new Label("-");
private final Label detailQrbValue = new Label("-");
private final Label detailQtfValue = new Label("-");
private final Label detailBandsValue = new Label("-");
private final TextArea detailFrequenciesArea = new TextArea();
private final Label detailAirplanesValue = new Label("-");
private final Button triggerClusterSpotButton = new Button("Trigger cluster spot"); private final Button triggerClusterSpotButton = new Button("Trigger cluster spot");
private final Label detailPathFromLocatorValue = new Label("-"); private final Label detailPathFromLocatorValue = new Label("-");
@@ -210,6 +211,11 @@ public final class StationMapView {
this.onTriggerClusterSpot = onTriggerClusterSpot; this.onTriggerClusterSpot = onTriggerClusterSpot;
} }
public void setOnResetView(Runnable onResetView) {
this.onResetView = onResetView;
}
public void showWindow() { public void showWindow() {
applyThemeFromPreferences(); applyThemeFromPreferences();
@@ -282,10 +288,6 @@ public final class StationMapView {
stage.setTitle("Station Map"); stage.setTitle("Station Map");
detailFrequenciesArea.setEditable(false);
detailFrequenciesArea.setWrapText(true);
detailFrequenciesArea.setPrefRowCount(4);
detailPathEndpointsValue.setWrapText(true); detailPathEndpointsValue.setWrapText(true);
detailPathEndpointsValue.setMaxWidth(Double.MAX_VALUE); detailPathEndpointsValue.setMaxWidth(Double.MAX_VALUE);
@@ -299,12 +301,23 @@ public final class StationMapView {
detailPathMechanismsValue.setMaxWidth(Double.MAX_VALUE); detailPathMechanismsValue.setMaxWidth(Double.MAX_VALUE);
triggerClusterSpotButton.setDisable(true); triggerClusterSpotButton.setDisable(true);
triggerClusterSpotButton.setVisible(false);
triggerClusterSpotButton.setManaged(false);
triggerClusterSpotButton.setMinWidth(Region.USE_PREF_SIZE);
triggerClusterSpotButton.setOnAction(event -> { triggerClusterSpotButton.setOnAction(event -> {
if (detailCallsignRaw != null && onTriggerClusterSpot != null) { if (detailCallsignRaw != null && onTriggerClusterSpot != null) {
onTriggerClusterSpot.accept(detailCallsignRaw); onTriggerClusterSpot.accept(detailCallsignRaw);
} }
}); });
resetViewButton.setMinWidth(Region.USE_PREF_SIZE);
resetViewButton.setOnAction(event -> {
if (onResetView != null) {
onResetView.run();
}
});
pathAnalysisVisibilityButton.setMinWidth(Region.USE_PREF_SIZE); pathAnalysisVisibilityButton.setMinWidth(Region.USE_PREF_SIZE);
pathAnalysisVisibilityButton.setTooltip(pathAnalysisVisibilityTooltip); pathAnalysisVisibilityButton.setTooltip(pathAnalysisVisibilityTooltip);
pathAnalysisVisibilityButton.setOnAction(event -> pathAnalysisVisibilityButton.setOnAction(event ->
@@ -377,7 +390,7 @@ public final class StationMapView {
); );
pathAnalysisSection = createPathAnalysisSection(); pathAnalysisSection = createPathAnalysisSection();
detailPane = new VBox(10, createSelectedStationSection(), pathAnalysisSection); detailPane = new VBox(10, pathAnalysisSection);
detailPane.setPadding(new Insets(10)); detailPane.setPadding(new Insets(10));
@@ -489,20 +502,25 @@ public final class StationMapView {
* must always have an obvious way to restore a previously hidden analysis. * must always have an obvious way to restore a previously hidden analysis.
*/ */
private HBox createMapHeader() { private HBox createMapHeader() {
// The status may be shortened before the show/hide control is ever clipped.
statusLabel.setMinWidth(0); statusLabel.setMinWidth(0);
statusLabel.setMaxWidth(Double.MAX_VALUE); statusLabel.setMaxWidth(Double.MAX_VALUE);
statusLabel.setTextOverrun(OverrunStyle.ELLIPSIS); statusLabel.setTextOverrun(OverrunStyle.ELLIPSIS);
statusLabel.setTooltip(statusTooltip);
HBox header = new HBox( HBox header = new HBox(
10, 10,
statusLabel, statusLabel,
triggerClusterSpotButton,
resetViewButton,
pathAnalysisHiddenHintLabel, pathAnalysisHiddenHintLabel,
pathAnalysisVisibilityButton pathAnalysisVisibilityButton
); );
header.setAlignment(Pos.CENTER_LEFT); header.setAlignment(Pos.CENTER_LEFT);
header.setPadding(new Insets(8)); header.setPadding(new Insets(8));
HBox.setHgrow(statusLabel, Priority.ALWAYS); HBox.setHgrow(statusLabel, Priority.ALWAYS);
return header; return header;
} }
@@ -523,6 +541,7 @@ public final class StationMapView {
pathAnalysisSection.setVisible(visible); pathAnalysisSection.setVisible(visible);
pathAnalysisSection.setManaged(visible); pathAnalysisSection.setManaged(visible);
updateDetailPanePresence(visible);
pathAnalysisHiddenHintLabel.setVisible(!visible); pathAnalysisHiddenHintLabel.setVisible(!visible);
pathAnalysisHiddenHintLabel.setManaged(!visible); pathAnalysisHiddenHintLabel.setManaged(!visible);
@@ -567,45 +586,6 @@ public final class StationMapView {
: MINIMUM_HEIGHT_WITHOUT_PATH_ANALYSIS; : MINIMUM_HEIGHT_WITHOUT_PATH_ANALYSIS;
} }
private VBox createSelectedStationSection() {
GridPane detailGrid = new GridPane();
detailGrid.setHgap(8);
detailGrid.setVgap(6);
configureCompactGrid(detailGrid);
int row = 0;
detailGrid.add(new Label("Station:"), 0, row);
detailGrid.add(detailCallsignValue, 1, row++);
detailGrid.add(new Label("Locator:"), 0, row);
detailGrid.add(detailLocatorValue, 1, row++);
detailGrid.add(new Label("Path:"), 0, row);
Label compactPathValue = new Label();
compactPathValue.textProperty().bind(
detailQrbValue.textProperty()
.concat(" / ")
.concat(detailQtfValue.textProperty())
);
detailGrid.add(compactPathValue, 1, row++);
detailGrid.add(new Label("Bands:"), 0, row);
detailGrid.add(detailBandsValue, 1, row++);
// Frequencies are useful, but they consume vertical space. Keep them compact.
detailFrequenciesArea.setPrefRowCount(2);
detailGrid.add(new Label("QRG:"), 0, row);
detailGrid.add(detailFrequenciesArea, 1, row++);
return new VBox(8,
new Label("Selected station"),
new Separator(Orientation.HORIZONTAL),
detailGrid,
triggerClusterSpotButton
);
}
/** /**
* ensures that the labels remains visible * ensures that the labels remains visible
@@ -950,58 +930,107 @@ public final class StationMapView {
private void updateStatusLabel() { private void updateStatusLabel() {
StringBuilder text = new StringBuilder(); StringBuilder text = new StringBuilder();
text.append("Showing ").append(lastSnapshots.size()).append(" visible stations");
text.append("Showing ")
.append(lastSnapshots.size())
.append(" visible stations");
if (filteredViewActive) { if (filteredViewActive) {
text.append(" | filtered view active"); text.append(" | filtered view active");
} }
statusLabel.setText(text.toString()); MapCallsignRawSnapshot selectedSnapshot = lastSelectedSnapshot;
if (selectedSnapshot != null) {
text.append(" | Selected: ")
.append(selectedSnapshot.displayCallSign());
if (!selectedSnapshot.locator6().isBlank()) {
text.append(" | ")
.append(selectedSnapshot.locator6());
}
text.append(" | ")
.append(String.format(
Locale.US,
"%.0f km / %.0f°",
selectedSnapshot.qrbKm(),
selectedSnapshot.qtfDeg()
));
String bandText = selectedSnapshot.bandSummary().isBlank()
? "-"
: selectedSnapshot.bandSummary();
if (selectedSnapshot.offersSelectedBand()) {
bandText += " B+";
}
text.append(" | Bands: ")
.append(bandText);
String frequencies = selectedSnapshot.detailFrequencyText();
if (frequencies != null && !frequencies.isBlank()) {
frequencies = frequencies
.replace('\n', ' ')
.replace('\r', ' ')
.replaceAll("\\s+", " ")
.trim();
text.append(" | QRG: ")
.append(frequencies);
}
}
String statusText = text.toString();
statusLabel.setText(statusText);
statusTooltip.setText(statusText);
} }
private void updateDetailPanel(MapCallsignRawSnapshot selectedSnapshot) { private void updateDetailPanel(MapCallsignRawSnapshot selectedSnapshot) {
if (selectedSnapshot == null) { if (selectedSnapshot == null) {
clearSelectedStationPanel(); detailCallsignRaw = null;
triggerClusterSpotButton.setDisable(true);
triggerClusterSpotButton.setVisible(false);
triggerClusterSpotButton.setManaged(false);
clearPathAnalysisPanel(); clearPathAnalysisPanel();
return; return;
} }
updateSelectedStationPanel(selectedSnapshot); detailCallsignRaw = selectedSnapshot.callSignRaw();
triggerClusterSpotButton.setDisable(false);
triggerClusterSpotButton.setVisible(true);
triggerClusterSpotButton.setManaged(true);
if (selectedSnapshot == null) {
updatePathAnalysisPanel(PathAnalysisResult.waitingForSelection(homeLocator6));
} else {
updatePathAnalysisPanel(lastPathAnalysisResult); updatePathAnalysisPanel(lastPathAnalysisResult);
} }
private void updateDetailPanePresence(boolean visible) {
if (mainSplitPane == null || detailScrollPane == null) {
return;
} }
private void clearSelectedStationPanel() { if (visible) {
detailCallsignRaw = null; if (!mainSplitPane.getItems().contains(detailScrollPane)) {
detailCallsignValue.setText("-"); mainSplitPane.getItems().add(detailScrollPane);
detailLocatorValue.setText("-");
detailQrbValue.setText("-"); Platform.runLater(() ->
detailQtfValue.setText("-"); mainSplitPane.setDividerPositions(lastDetailDividerPosition)
detailBandsValue.setText("-"); );
detailFrequenciesArea.setText("-"); }
detailAirplanesValue.setText("-"); } else {
triggerClusterSpotButton.setDisable(true); if (!mainSplitPane.getDividers().isEmpty()) {
lastDetailDividerPosition =
mainSplitPane.getDividers().get(0).getPosition();
} }
private void updateSelectedStationPanel(MapCallsignRawSnapshot selectedSnapshot) { mainSplitPane.getItems().remove(detailScrollPane);
detailCallsignRaw = selectedSnapshot.callSignRaw();
detailCallsignValue.setText(selectedSnapshot.displayCallSign());
detailLocatorValue.setText(selectedSnapshot.locator6());
detailQrbValue.setText(String.format(Locale.US, "%.0f km", selectedSnapshot.qrbKm()));
detailQtfValue.setText(String.format(Locale.US, "%.0f°", selectedSnapshot.qtfDeg()));
String bandText = selectedSnapshot.bandSummary().isBlank() ? "-" : selectedSnapshot.bandSummary();
if (selectedSnapshot.offersSelectedBand()) {
bandText += " B+";
} }
detailBandsValue.setText(bandText);
detailFrequenciesArea.setText(selectedSnapshot.detailFrequencyText());
detailAirplanesValue.setText(String.valueOf(selectedSnapshot.reachableAirplanes()));
triggerClusterSpotButton.setDisable(false);
} }
private void clearPathAnalysisPanel() { private void clearPathAnalysisPanel() {
@@ -1331,13 +1360,13 @@ public final class StationMapView {
mainSplitPane.setStyle("-fx-background-color: #2b3035;"); mainSplitPane.setStyle("-fx-background-color: #2b3035;");
detailPane.setStyle("-fx-background-color: #31373c; -fx-border-color: #4c565c; -fx-border-width: 0 0 0 1;"); detailPane.setStyle("-fx-background-color: #31373c; -fx-border-color: #4c565c; -fx-border-width: 0 0 0 1;");
statusLabel.setStyle("-fx-background-color: #373e43; -fx-text-fill: lightgray; -fx-padding: 8 10 8 10; -fx-background-radius: 4;"); statusLabel.setStyle("-fx-background-color: #373e43; -fx-text-fill: lightgray; -fx-padding: 8 10 8 10; -fx-background-radius: 4;");
detailFrequenciesArea.setStyle("-fx-control-inner-background: #444b50; -fx-text-fill: lightgray;"); // detailFrequenciesArea.setStyle("-fx-control-inner-background: #444b50; -fx-text-fill: lightgray;");
} else { } else {
rootPane.setStyle("-fx-background-color: #f2f2f2;"); rootPane.setStyle("-fx-background-color: #f2f2f2;");
mainSplitPane.setStyle("-fx-background-color: #f2f2f2;"); mainSplitPane.setStyle("-fx-background-color: #f2f2f2;");
detailPane.setStyle("-fx-background-color: #f7f7f7; -fx-border-color: #d0d0d0; -fx-border-width: 0 0 0 1;"); detailPane.setStyle("-fx-background-color: #f7f7f7; -fx-border-color: #d0d0d0; -fx-border-width: 0 0 0 1;");
statusLabel.setStyle("-fx-background-color: #f7f7f7; -fx-text-fill: #333333; -fx-padding: 8 10 8 10; -fx-background-radius: 4;"); statusLabel.setStyle("-fx-background-color: #f7f7f7; -fx-text-fill: #333333; -fx-padding: 8 10 8 10; -fx-background-radius: 4;");
detailFrequenciesArea.setStyle(""); // detailFrequenciesArea.setStyle("");
} }
} }
+4
View File
@@ -2383,3 +2383,7 @@ OZ6TY;Henning;JO55XE;StringProperty [value: 144.196]; wkd true; wkd144 true; wkd
DF7KF;Dithmar;JO30FK;StringProperty [value: null]; wkd true; wkd144 true; wkd432false; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz DF7KF;Dithmar;JO30FK;StringProperty [value: null]; wkd true; wkd144 true; wkd432false; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
DH1NFJ;Jochen;JO50QL;StringProperty [value: null]; wkd true; wkd144 false; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 3: Microwave DH1NFJ;Jochen;JO50QL;StringProperty [value: null]; wkd true; wkd144 false; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 3: Microwave
PA2RU;René;JO32LT;StringProperty [value: null]; wkd true; wkd144 false; wkd432false; wkd1240true; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz PA2RU;René;JO32LT;StringProperty [value: null]; wkd true; wkd144 false; wkd432false; wkd1240true; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
SM6VTZ;Chris .135;JO58UJ;StringProperty [value: 144.135]; wkd true; wkd144 false; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
SM7EYW;Torleif 432,205;JO65NK;StringProperty [value: 144.205]; wkd true; wkd144 false; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
DJ8MS;Tor_70cm;JO54UC;StringProperty [value: null]; wkd true; wkd144 false; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz
DK0MM;Jens/Alex;JN49IU;StringProperty [value: 432.305]; wkd true; wkd144 false; wkd432true; wkd1240false; wkd2300false; wkd3400false; wkd5600false; wkd10Gfalse ; 2: 144/432 MHz