Skip to content

Commit

Permalink
#86 Improved NoteEditor to show confirmation dialog if content was ch…
Browse files Browse the repository at this point in the history
…anged and ESC pressed to close
  • Loading branch information
raydac committed Aug 9, 2021
1 parent 45da424 commit a02ed59
Show file tree
Hide file tree
Showing 11 changed files with 203 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,9 @@ public void editTextForTopic(final Topic topic) {
if (note == null) {
// create new
result = IdeaUtils
.editText(this.editor.getProject(), String
.format(BUNDLE.getString("MMDGraphEditor.editTextForTopic.dlfAddNoteTitle"),
.editText(this.editor.getProject(),
this.dialogProvider,
String.format(BUNDLE.getString("MMDGraphEditor.editTextForTopic.dlfAddNoteTitle"),
Utils.makeShortTextVersion(topic.getText(), 16)),
new NoteEditorData()); //NOI18N
} else {
Expand Down Expand Up @@ -470,8 +471,8 @@ public void editTextForTopic(final Topic topic) {
} else {
result = IdeaUtils
.editText(this.editor.getProject(),
String.format(
BUNDLE.getString("MMDGraphEditor.editTextForTopic.dlgEditNoteTitle"),
this.dialogProvider,
String.format(BUNDLE.getString("MMDGraphEditor.editTextForTopic.dlgEditNoteTitle"),
Utils.makeShortTextVersion(topic.getText(), 16)), noteText);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ public class PlainTextEditor extends JPanel {
private volatile String password;
private volatile String hint;

private final String originalText;

private boolean cancelled;

private static final FileFilter TEXT_FILE_FILTER = new FileFilter() {

@Override
Expand All @@ -91,6 +95,7 @@ public PlainTextEditor(final Project project, final NoteEditorData data) {

this.password = data.getPassword();
this.hint = data.getHint();
this.originalText = data.getText();

this.editor = new EmptyTextEditor(project);

Expand Down Expand Up @@ -195,6 +200,18 @@ public PlainTextEditor(final Project project, final NoteEditorData data) {
SwingUtilities.invokeLater(() -> editor.replaceSelection(data.getText()));
}

public boolean isChanged() {
return !this.originalText.equals(this.getEditor().getText());
}

public boolean isCancelled(){
return this.cancelled;
}

public void cancel() {
this.cancelled = true;
}

@Nonnull
private JButton makeButton(@Nullable final String text, @Nullable final Icon icon) {
final JButton result = UI_COMPO_FACTORY.makeButton();
Expand All @@ -212,8 +229,9 @@ private JToggleButton makeToggleButton(@Nullable final String text, @Nullable fi
return result;
}

@Nullable
public NoteEditorData getData() {
return new NoteEditorData(this.editor.getText(),this.password, this.hint);
return this.cancelled ? null : new NoteEditorData(this.editor.getText(),this.password, this.hint);
}

public EmptyTextEditor getEditor() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.igormaznitsa.mindmap.model.logger.LoggerFactory;
import com.igormaznitsa.mindmap.swing.panel.DialogProvider;
import com.igormaznitsa.mindmap.swing.panel.HasPreferredFocusComponent;
import com.igormaznitsa.mindmap.swing.panel.utils.Utils;
import com.intellij.CommonBundle;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.Disposable;
Expand Down Expand Up @@ -341,10 +342,12 @@ public static File chooseFile(final Component parent, final boolean filesOnly, f
}
}

public static NoteEditorData editText(final Project project, final String title, final NoteEditorData data) {
public static NoteEditorData editText(final Project project, final DialogProvider dialogProvider, final String title, final NoteEditorData data) {
final PlainTextEditor editor = new PlainTextEditor(project, data);
editor.setPreferredSize(new Dimension(550, 450));

Utils.catchEscInParentDialog(editor, dialogProvider, d -> editor.isChanged(), x -> editor.cancel());

final DialogComponent dialog = new DialogComponent(project, title, editor, editor.getEditor(), false);

return dialog.showAndGet() ? editor.getData() : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,77 +19,67 @@
import com.igormaznitsa.meta.annotation.ImplementationNote;
import com.igormaznitsa.meta.annotation.MayContainNull;
import com.igormaznitsa.meta.annotation.MustNotContainNull;
import com.igormaznitsa.meta.annotation.ReturnsOriginal;
import com.igormaznitsa.mindmap.model.Topic;
import com.igormaznitsa.mindmap.model.logger.Logger;
import com.igormaznitsa.mindmap.model.logger.LoggerFactory;
import com.igormaznitsa.mindmap.plugins.MindMapPluginRegistry;
import com.igormaznitsa.mindmap.plugins.PopUpSection;
import com.igormaznitsa.mindmap.plugins.api.PluginContext;
import com.igormaznitsa.mindmap.plugins.api.PopUpMenuItemPlugin;
import com.igormaznitsa.mindmap.swing.panel.DialogProvider;
import com.igormaznitsa.mindmap.swing.panel.MindMapPanelConfig;
import com.igormaznitsa.mindmap.swing.panel.ui.AbstractCollapsableElement;
import com.igormaznitsa.mindmap.swing.panel.ui.AbstractElement;
import com.igormaznitsa.mindmap.swing.panel.ui.gfx.MMGraphics;
import com.igormaznitsa.mindmap.swing.panel.ui.gfx.MMGraphics2DWrapper;
import com.igormaznitsa.mindmap.swing.services.IconID;
import com.igormaznitsa.mindmap.swing.services.ImageIconService;
import com.igormaznitsa.mindmap.swing.services.ImageIconServiceProvider;
import com.igormaznitsa.mindmap.swing.services.UIComponentFactory;
import com.igormaznitsa.mindmap.swing.services.UIComponentFactoryProvider;
import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import com.igormaznitsa.mindmap.swing.services.*;
import net.iharder.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.SystemUtils;
import org.jsoup.Jsoup;
import org.jsoup.helper.W3CDom;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
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.function.Consumer;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import net.iharder.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.SystemUtils;
import org.jsoup.Jsoup;
import org.jsoup.helper.W3CDom;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public final class Utils {

Expand Down Expand Up @@ -513,9 +503,9 @@ public static String color2html(@Nullable final Color color, final boolean hasAl
final int[] components;

if (hasAlpha) {
components = new int[] {color.getAlpha(), color.getRed(), color.getGreen(), color.getBlue()};
components = new int[]{color.getAlpha(), color.getRed(), color.getGreen(), color.getBlue()};
} else {
components = new int[] {color.getRed(), color.getGreen(), color.getBlue()};
components = new int[]{color.getRed(), color.getGreen(), color.getBlue()};
}

for (final int c : components) {
Expand Down Expand Up @@ -776,12 +766,12 @@ public static Color makeContrastColor(@Nonnull final Color color) {
@Nonnull
@MustNotContainNull
private static List<JMenuItem> findPopupMenuItems(
@Nonnull final PluginContext context,
@Nonnull final PopUpSection section,
final boolean fullScreenModeActive,
@Nonnull @MayContainNull final List<JMenuItem> list,
@Nullable final Topic topicUnderMouse,
@Nonnull @MustNotContainNull final List<PopUpMenuItemPlugin> pluginMenuItems
@Nonnull final PluginContext context,
@Nonnull final PopUpSection section,
final boolean fullScreenModeActive,
@Nonnull @MayContainNull final List<JMenuItem> list,
@Nullable final Topic topicUnderMouse,
@Nonnull @MustNotContainNull final List<PopUpMenuItemPlugin> pluginMenuItems
) {
list.clear();

Expand All @@ -791,8 +781,8 @@ private static List<JMenuItem> findPopupMenuItems(
}
if (p.getSection() == section) {
if (!(p.needsTopicUnderMouse() || p.needsSelectedTopics())
|| (p.needsTopicUnderMouse() && topicUnderMouse != null)
|| (p.needsSelectedTopics() && context.getSelectedTopics().length > 0)) {
|| (p.needsTopicUnderMouse() && topicUnderMouse != null)
|| (p.needsSelectedTopics() && context.getSelectedTopics().length > 0)) {

final JMenuItem item = p.makeMenuItem(context, topicUnderMouse);
if (item != null) {
Expand Down Expand Up @@ -845,9 +835,9 @@ public static boolean isDataFlavorAvailable(@Nonnull final Clipboard clipboard,

@Nonnull
public static JPopupMenu makePopUp(
@Nonnull final PluginContext context,
final boolean fullScreenModeActive,
@Nullable final Topic topicUnderMouse
@Nonnull final PluginContext context,
final boolean fullScreenModeActive,
@Nullable final Topic topicUnderMouse
) {
final JPopupMenu result = UI_COMPO_FACTORY.makePopupMenu();
final List<PopUpMenuItemPlugin> pluginMenuItems = MindMapPluginRegistry.getInstance().findFor(PopUpMenuItemPlugin.class);
Expand Down Expand Up @@ -886,6 +876,58 @@ public static boolean isKeyStrokeEvent(@Nullable final KeyStroke keyStroke, fina
return result;
}

@Nonnull
@SafeVarargs
@ReturnsOriginal
public static JComponent catchEscInParentDialog(
@Nonnull final JComponent component,
@Nonnull final DialogProvider dialogProvider,
@Nullable final Predicate<JDialog> doClose,
@Nonnull @MustNotContainNull final Consumer<JDialog>... beforeClose) {
component.addHierarchyListener(new HierarchyListener() {

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) {
final JDialog dialog = (JDialog) window;
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<JDialog> c : beforeClose) {
try {
c.accept(dialog);
} catch (Exception ex) {
LOGGER.error("Error during before close call", ex);
}
}
dialog.dispose();
}
}
});
}
}
});
return component;
}

@Nonnull
public static byte[] base64decode(@Nonnull final String text) throws IOException {
return Base64.decode(text);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,7 @@ PasswordPanel.labelPassword.tooltip = Password text, all leading and trailing sp
PasswordPanel.labelHint.text = Hint:
PasswordPanel.labelHint.tooltip = Hint for the password
PasswordPanel.checkboxShowPassword.text = Show password
PasswordPanel.checkboxShowPassword.tooltip = Show or hide password text
PasswordPanel.checkboxShowPassword.tooltip = Show or hide password text
# Utils
Utils.confirmActionTitle = Confirm action
Utils.closeForContentChange = Content is changed, close editor?
15 changes: 12 additions & 3 deletions mind-map/nb-mind-map/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
<artifactId>animal-sniffer-maven-plugin</artifactId>
<executions>
<execution>
<id>ensure-java-1.6-class-library</id>
<id>ensure-java-1.8-class-library</id>
<phase>test</phase>
<goals>
<goal>check</goal>
Expand All @@ -141,8 +141,8 @@
</annotations>
<signature>
<groupId>org.codehaus.mojo.signature</groupId>
<artifactId>java16</artifactId>
<version>1.1</version>
<artifactId>java18</artifactId>
<version>1.0</version>
</signature>
</configuration>
</execution>
Expand Down Expand Up @@ -187,6 +187,15 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1437,8 +1437,8 @@ private void editTextForTopic(final Topic topic) {
final NoteEditorData result;
if (note == null) {
// create new
result = NbUtils.editText(null, String
.format(BUNDLE.getString("MMDGraphEditor.editTextForTopic.dlfAddNoteTitle"),
result = NbUtils.editText(null, DialogProviderManager.getInstance().getDialogProvider(),
String.format(BUNDLE.getString("MMDGraphEditor.editTextForTopic.dlfAddNoteTitle"),
Utils.makeShortTextVersion(topic.getText(), 16)),
new NoteEditorData()); //NOI18N
} else {
Expand Down Expand Up @@ -1475,7 +1475,7 @@ private void editTextForTopic(final Topic topic) {
if (noteText == null) {
result = null;
} else {
result = NbUtils.editText(null, String.format(
result = NbUtils.editText(null, DialogProviderManager.getInstance().getDialogProvider(), String.format(
BUNDLE.getString("MMDGraphEditor.editTextForTopic.dlgEditNoteTitle"),
Utils.makeShortTextVersion(topic.getText(), 16)), noteText);
}
Expand Down
Loading

0 comments on commit a02ed59

Please sign in to comment.