From ac609fe7535add07518797f157c74ef66ea76e9e Mon Sep 17 00:00:00 2001 From: Igor Maznitsa Date: Tue, 10 Aug 2021 10:02:37 +0300 Subject: [PATCH] #86 Improved NoteEditor to catch dialog close button, added catch of cancel button --- mind-map/mind-map-swing-panel/pom.xml | 9 ++ .../mindmap/swing/panel/utils/Utils.java | 109 +++++++++++++----- mind-map/pom.xml | 4 +- 3 files changed, 91 insertions(+), 31 deletions(-) diff --git a/mind-map/mind-map-swing-panel/pom.xml b/mind-map/mind-map-swing-panel/pom.xml index d8798d2d..7977b9c1 100644 --- a/mind-map/mind-map-swing-panel/pom.xml +++ b/mind-map/mind-map-swing-panel/pom.xml @@ -191,6 +191,15 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + + \ No newline at end of file diff --git a/mind-map/mind-map-swing-panel/src/main/java/com/igormaznitsa/mindmap/swing/panel/utils/Utils.java b/mind-map/mind-map-swing-panel/src/main/java/com/igormaznitsa/mindmap/swing/panel/utils/Utils.java index 675c8bd1..1db403c8 100644 --- a/mind-map/mind-map-swing-panel/src/main/java/com/igormaznitsa/mindmap/swing/panel/utils/Utils.java +++ b/mind-map/mind-map-swing-panel/src/main/java/com/igormaznitsa/mindmap/swing/panel/utils/Utils.java @@ -58,10 +58,7 @@ import java.awt.*; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; -import java.awt.event.ActionEvent; -import java.awt.event.HierarchyEvent; -import java.awt.event.HierarchyListener; -import java.awt.event.KeyEvent; +import java.awt.event.*; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; @@ -70,10 +67,8 @@ import java.io.*; import java.lang.reflect.InvocationTargetException; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.List; -import java.util.Locale; -import java.util.ResourceBundle; +import java.util.*; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.regex.Matcher; @@ -876,6 +871,33 @@ public static boolean isKeyStrokeEvent(@Nullable final KeyStroke keyStroke, fina return result; } + @Nonnull + @MustNotContainNull + private static List findAllOptionPaneButtons(@Nonnull final JComponent component) { + final List result = new ArrayList<>(); + Arrays.stream(component.getComponents()) + .filter(x -> x instanceof JComponent) + .map(x -> (JComponent) x) + .forEach(x -> { + if (x instanceof JButton) { + if ("OptionPane.button".equals(x.getName())) { + result.add((JButton) x); + } + } else { + result.addAll(findAllOptionPaneButtons(x)); + } + }); + return result; + } + + private static void replaceActionListenerForButton(@Nonnull final JButton button, @Nonnull final ActionListener listener) { + final ActionListener[] currentListeners = button.getActionListeners(); + for (final ActionListener l : currentListeners) { + button.removeActionListener(l); + } + button.addActionListener(listener); + } + @Nonnull @SafeVarargs @ReturnsOriginal @@ -886,40 +908,69 @@ public static JComponent catchEscInParentDialog( @Nonnull @MustNotContainNull final Consumer... beforeClose) { component.addHierarchyListener(new HierarchyListener() { + final Consumer processor = dialog -> { + final boolean close; + if (doClose == null) { + close = true; + } else { + if (doClose.test(dialog)) { + close = dialogProvider + .msgConfirmOkCancel(dialog, BUNDLE.getString("Utils.confirmActionTitle"), BUNDLE.getString("Utils.closeForContentChange")); + } else { + close = true; + } + } + if (close) { + try { + for (final Consumer c : beforeClose) { + try { + c.accept(dialog); + } catch (Exception ex) { + LOGGER.error("Error during before close call", ex); + } + } + } finally { + dialog.dispose(); + } + } + }; private final KeyStroke escapeKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false); @Override public void hierarchyChanged(@Nonnull final HierarchyEvent e) { final Window window = SwingUtilities.getWindowAncestor(component); - if (window instanceof JDialog) { + if (window instanceof JDialog && (e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) != 0) { final JDialog dialog = (JDialog) window; + + final List dialogButtons = findAllOptionPaneButtons(dialog.getRootPane()); + dialogButtons.stream() + .filter(x -> "cancel".equalsIgnoreCase(x.getText())) + .forEach(x -> replaceActionListenerForButton(x, be -> { + processor.accept(dialog); + })); + + dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); + + final WindowListener windowListener = new WindowAdapter() { + @Override + public void windowClosing(@Nonnull final WindowEvent e) { + processor.accept(dialog); + } + }; + + final WindowListener[] windowListeners = dialog.getWindowListeners(); + for (final WindowListener w : windowListeners) { + dialog.removeWindowListener(w); + } + dialog.addWindowListener(windowListener); + final InputMap inputMap = dialog.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); inputMap.put(escapeKeyStroke, "PRESSING_ESCAPE"); final ActionMap actionMap = dialog.getRootPane().getActionMap(); actionMap.put("PRESSING_ESCAPE", new AbstractAction() { @Override public void actionPerformed(@Nonnull final ActionEvent e) { - final boolean close; - if (doClose == null) { - close = true; - } else { - if (doClose.test(dialog)) { - close = dialogProvider - .msgConfirmOkCancel(dialog, BUNDLE.getString("Utils.confirmActionTitle"), BUNDLE.getString("Utils.closeForContentChange")); - } else { - close = true; - } - } - if (close) { - for (final Consumer c : beforeClose) { - try { - c.accept(dialog); - } catch (Exception ex) { - LOGGER.error("Error during before close call", ex); - } - } - dialog.dispose(); - } + processor.accept(dialog); } }); } diff --git a/mind-map/pom.xml b/mind-map/pom.xml index 4068ae85..a385df55 100644 --- a/mind-map/pom.xml +++ b/mind-map/pom.xml @@ -215,8 +215,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.7 - 1.7 + 1.8 + 1.8 true true