diff --git a/src/main/java/de/neemann/digital/core/element/ElementAttributes.java b/src/main/java/de/neemann/digital/core/element/ElementAttributes.java index d9e606e51..c77a1128d 100644 --- a/src/main/java/de/neemann/digital/core/element/ElementAttributes.java +++ b/src/main/java/de/neemann/digital/core/element/ElementAttributes.java @@ -216,9 +216,15 @@ public class ElementAttributes { * @param file the file */ public void setFile(String fileKey, File file) { - if (attributes == null) - attributes = new HashMap<>(); - attributes.put(fileKey, file.getPath()); + if (file == null) { + if (attributes != null) + attributes.remove(fileKey); + } else if (!file.equals(getFile(fileKey))) { + if (attributes == null) + attributes = new HashMap<>(); + attributes.put(fileKey, file.getPath()); + fireValueChanged(); + } } /** diff --git a/src/main/java/de/neemann/digital/gui/Main.java b/src/main/java/de/neemann/digital/gui/Main.java index 3e144c310..eadd46e66 100644 --- a/src/main/java/de/neemann/digital/gui/Main.java +++ b/src/main/java/de/neemann/digital/gui/Main.java @@ -76,8 +76,6 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS private static final String KEY_START_STOP_ACTION = "startStop"; private static boolean experimental; - private static File lastExportDirectory; - /** * @return true if experimental features are enabled */ @@ -1205,13 +1203,15 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS if (filename != null) fc.setSelectedFile(SaveAsHelper.checkSuffix(filename, suffix)); - if (lastExportDirectory != null) - fc.setCurrentDirectory(lastExportDirectory); + ElementAttributes settings = Settings.getInstance().getAttributes(); + File exportDir = settings.getFile("exportDirectory"); + if (exportDir != null) + fc.setCurrentDirectory(exportDir); fc.addChoosableFileFilter(new FileNameExtensionFilter(name, suffix)); new SaveAsHelper(Main.this, fc, suffix).checkOverwrite( file -> { - lastExportDirectory = file.getParentFile(); + settings.setFile("exportDirectory", file.getParentFile()); try (OutputStream out = new FileOutputStream(file)) { new Export(circuitComponent.getCircuit(), exportFactory).export(out); } @@ -1234,13 +1234,15 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS if (filename != null) fc.setSelectedFile(SaveAsHelper.checkSuffix(filename, "gif")); - if (lastExportDirectory != null) - fc.setCurrentDirectory(lastExportDirectory); + ElementAttributes settings = Settings.getInstance().getAttributes(); + File exportDir = settings.getFile("exportDirectory"); + if (exportDir != null) + fc.setCurrentDirectory(exportDir); fc.addChoosableFileFilter(new FileNameExtensionFilter(name, "gif")); new SaveAsHelper(Main.this, fc, "gif").checkOverwrite( file -> { - lastExportDirectory = file.getParentFile(); + settings.setFile("exportDirectory", file.getParentFile()); GifExporter gifExporter = new GifExporter(Main.this, circuitComponent.getCircuit(), 500, file); setDebug(false); windowPosManager.closeAll(); diff --git a/src/main/java/de/neemann/digital/gui/components/data/GraphComponent.java b/src/main/java/de/neemann/digital/gui/components/data/GraphComponent.java index 80c9ae8b9..e846bc8c4 100644 --- a/src/main/java/de/neemann/digital/gui/components/data/GraphComponent.java +++ b/src/main/java/de/neemann/digital/gui/components/data/GraphComponent.java @@ -87,4 +87,11 @@ public class GraphComponent extends JComponent { public void setScrollPane(JScrollPane scrollPane) { this.scrollPane = scrollPane; } + + /** + * @return the data plotter + */ + public DataPlotter getPlotter() { + return plotter; + } } diff --git a/src/main/java/de/neemann/digital/gui/components/data/GraphDialog.java b/src/main/java/de/neemann/digital/gui/components/data/GraphDialog.java index f365edd9d..37148d6af 100644 --- a/src/main/java/de/neemann/digital/gui/components/data/GraphDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/data/GraphDialog.java @@ -1,8 +1,11 @@ package de.neemann.digital.gui.components.data; import de.neemann.digital.core.*; +import de.neemann.digital.core.element.ElementAttributes; import de.neemann.digital.data.ValueTable; +import de.neemann.digital.draw.graphics.*; import de.neemann.digital.gui.SaveAsHelper; +import de.neemann.digital.gui.Settings; import de.neemann.digital.gui.components.OrderMerger; import de.neemann.digital.gui.components.testing.ValueTableDialog; import de.neemann.digital.gui.sync.NoSync; @@ -18,6 +21,7 @@ import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.io.*; import java.util.ArrayList; import java.util.List; @@ -163,6 +167,8 @@ public class GraphDialog extends JDialog implements Observer { .checkOverwrite(logData::saveCSV); } }.setToolTip(Lang.get("menu_saveData_tt")).createJMenuItem()); + file.add(new ExportAction(Lang.get("menu_exportSVG"), GraphicSVGIndex::new).createJMenuItem()); + file.add(new ExportAction(Lang.get("menu_exportSVGLaTex"), GraphicSVGLaTeX::new).createJMenuItem()); JMenu view = new JMenu(Lang.get("menu_view")); bar.add(view); @@ -198,4 +204,41 @@ public class GraphDialog extends JDialog implements Observer { showTable.setActive(false); return this; } + + private final class ExportAction extends ToolTipAction { + private final ExportFactory factory; + + private ExportAction(String title, ExportFactory factory) { + super(title); + this.factory = factory; + } + + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser fileChooser = new MyFileChooser(); + + ElementAttributes settings = Settings.getInstance().getAttributes(); + File exportDir = settings.getFile("exportDirectory"); + if (exportDir != null) + fileChooser.setCurrentDirectory(exportDir); + + + fileChooser.setFileFilter(new FileNameExtensionFilter("SVG", "svg")); + new SaveAsHelper(GraphDialog.this, fileChooser, "svg") + .checkOverwrite(file -> { + settings.setFile("exportDirectory", file.getParentFile()); + Graphic gr = factory.create(new FileOutputStream(file)); + try { + GraphicMinMax minMax = new GraphicMinMax(); + dsc.getPlotter().drawTo(minMax, null); + gr.setBoundingBox(minMax.getMin(), minMax.getMax()); + dsc.getPlotter().drawTo(gr, null); + } finally { + if (gr instanceof Closeable) + ((Closeable) gr).close(); + } + }); + } + + } }