Added better load and save preferences, non-modal help.

This commit is contained in:
Andrew Lalis 2021-02-23 09:10:23 +01:00
parent 7a49772540
commit f37df5defc
5 changed files with 59 additions and 25 deletions

View File

@ -18,11 +18,12 @@ import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.prefs.Preferences;
public class ExportToImageAction extends AbstractAction {
private static ExportToImageAction instance;
private static final String LAST_EXPORT_LOCATION_KEY = "lastExportLocation";
private static ExportToImageAction instance;
public static ExportToImageAction getInstance() {
if (instance == null) {
instance = new ExportToImageAction();
@ -30,8 +31,6 @@ public class ExportToImageAction extends AbstractAction {
return instance;
}
private File lastSelectedFile;
@Setter
private MappingModel model;
@ -52,12 +51,14 @@ public class ExportToImageAction extends AbstractAction {
);
return;
}
JFileChooser fileChooser = new JFileChooser(this.lastSelectedFile);
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileFilter(new FileNameExtensionFilter(
"Image files", ImageIO.getReaderFileSuffixes()
));
if (this.lastSelectedFile != null) {
fileChooser.setSelectedFile(this.lastSelectedFile);
Preferences prefs = Preferences.userNodeForPackage(ExportToImageAction.class);
String path = prefs.get(LAST_EXPORT_LOCATION_KEY, null);
if (path != null) {
fileChooser.setSelectedFile(new File(path));
}
int choice = fileChooser.showSaveDialog((Component) e.getSource());
if (choice == JFileChooser.APPROVE_OPTION) {
@ -74,7 +75,18 @@ public class ExportToImageAction extends AbstractAction {
chosenFile = new File(chosenFile.getParent(), chosenFile.getName() + '.' + extension);
}
try {
ImageIO.write(this.renderModel(), extension, chosenFile);
long start = System.currentTimeMillis();
BufferedImage render = this.renderModel();
double durationSeconds = (System.currentTimeMillis() - start) / 1000.0;
ImageIO.write(render, extension, chosenFile);
prefs.put(LAST_EXPORT_LOCATION_KEY, chosenFile.getAbsolutePath());
JOptionPane.showMessageDialog(
fileChooser,
"Image export completed in " + String.format("%.4f", durationSeconds) + " seconds.\n" +
"Resolution: " + render.getWidth() + "x" + render.getHeight(),
"Image Export Complete",
JOptionPane.INFORMATION_MESSAGE
);
} catch (IOException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(fileChooser, "An error occurred and the file could not be saved:\n" + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
@ -83,23 +95,30 @@ public class ExportToImageAction extends AbstractAction {
}
private BufferedImage renderModel() {
// Prepare a tiny sample image that we can use to determine the bounds of the model in a graphics context.
BufferedImage bufferedImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bufferedImage.createGraphics();
DiagramPanel.prepareGraphics(g2d);
final Rectangle bounds = this.model.getViewModel().getBounds(g2d);
// Prepare the output image.
BufferedImage outputImage = new BufferedImage(bounds.width, bounds.height + 20, BufferedImage.TYPE_INT_RGB);
g2d = outputImage.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(outputImage.getMinX(), outputImage.getMinY(), outputImage.getWidth(), outputImage.getHeight());
// Transform the graphics space to account for the model's offset from origin.
AffineTransform originalTransform = g2d.getTransform();
g2d.setTransform(AffineTransform.getTranslateInstance(-bounds.x, -bounds.y));
DiagramPanel.prepareGraphics(g2d);
// Render the model.
List<Relation> selectedRelations = this.model.getSelectedRelations();
this.model.getSelectedRelations().forEach(r -> r.setSelected(false));
new MappingModelViewModel(this.model).draw(g2d);
this.model.getRelations().forEach(r -> r.setSelected(selectedRelations.contains(r)));
// Revert back to the normal image space, and render a watermark.
g2d.setTransform(originalTransform);
g2d.setColor(Color.LIGHT_GRAY);
g2d.setFont(g2d.getFont().deriveFont(10.0f));

View File

@ -12,10 +12,16 @@ import java.net.URISyntaxException;
public abstract class HtmlDocumentViewerAction extends AbstractAction {
private final String resourceFileName;
private final Dialog.ModalityType modalityType;
public HtmlDocumentViewerAction(String name, String resourceFileName) {
this(name, resourceFileName, Dialog.ModalityType.APPLICATION_MODAL);
}
public HtmlDocumentViewerAction(String name, String resourceFileName, Dialog.ModalityType modalityType) {
super(name);
this.resourceFileName = resourceFileName;
this.modalityType = modalityType;
}
@Override
@ -23,7 +29,7 @@ public abstract class HtmlDocumentViewerAction extends AbstractAction {
JDialog dialog = new JDialog(
SwingUtilities.getWindowAncestor((Component) e.getSource()),
(String) this.getValue(NAME),
Dialog.ModalityType.APPLICATION_MODAL
this.modalityType
);
JTextPane textPane = new JTextPane();
textPane.setEditable(false);

View File

@ -14,10 +14,12 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.prefs.Preferences;
public class LoadAction extends AbstractAction {
private static LoadAction instance;
private static final String LAST_LOAD_LOCATION_KEY = "lastLoadLocation";
private static LoadAction instance;
public static LoadAction getInstance() {
if (instance == null) {
instance = new LoadAction();
@ -25,8 +27,6 @@ public class LoadAction extends AbstractAction {
return instance;
}
private File lastSelectedFile;
@Setter
private DiagramPanel diagramPanel;
@ -38,14 +38,16 @@ public class LoadAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fileChooser = new JFileChooser(this.lastSelectedFile);
JFileChooser fileChooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter(
"ERME Serialized Files",
"erme"
);
fileChooser.setFileFilter(filter);
if (this.lastSelectedFile != null) {
fileChooser.setSelectedFile(this.lastSelectedFile);
Preferences prefs = Preferences.userNodeForPackage(LoadAction.class);
String path = prefs.get(LAST_LOAD_LOCATION_KEY, null);
if (path != null) {
fileChooser.setSelectedFile(new File(path));
}
int choice = fileChooser.showOpenDialog((Component) e.getSource());
if (choice == JFileChooser.APPROVE_OPTION) {
@ -56,8 +58,8 @@ public class LoadAction extends AbstractAction {
}
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(chosenFile))) {
MappingModel loadedModel = (MappingModel) ois.readObject();
this.lastSelectedFile = chosenFile;
this.diagramPanel.setModel(loadedModel);
prefs.put(LAST_LOAD_LOCATION_KEY, chosenFile.getAbsolutePath());
} catch (IOException | ClassNotFoundException | ClassCastException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(fileChooser, "An error occurred and the file could not be read:\n" + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);

View File

@ -1,5 +1,7 @@
package nl.andrewlalis.erme.control.actions;
import java.awt.*;
public class MappingAlgorithmHelpAction extends HtmlDocumentViewerAction {
private static MappingAlgorithmHelpAction instance;
@ -11,7 +13,7 @@ public class MappingAlgorithmHelpAction extends HtmlDocumentViewerAction {
}
public MappingAlgorithmHelpAction() {
super("Mapping Algorithm Help", "html/er_mapping_algorithm.html");
super("Mapping Algorithm Help", "html/er_mapping_algorithm.html", Dialog.ModalityType.DOCUMENT_MODAL);
this.putValue(SHORT_DESCRIPTION, "Shows a quick guide on how to map from an ER model to a schema.");
}
}

View File

@ -9,11 +9,16 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.prefs.Preferences;
public class SaveAction extends AbstractAction {
private static SaveAction instance;
private static final String LAST_SAVE_LOCATION_KEY = "lastSaveLocation";
private static SaveAction instance;
public static SaveAction getInstance() {
if (instance == null) {
instance = new SaveAction();
@ -21,8 +26,6 @@ public class SaveAction extends AbstractAction {
return instance;
}
private File lastSelectedFile;
@Setter
private MappingModel model;
@ -34,14 +37,16 @@ public class SaveAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fileChooser = new JFileChooser(this.lastSelectedFile);
JFileChooser fileChooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter(
"ERME Serialized Files",
"erme"
);
fileChooser.setFileFilter(filter);
if (this.lastSelectedFile != null) {
fileChooser.setSelectedFile(this.lastSelectedFile);
Preferences prefs = Preferences.userNodeForPackage(SaveAction.class);
String path = prefs.get(LAST_SAVE_LOCATION_KEY, null);
if (path != null) {
fileChooser.setSelectedFile(new File(path));
}
int choice = fileChooser.showSaveDialog((Component) e.getSource());
if (choice == JFileChooser.APPROVE_OPTION) {
@ -56,7 +61,7 @@ public class SaveAction extends AbstractAction {
// TODO: Check for confirm before overwriting.
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(chosenFile))) {
oos.writeObject(this.model);
this.lastSelectedFile = chosenFile;
prefs.put(LAST_SAVE_LOCATION_KEY, chosenFile.getAbsolutePath());
JOptionPane.showMessageDialog(fileChooser, "File saved successfully.", "Success", JOptionPane.INFORMATION_MESSAGE);
} catch (IOException ex) {
ex.printStackTrace();