mirror of
https://github.com/praktimarc/kst4contest.git
synced 2026-09-15 21:55:32 +02:00
Add optional station map clustering toggle (solves #79) and added documentation
This commit is contained in:
@@ -55,7 +55,7 @@ public class ChatPreferences {
|
||||
* Reading must stay backwards compatible: missing/unknown tags should fall back to defaults.
|
||||
*/
|
||||
// private static final int CONFIG_VERSION = 2;
|
||||
public static final int CONFIG_VERSION = 6;
|
||||
public static final int CONFIG_VERSION = 7;
|
||||
|
||||
// Prefer writing tag names that mirror variable names (human readable). Keep legacy tags for compatibility.
|
||||
private static final String TAG_CONFIG_VERSION = "configVersion";
|
||||
@@ -346,6 +346,7 @@ public class ChatPreferences {
|
||||
private double[] GUIstationMapStageSceneSizeHW = new double[] { 1000, 800 };
|
||||
private double[] GUIstationMapStagePositionXY = new double[] { Double.NaN, Double.NaN };
|
||||
private boolean GUIstationMapPathAnalysisVisible = true;
|
||||
private boolean GUIstationMapClusteringEnabled = true;
|
||||
private final Map<String, Double> tableColumnWidths = new LinkedHashMap<>();
|
||||
|
||||
private static final String TAG_TABLE_COLUMN_WIDTH = "tableColumnWidth";
|
||||
@@ -655,6 +656,14 @@ public class ChatPreferences {
|
||||
this.GUIstationMapPathAnalysisVisible = GUIstationMapPathAnalysisVisible;
|
||||
}
|
||||
|
||||
public boolean isGUIstationMapClusteringEnabled() {
|
||||
return GUIstationMapClusteringEnabled;
|
||||
}
|
||||
|
||||
public void setGUIstationMapClusteringEnabled(boolean GUIstationMapClusteringEnabled) {
|
||||
this.GUIstationMapClusteringEnabled = GUIstationMapClusteringEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stored width for one stable table/leaf-column identity.
|
||||
*
|
||||
@@ -2120,6 +2129,12 @@ public class ChatPreferences {
|
||||
);
|
||||
guiOptions.appendChild(GUIstationMapPathAnalysisVisible);
|
||||
|
||||
Element GUIstationMapClusteringEnabled = doc.createElement("GUIstationMapClusteringEnabled");
|
||||
GUIstationMapClusteringEnabled.setTextContent(
|
||||
String.valueOf(this.isGUIstationMapClusteringEnabled())
|
||||
);
|
||||
guiOptions.appendChild(GUIstationMapClusteringEnabled);
|
||||
|
||||
appendTableColumnWidths(doc, guiOptions);
|
||||
|
||||
/****************************************************************************************
|
||||
@@ -2204,6 +2219,8 @@ public class ChatPreferences {
|
||||
getGUIstationMapStageSceneSizeHW()[0] + ";" + getGUIstationMapStageSceneSizeHW()[1]);
|
||||
upsertDirectChildText(document, guiOptions, "GUIstationMapStagePositionXY",
|
||||
getGUIstationMapStagePositionXY()[0] + ";" + getGUIstationMapStagePositionXY()[1]);
|
||||
upsertDirectChildText(document, guiOptions, "GUIstationMapClusteringEnabled",
|
||||
String.valueOf(isGUIstationMapClusteringEnabled()));
|
||||
}
|
||||
|
||||
private void appendTableColumnWidths(Document document, Element guiOptions) {
|
||||
@@ -2956,6 +2973,7 @@ public class ChatPreferences {
|
||||
* case read GUI options
|
||||
*
|
||||
***********************************************/
|
||||
this.setGUIstationMapClusteringEnabled(true);
|
||||
list = doc.getElementsByTagName("guiOptions");
|
||||
if (list.getLength() != 0) {
|
||||
|
||||
@@ -2994,6 +3012,17 @@ public class ChatPreferences {
|
||||
"GUIstationMapPathAnalysisVisible"
|
||||
));
|
||||
|
||||
/*
|
||||
* Files written before config version 7 do not contain this value.
|
||||
* Missing or malformed values keep clustering enabled so existing
|
||||
* installations retain the established map behaviour.
|
||||
*/
|
||||
this.setGUIstationMapClusteringEnabled(getBooleanOrDefault(
|
||||
element,
|
||||
true,
|
||||
"GUIstationMapClusteringEnabled"
|
||||
));
|
||||
|
||||
// Splitpane divider positions
|
||||
String s1 = getText(element, null, "GUIselectedCallSignSplitPane_dividerposition");
|
||||
if (s1 != null) {
|
||||
@@ -3344,6 +3373,20 @@ public class ChatPreferences {
|
||||
return "true".equalsIgnoreCase(v) || "1".equals(v) || "yes".equalsIgnoreCase(v);
|
||||
}
|
||||
|
||||
private static boolean getBooleanOrDefault(Element parent, boolean defaultValue, String... tagNames) {
|
||||
String value = getText(parent, null, tagNames);
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
if ("true".equalsIgnoreCase(value) || "1".equals(value) || "yes".equalsIgnoreCase(value)) {
|
||||
return true;
|
||||
}
|
||||
if ("false".equalsIgnoreCase(value) || "0".equals(value) || "no".equalsIgnoreCase(value)) {
|
||||
return false;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static int getInt(Element parent, int defaultValue, String... tagNames) {
|
||||
String v = getText(parent, null, tagNames);
|
||||
if (v == null) {
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.nio.charset.StandardCharsets;
|
||||
* - grid / beam / connection use non-interactive panes
|
||||
* - JavaScript errors are forwarded to Java through javaMapBridge
|
||||
* - setTheme(light|dark) aligns the map with the JavaFX application theme
|
||||
* - setStationClusteringEnabled(boolean) re-renders the existing station data
|
||||
*
|
||||
* Important:
|
||||
* This version intentionally uses integer Leaflet zoom levels again.
|
||||
@@ -356,6 +357,7 @@ public final class MapHtmlResources {
|
||||
*/
|
||||
let stationData = [];
|
||||
let stationsByCallsignRaw = {};
|
||||
let stationClusteringEnabled = true;
|
||||
|
||||
let clustersById = {};
|
||||
let clusterSequence = 0;
|
||||
@@ -810,13 +812,19 @@ public final class MapHtmlResources {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Number(map.getZoom()) >= KST_CLUSTER_DISABLE_ZOOM) {
|
||||
if (!stationClusteringEnabled
|
||||
|| Number(map.getZoom()) >= KST_CLUSTER_DISABLE_ZOOM) {
|
||||
renderAllStationsIndividually();
|
||||
} else {
|
||||
renderClusteredStations();
|
||||
}
|
||||
}
|
||||
|
||||
function setStationClusteringEnabled(enabled) {
|
||||
stationClusteringEnabled = Boolean(enabled);
|
||||
renderStationMarkers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Zooms into a cluster.
|
||||
*
|
||||
@@ -1271,6 +1279,7 @@ public final class MapHtmlResources {
|
||||
getViewportState: getViewportState,
|
||||
setHome: setHome,
|
||||
setStations: setStations,
|
||||
setStationClusteringEnabled: setStationClusteringEnabled,
|
||||
setBeam: setBeam,
|
||||
setConnection: setConnection,
|
||||
setProfileHoverPoint: setProfileHoverPoint,
|
||||
@@ -1284,4 +1293,4 @@ public final class MapHtmlResources {
|
||||
</html>
|
||||
""".replace("__TILE_PROXY_PORT__", String.valueOf(tileProxyPort));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,9 @@ public final class StationMapView {
|
||||
|
||||
private final Button resetViewButton = new Button("Reset view");
|
||||
private final Tooltip statusTooltip = new Tooltip();
|
||||
private final CheckBox stationClusteringCheckBox = new CheckBox("Group nearby stations");
|
||||
private final Tooltip stationClusteringTooltip = new Tooltip(
|
||||
"Group nearby stations into clusters at lower zoom levels.");
|
||||
|
||||
private Runnable onResetView;
|
||||
|
||||
@@ -333,6 +336,21 @@ public final class StationMapView {
|
||||
}
|
||||
});
|
||||
|
||||
stationClusteringCheckBox.setMinWidth(Region.USE_PREF_SIZE);
|
||||
stationClusteringCheckBox.setTooltip(stationClusteringTooltip);
|
||||
stationClusteringCheckBox.setAccessibleText("Group nearby stations");
|
||||
stationClusteringCheckBox.setAccessibleHelp(stationClusteringTooltip.getText());
|
||||
stationClusteringCheckBox.setSelected(chatPreferences.isGUIstationMapClusteringEnabled());
|
||||
stationClusteringCheckBox.selectedProperty().addListener((obs, oldValue, newValue) -> {
|
||||
boolean enabled = newValue;
|
||||
chatPreferences.setGUIstationMapClusteringEnabled(enabled);
|
||||
if (mapReady) {
|
||||
executeMapScriptSafely(
|
||||
"window.kstMapApi.setStationClusteringEnabled(" + enabled + ");");
|
||||
}
|
||||
layoutSaveRequester.run();
|
||||
});
|
||||
|
||||
pathAnalysisVisibilityButton.setMinWidth(Region.USE_PREF_SIZE);
|
||||
pathAnalysisVisibilityButton.setTooltip(pathAnalysisVisibilityTooltip);
|
||||
pathAnalysisVisibilityButton.setOnAction(event ->
|
||||
@@ -535,6 +553,7 @@ public final class StationMapView {
|
||||
statusLabel,
|
||||
triggerClusterSpotButton,
|
||||
resetViewButton,
|
||||
stationClusteringCheckBox,
|
||||
pathAnalysisHiddenHintLabel,
|
||||
pathAnalysisVisibilityButton
|
||||
);
|
||||
@@ -808,6 +827,9 @@ public final class StationMapView {
|
||||
window.setMember("javaMapBridge", javaMapBridge);
|
||||
|
||||
executeMapScriptSafely("window.kstMapApi.init();");
|
||||
executeMapScriptSafely(
|
||||
"window.kstMapApi.setStationClusteringEnabled("
|
||||
+ chatPreferences.isGUIstationMapClusteringEnabled() + ");");
|
||||
|
||||
mapReady = true;
|
||||
applyMapThemeToWebView(chatPreferences.isGUI_darkModeActive());
|
||||
|
||||
Reference in New Issue
Block a user