From 75bd5b29567622af0ddf3036f2952f0dcfc2b67d Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Sat, 11 Jan 2025 16:29:49 +0000 Subject: [PATCH 1/8] renderer2d/WorldRenderPainter: Adding possibility to delete the visible area ties cache. --- .../neptus/renderer2d/WorldRenderPainter.java | 193 ++++++++++++++---- .../pt/lsts/neptus/renderer2d/tiles/Tile.java | 99 +++++++-- 2 files changed, 231 insertions(+), 61 deletions(-) diff --git a/src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java b/src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java index d98db8a5b5..1741b8874f 100644 --- a/src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java +++ b/src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java @@ -619,12 +619,24 @@ public static void clearMemCache() { * @param mapStyle */ public static void clearMemCache(String mapStyle) { + clearMemCache(mapStyle, null); + } + + public static void clearMemCache(String mapStyle, List quadKeys) { Map map = tileHolderList.get(mapStyle); if (map != null) { Tile[] lst = map.values().toArray(new Tile[0]); - map.clear(); + if (quadKeys == null || quadKeys.isEmpty()) + map.clear(); for (Tile tile : lst) { - tile.dispose(); + if (quadKeys == null || quadKeys.isEmpty()) { + tile.dispose(); + } else { + if (quadKeys.contains(tile.getId())) { + map.remove(tile.getId()); + tile.dispose(); + } + } } } } @@ -634,12 +646,7 @@ public static void clearMemCache(String mapStyle) { */ public static void clearDiskCache() { for (Class clazz : tileClassList.values()) { - try { - clazz.getMethod("clearDiskCache").invoke(null); - } - catch (Exception e) { - e.printStackTrace(); - } + clearDiskCache("all", clazz, null); } } @@ -648,12 +655,58 @@ public static void clearDiskCache() { */ public static void clearDiskCache(String mapStyle) { Class clazz = tileClassList.get(mapStyle); - if (clazz != null) + clearDiskCache(mapStyle, clazz, null); + } + + public static void clearDiskCache(String mapStyle, List quadKeys) { + Class clazz = tileClassList.get(mapStyle); + clearDiskCache(mapStyle, clazz, quadKeys); + } + + private static void clearDiskCache(String mapStyle, Class clazz, List quadKeys) { + if (clazz == null) + return; + + String mapStyleBaseFolderName = clazz.getSimpleName(); + try { + clazz.getMethod("clearDiskCache", List.class).invoke(null, quadKeys); + } + catch (NoSuchMethodException e) { try { - clazz.getMethod("clearDiskCache").invoke(null); + if (quadKeys == null) { + clazz.getMethod("clearDiskCache").invoke(null); + } + else { + clazz.getMethod("clearDiskCache", String[].class).invoke(null, (Object) quadKeys.toArray(new String[0])); + } + } + catch (NoSuchMethodException ex) { + try { + if (quadKeys == null || quadKeys.isEmpty()) { + clazz.getMethod("clearDiskCache").invoke(null); + } else { + Tile.clearDiskCache(mapStyleBaseFolderName, quadKeys); + } + } + catch (NoSuchMethodException ex2) { + try { + // Last resort + Tile.clearDiskCache(mapStyleBaseFolderName, quadKeys); + } + catch (Exception e1) { + NeptusLog.pub().error("Error clearing disk cache for {} : {}", mapStyle, e1.getMessage()); + } + } + catch (Exception e1) { + NeptusLog.pub().error("Error clearing disk cache for {} : {}", mapStyle, e1.getMessage()); + } } + catch (Exception e1) { + NeptusLog.pub().error("Error clearing disk cache for {} : {}", mapStyle, e1.getMessage()); + } + } catch (Exception e) { - e.printStackTrace(); + NeptusLog.pub().error("Error clearing disk cache for {} : {}", mapStyle, e.getMessage()); } } @@ -1042,7 +1095,7 @@ public static double[] getRendererWorldLatLonDegsMinMax(StateRenderer2D renderer } /** - * Return the tileXMin, tileYMin, tileXMax, tileYMax array for the current + * Return the tileXMin, tileYMin, tileXMax, tileYMax array for the current * renderer level of detail. * @param renderer * @return tileXMin, tileYMin, tileXMax, tileYMax array @@ -1063,36 +1116,52 @@ public static int[] getTileMinMaxForRenderer(StateRenderer2D renderer) { return new int[] { tileXMin, tileYMin, tileXMax, tileYMax }; } - private void fetchAllTilesForRendererVisibleArea(StateRenderer2D renderer, String mapStyle) { + private static List fetchQuadKeysFor(StateRenderer2D renderer, String mapStyle, int levelOfDetailIncrement) { int[] tmmr = getTileMinMaxForRenderer(renderer); int tileXMin = tmmr[0]; int tileXMax = tmmr[2]; int tileYMin = tmmr[1]; int tileYMax = tmmr[3]; int levelOfDetail = renderer.getLevelOfDetail(); - int maxLevelOfDetail = Math.min(getMaxLevelOfDetail(mapStyle), levelOfDetail + 2); - NeptusLog.pub().info("<###>tileXMin=" + tileXMin + ", tileYMin=" + tileYMin + ", tileXMax=" + tileXMax + ", tileYMax=" + tileYMax); - Vector bagList = new Vector(); - for (int x = tileXMin; x <= tileXMax; x++) { - for (int y = tileYMin; y <= tileYMax; y++) { - String quadKey = MapTileUtil.tileXYToQuadKey(x, y, levelOfDetail); - bagList.add(quadKey); - // NeptusLog.pub().info("<###> "+maxLevelOfDetail + " >= \t" + levelOfDetail + " :: \t" + quadKey); - if (levelOfDetail >= maxLevelOfDetail) - continue; - for (int sLoD = levelOfDetail + 1; sLoD <= maxLevelOfDetail; sLoD++) { - produceQuadKeysWorker(quadKey, maxLevelOfDetail, bagList); - } - } - } - NeptusLog.pub().info("<###> "+bagList.size() + " tiles"); - Collections.sort(bagList, new Comparator() { - @Override - public int compare(String o1, String o2) { - return o1.length() - o2.length(); - } - }); - // GuiUtils.printList(bagList); + return fetchQuadKeysFor(tileXMin, tileXMax, tileYMin, tileYMax, mapStyle, levelOfDetail, levelOfDetailIncrement); + } + + private static List fetchQuadKeysFor(int tileXMin, int tileXMax, int tileYMin, int tileYMax, String mapStyle, + int levelOfDetail, int levelOfDetailIncrement) { + int maxLevelOfDetail = Math.min(getMaxLevelOfDetail(mapStyle), levelOfDetail + Math.max(0, levelOfDetailIncrement)); + NeptusLog.pub().info("<###>tileXMin=" + tileXMin + ", tileYMin=" + tileYMin + ", tileXMax=" + tileXMax + ", tileYMax=" + tileYMax); + List bagList = new ArrayList<>(); + for (int x = tileXMin; x <= tileXMax; x++) { + for (int y = tileYMin; y <= tileYMax; y++) { + String quadKey = MapTileUtil.tileXYToQuadKey(x, y, levelOfDetail); + bagList.add(quadKey); + // NeptusLog.pub().info("<###> "+maxLevelOfDetail + " >= \t" + levelOfDetail + " :: \t" + quadKey); + if (levelOfDetail >= maxLevelOfDetail) + continue; + for (int sLoD = levelOfDetail + 1; sLoD <= maxLevelOfDetail; sLoD++) { + produceQuadKeysWorker(quadKey, maxLevelOfDetail, bagList); + } + } + } + NeptusLog.pub().info("<###> " + bagList.size() + " tiles"); + Collections.sort(bagList, new Comparator() { + @Override + public int compare(String o1, String o2) { + return o1.length() - o2.length(); + } + }); + // GuiUtils.printList(bagList); + return bagList; + } + + private void fetchAllTilesForRendererVisibleArea(StateRenderer2D renderer, String mapStyle) { + int[] tmmr = getTileMinMaxForRenderer(renderer); + int tileXMin = tmmr[0]; + int tileXMax = tmmr[2]; + int tileYMin = tmmr[1]; + int tileYMax = tmmr[3]; + int levelOfDetail = renderer.getLevelOfDetail(); + List bagList = fetchQuadKeysFor(tileXMin, tileXMax, tileYMin, tileYMax, mapStyle, levelOfDetail, 2); for (String quadKey : bagList) { Map map = tileHolderList.get(mapStyle); @@ -1116,7 +1185,7 @@ public int compare(String o1, String o2) { } } - private List produceQuadKeysWorker(String quadKey, int maxLevelOfDetail, List bagList) { + private static List produceQuadKeysWorker(String quadKey, int maxLevelOfDetail, List bagList) { if (quadKey.length() >= maxLevelOfDetail) return bagList; String qk0 = quadKey + "0"; @@ -1164,13 +1233,13 @@ public void createChooseMapStyleDialog() { Window winParent = SwingUtilities.windowForComponent(renderer2D); //parent); dialogProperties = new JDialog(winParent); dialogProperties.setLayout(new BorderLayout(10, 0)); - dialogProperties.setSize(700, 350); + dialogProperties.setSize(720, 350); dialogProperties.setIconImages(ConfigFetch.getIconImagesForFrames()); dialogProperties.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); dialogProperties.setTitle(I18n.text("World Map Layer")); ButtonGroup baseMapsButtonGroup = new ButtonGroup(); - JPanel confPanel = new JPanel(new MigLayout("ins 0, wrap 5")); + JPanel confPanel = new JPanel(new MigLayout("ins 0, wrap 6")); confPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); List mapKeys = getOrderedMapList(); @@ -1232,7 +1301,7 @@ public void stateChanged(ChangeEvent e) { boolean tileOrMapProvider = isTileOrMapProvider(ms); if (tileOrMapProvider) { final JButton clearButton = new JButton(); - AbstractAction clearAction = new AbstractAction(I18n.text("Clear cache").toLowerCase()) { + AbstractAction clearAction = new AbstractAction(I18n.text("Clear").toLowerCase()) { @Override public void actionPerformed(ActionEvent e) { clearButton.setEnabled(false); @@ -1258,12 +1327,50 @@ protected void done() { } }; clearButton.setAction(clearAction); + clearButton.setToolTipText(I18n.text("Clear all tiles from disk cache.")); confPanel.add(clearButton, "sg buttons"); } else { confPanel.add(new JLabel(), "sg buttons"); } + if (tileOrMapProvider) { + final JButton clearVizButton = new JButton(); + AbstractAction clearVizAction = new AbstractAction(I18n.text("Clear visible").toLowerCase()) { + @Override + public void actionPerformed(ActionEvent e) { + clearVizButton.setEnabled(false); + new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + int levelOfDetail = renderer2D.getLevelOfDetail(); + List bagList = fetchQuadKeysFor(renderer2D, ms, MapTileUtil.LEVEL_MAX - levelOfDetail); + clearMemCache(ms, bagList); + clearDiskCache(ms, bagList); + return null; + } + + @Override + protected void done() { + try { + get(); + } + catch (Exception e) { + NeptusLog.pub().error(e); + } + clearVizButton.setEnabled(true); + } + }.execute(); + } + }; + clearVizButton.setAction(clearVizAction); + clearVizButton.setToolTipText(I18n.text("Clear visible tiles from disk cache.")); + confPanel.add(clearVizButton, "sg buttons"); + } + else { + confPanel.add(new JLabel(), "sg buttons"); + } + final Class clazz = getClassForStyle(ms); if (clazz.getAnnotation(MapTileProvider.class).usePropertiesOrCustomOptionsDialog()) { Vector dFA = new Vector(); @@ -1276,7 +1383,7 @@ protected void done() { } else { final PropertiesProvider pprov = createPropertiesProvider(ms, dFA); - confPanel.add(new JButton(new AbstractAction(I18n.text("Edit properties").toLowerCase()) { + confPanel.add(new JButton(new AbstractAction(I18n.text("properties").toLowerCase()) { @Override public void actionPerformed(ActionEvent e) { PropertiesEditor.editProperties(pprov, dialogProperties, true); @@ -1296,7 +1403,7 @@ public void actionPerformed(ActionEvent e) { dialog.setModalityType(ModalityType.DOCUMENT_MODAL); final JDialog dialog1 = dialog; - confPanel.add(new JButton(new AbstractAction(I18n.text("Edit properties").toLowerCase()) { + confPanel.add(new JButton(new AbstractAction(I18n.text("properties").toLowerCase()) { @Override public void actionPerformed(ActionEvent e) { dialog1.requestFocus(); @@ -1332,7 +1439,7 @@ public void actionPerformed(ActionEvent e) { else { final JButton fetchButton = new JButton(); /// To fetch the map tiles from the visible area - AbstractAction fetchAction = new AbstractAction(I18n.text("Fetch visible area").toLowerCase()) { + AbstractAction fetchAction = new AbstractAction(I18n.text("Fetch visible").toLowerCase()) { @Override public void actionPerformed(ActionEvent e) { fetchButton.setEnabled(false); diff --git a/src/java/pt/lsts/neptus/renderer2d/tiles/Tile.java b/src/java/pt/lsts/neptus/renderer2d/tiles/Tile.java index 5beeed7f49..60806e0da4 100644 --- a/src/java/pt/lsts/neptus/renderer2d/tiles/Tile.java +++ b/src/java/pt/lsts/neptus/renderer2d/tiles/Tile.java @@ -41,7 +41,11 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Timer; import java.util.TimerTask; import java.util.Vector; @@ -593,24 +597,59 @@ private void loadImageFromLowerLevelOfDetail() { } /** - * This should be override, this implementation does not do anything. + * This should be overridden, this implementation does not do anything. */ - public static void clearDiskCache() { - + //public static void clearDiskCache(String... tileQuadKeys) { + //} + + /** + * This will delete the disk cache. This will run on a Thread. + * A public static method clearDiskCache(String... tileQuadKeys) should be created for every class extending Tile. + * @param tileClassId This should be the class {@link Class#getSimpleName()}. + * If null will delete all cache. + * @param tileQuadKeys This should be the quad keys of the tiles to delete. + */ + public static void clearDiskCache(String tileClassId) { + clearDiskCache(tileClassId, null); } - + /** * This will delete the disk cache. This will run on a Thread. - * A public static method clearDiskCache() should be created for every class extending Tile. + * A public static method clearDiskCache(String... tileQuadKeys) should be created for every class extending Tile. * @param tileClassId This should be the class {@link Class#getSimpleName()}. + * If null will delete all cache. + * @param tileQuadKeys This should be the quad keys of the tiles to delete. */ - protected static void clearDiskCache(String tileClassId) { + public static void clearDiskCache(String tileClassId, List tileQuadKeys) { + Map>> mapTilesZXY = new HashMap<>(); + if (tileQuadKeys != null) { + for (String tileQuadKey : tileQuadKeys) { + try { + int[] txy = MapTileUtil.quadKeyToTileXY(tileQuadKey); + String z = txy[2] + ""; + String x = txy[0] + ""; + String y = txy[1] + ""; + if (!mapTilesZXY.containsKey(z)) + mapTilesZXY.put(z, new HashMap<>()); + Map> mz = mapTilesZXY.get(z); + if (!mz.containsKey(x)) + mz.put(x, new ArrayList<>()); + mz.get(x).add(y); + } + catch (Exception e) { + NeptusLog.pub().debug("Error parsing tile quad key: {}", tileQuadKey); + } + } + } + final String path = TILE_BASE_CACHE_DIR + "/" + tileClassId; Thread t = new Thread(() -> { tileCacheDiskClearOrTileSaveLock.writeLock().lock(); + int bCount = 0, zCount = 0, xCount = 0, yCount = 0; + int zCountDelErr = 0, xCountDelErr = 0, yCountDelErr = 0; try { File base = new File(path); - File[] zList = base.listFiles(pathname -> pathname.isDirectory() && (pathname.getName().length() > 0 + File[] zList = base.listFiles(pathname -> pathname.isDirectory() && (!pathname.getName().isEmpty() && pathname.getName().charAt(0) == 'z')); if (zList == null) return; @@ -618,7 +657,9 @@ protected static void clearDiskCache(String tileClassId) { String zStr = fileZ.getName().replace("z", ""); try { Integer.parseInt(zStr); - File[] xList = fileZ.listFiles(pathname -> pathname.isDirectory() && (pathname.getName().length() > 0 + if (!mapTilesZXY.isEmpty() && !mapTilesZXY.containsKey(zStr)) + continue; + File[] xList = fileZ.listFiles(pathname -> pathname.isDirectory() && (!pathname.getName().isEmpty() && pathname.getName().charAt(0) == 'x')); if (xList == null) continue; @@ -626,41 +667,63 @@ protected static void clearDiskCache(String tileClassId) { String xStr = fileX.getName().replace("x", ""); try { Integer.parseInt(xStr); + if (!mapTilesZXY.isEmpty() && !mapTilesZXY.get(zStr).containsKey(xStr)) + continue; File[] yList = fileX.listFiles(pathname -> pathname.isFile() && TILE_FX_EXTENSION.equalsIgnoreCase(FileUtil - .getFileExtension(pathname)) - && (pathname.getName().length() > 0 && pathname.getName().charAt(0) == 'y')); + .getFileExtension(pathname)) + && (!pathname.getName().isEmpty() && pathname.getName().charAt(0) == 'y')); if (yList == null) continue; for (File fileY : yList) { String yStr = fileY.getName().replace("y", "").replace("." + TILE_FX_EXTENSION, ""); try { Integer.parseInt(yStr); - fileY.delete(); + if (!mapTilesZXY.isEmpty() && !mapTilesZXY.get(zStr).get(xStr).contains(yStr)) + continue; + if (fileY.delete()) + yCount++; + else + yCountDelErr++; } catch (Exception e) { - e.printStackTrace(); + NeptusLog.pub().debug("Error deleting tile Y file: {} : {}", fileY.getAbsolutePath(), e.getMessage()); } } - fileX.delete(); + if (mapTilesZXY.isEmpty() || Objects.requireNonNull(fileX.listFiles()).length == 0) { + if (fileX.delete()) + xCount++; + else + xCountDelErr++; + } } catch (Exception e) { - e.printStackTrace(); + NeptusLog.pub().debug("Error deleting tile X folder: {} : {}", fileX.getAbsolutePath(), e.getMessage()); } } - fileZ.delete(); + if (mapTilesZXY.isEmpty() || Objects.requireNonNull(fileZ.listFiles()).length == 0) { + if (fileZ.delete()) + zCount++; + else + zCountDelErr++; + } } catch (Exception e) { - e.printStackTrace(); + NeptusLog.pub().debug("Error deleting tile Z folder: {} : {}", fileZ.getAbsolutePath(), e.getMessage()); } } - base.delete(); + if (mapTilesZXY.isEmpty() || Objects.requireNonNull(base.listFiles()).length == 0) { + bCount = base.delete() ? bCount + 1 : bCount; + } } catch (Exception e) { - e.printStackTrace(); + NeptusLog.pub().debug("Error deleting tile base folder: {} : {}", path, e.getMessage()); } finally { tileCacheDiskClearOrTileSaveLock.writeLock().unlock(); + NeptusLog.pub().info("Deleted {} {} folders, {} z folders, {} x folders, {} y files. Errors: {} z folders, {} x folders, {} y files.", + bCount, tileClassId, zCount, xCount, yCount, zCountDelErr, xCountDelErr, yCountDelErr); + } }); t.setDaemon(true); From 2b61bd4b20181da495fa766e9b27eedd6dd30790 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Sat, 11 Jan 2025 16:50:35 +0000 Subject: [PATCH 2/8] renderer2d/WorldRenderPainter: Fix zoom buttons size mismatch. --- src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java b/src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java index 1741b8874f..6195477b26 100644 --- a/src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java +++ b/src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java @@ -1471,6 +1471,7 @@ protected void done() { } final JLabel levelOfDetailLabel = new JLabel(); + final JPanel zoomPanel = new JPanel(new MigLayout("ins 0")); final JButton zoomInButton = new JButton(new AbstractAction("+") { @Override public void actionPerformed(ActionEvent e) { @@ -1485,6 +1486,8 @@ public void actionPerformed(ActionEvent e) { } }); zoomOutButton.setToolTipText(I18n.text("Zoom out")); + zoomPanel.add(zoomInButton, "sg zoom"); + zoomPanel.add(zoomOutButton, "sg zoom"); final JLabel memInfoLabel = new JLabel(); final JLabel loadingTilesLabel = new JLabel(); final JButton stopLoadingButton = new JButton(new AbstractAction(I18n.text("Stop Loading")) { @@ -1497,8 +1500,7 @@ public void actionPerformed(ActionEvent e) { busyPanel.setVisible(false); JXStatusBar statusBar = new JXStatusBar(); statusBar.add(levelOfDetailLabel); - statusBar.add(zoomInButton); - statusBar.add(zoomOutButton); + statusBar.add(zoomPanel); statusBar.add(memInfoLabel, JXStatusBar.Constraint.ResizeBehavior.FILL); statusBar.add(loadingTilesLabel); statusBar.add(stopLoadingButton); From 9b5b05e8b3b39c78b0dd576b8dca0c8de279d35f Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Sat, 11 Jan 2025 17:02:43 +0000 Subject: [PATCH 3/8] comm/ssh/SSHConnectionDialog: Fixing location if has a parent window. --- src/java/pt/lsts/neptus/comm/ssh/SSHConnectionDialog.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/ssh/SSHConnectionDialog.java b/src/java/pt/lsts/neptus/comm/ssh/SSHConnectionDialog.java index 9b7de2c770..7573520adb 100644 --- a/src/java/pt/lsts/neptus/comm/ssh/SSHConnectionDialog.java +++ b/src/java/pt/lsts/neptus/comm/ssh/SSHConnectionDialog.java @@ -257,7 +257,11 @@ else if (parentWindow instanceof Dialog) jDialog.setSize(this.getWidth() + 5, this.getHeight() + 35); jDialog.getContentPane().setLayout(new BorderLayout()); jDialog.getContentPane().add(this, BorderLayout.CENTER); - GuiUtils.centerOnScreen(jDialog); + if (parentWindow != null) { + jDialog.setLocationRelativeTo(parentWindow); + } else { + GuiUtils.centerOnScreen(jDialog); + } //jDialog.setModal(true); jDialog.setModalityType(parentWindow != null ? ModalityType.DOCUMENT_MODAL : ModalityType.APPLICATION_MODAL); jDialog.setAlwaysOnTop(true); From 7d66ea728bda3cec91eb4be88d78e5f0b069937d Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Sat, 11 Jan 2025 17:09:18 +0000 Subject: [PATCH 4/8] gui/PropertiesEditor: Fixing location if has a parent window. --- src/java/pt/lsts/neptus/gui/PropertiesEditor.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/gui/PropertiesEditor.java b/src/java/pt/lsts/neptus/gui/PropertiesEditor.java index df869c5fe0..fb85f56128 100644 --- a/src/java/pt/lsts/neptus/gui/PropertiesEditor.java +++ b/src/java/pt/lsts/neptus/gui/PropertiesEditor.java @@ -371,7 +371,11 @@ public void windowActivated(WindowEvent e) { propertySheetDialog.getContentPane().add(psp); propertySheetDialog.pack(); - GuiUtils.centerOnScreen(propertySheetDialog); + if (parent != null) { + propertySheetDialog.setLocationRelativeTo(parent); + } else { + GuiUtils.centerOnScreen(propertySheetDialog); + } propertySheetDialog.setModalityType(ModalityType.DOCUMENT_MODAL); return propertySheetDialog; } From 5fc26e2ef154bbb83c296c9f4a9dc7c726e700bd Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Sun, 12 Jan 2025 12:43:21 +0000 Subject: [PATCH 5/8] util/GuiUtils: Adding reactEscapeKeyPress also for dialogues without cancel button. --- src/java/pt/lsts/neptus/util/GuiUtils.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/java/pt/lsts/neptus/util/GuiUtils.java b/src/java/pt/lsts/neptus/util/GuiUtils.java index d5c19dd745..a4d8a91e31 100644 --- a/src/java/pt/lsts/neptus/util/GuiUtils.java +++ b/src/java/pt/lsts/neptus/util/GuiUtils.java @@ -60,7 +60,9 @@ import java.awt.TrayIcon; import java.awt.TrayIcon.MessageType; import java.awt.Window; +import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; +import java.awt.event.WindowEvent; import java.awt.geom.AffineTransform; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; @@ -88,6 +90,8 @@ import javax.sound.sampled.Clip; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; +import javax.swing.AbstractAction; +import javax.swing.Action; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComboBox; @@ -102,6 +106,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPasswordField; +import javax.swing.JRootPane; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.KeyStroke; @@ -1008,6 +1013,18 @@ public static void reactEscapeKeyPress(JButton btn) { KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true), JComponent.WHEN_IN_FOCUSED_WINDOW); } + public static void reactEscapeKeyPress(JDialog dialog) { + Action dispatchClosing = new AbstractAction() { + public void actionPerformed(ActionEvent event) { + dialog.dispatchEvent(new WindowEvent(dialog, WindowEvent.WINDOW_CLOSING)); + } + }; + JRootPane root = dialog.getRootPane(); + root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( + KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), JComponent.WHEN_IN_FOCUSED_WINDOW); + root.getActionMap().put(JComponent.WHEN_IN_FOCUSED_WINDOW, dispatchClosing); + } + /** * @param btn * @param keyEvent From 6144c9176dbc728600a1a842063a6b07110dee15 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Sun, 12 Jan 2025 12:44:02 +0000 Subject: [PATCH 6/8] renderer2d/WorldRenderPainter: Adding close dialog with escape stroke. --- src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java b/src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java index 6195477b26..723cb0e65d 100644 --- a/src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java +++ b/src/java/pt/lsts/neptus/renderer2d/WorldRenderPainter.java @@ -1237,6 +1237,7 @@ public void createChooseMapStyleDialog() { dialogProperties.setIconImages(ConfigFetch.getIconImagesForFrames()); dialogProperties.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); dialogProperties.setTitle(I18n.text("World Map Layer")); + GuiUtils.reactEscapeKeyPress(dialogProperties); ButtonGroup baseMapsButtonGroup = new ButtonGroup(); JPanel confPanel = new JPanel(new MigLayout("ins 0, wrap 6")); From e831ea324b5d7af5c686c520608b41f528594e9a Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Sun, 12 Jan 2025 12:44:26 +0000 Subject: [PATCH 7/8] gui/AboutPanel: Adding close dialog with escape stroke. --- src/java/pt/lsts/neptus/gui/AboutPanel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java/pt/lsts/neptus/gui/AboutPanel.java b/src/java/pt/lsts/neptus/gui/AboutPanel.java index dc1e7a8ae0..42441f87de 100644 --- a/src/java/pt/lsts/neptus/gui/AboutPanel.java +++ b/src/java/pt/lsts/neptus/gui/AboutPanel.java @@ -123,6 +123,7 @@ public void mouseClicked(MouseEvent e) { }); this.fillText(); GuiUtils.centerOnScreen(this); + GuiUtils.reactEscapeKeyPress(this); } /** From d57eb46e0120fe23e7d7045af5cbfaaaf0eada66 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Sun, 12 Jan 2025 12:45:03 +0000 Subject: [PATCH 8/8] plugins/s57/S57Chart: Adding close dialog with escape stroke. --- .../s57/src/java/pt/lsts/neptus/plugins/s57/S57Chart.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins-dev/s57/src/java/pt/lsts/neptus/plugins/s57/S57Chart.java b/plugins-dev/s57/src/java/pt/lsts/neptus/plugins/s57/S57Chart.java index 1dc69427d8..8fd9d22129 100644 --- a/plugins-dev/s57/src/java/pt/lsts/neptus/plugins/s57/S57Chart.java +++ b/plugins-dev/s57/src/java/pt/lsts/neptus/plugins/s57/S57Chart.java @@ -46,6 +46,7 @@ import pt.lsts.neptus.renderer2d.StateRenderer2D; import pt.lsts.neptus.renderer2d.tiles.MapPainterProvider; import pt.lsts.neptus.types.coord.LocationType; +import pt.lsts.neptus.util.GuiUtils; import pt.lsts.neptus.util.conf.ConfigFetch; import pt.lsts.neptus.util.coord.MapTileUtil; import pt.lsts.s57.S57; @@ -124,6 +125,7 @@ public void dispose() { painterList.put(renderer, NeptusS57Painter.forge(s57, mc)); } + GuiUtils.reactEscapeKeyPress(dialog); return dialog; }