diff --git a/src/main/java/de/neemann/digital/gui/components/data/DataSample.java b/src/main/java/de/neemann/digital/gui/components/data/DataSample.java index b03963bb5..55b8cdf15 100644 --- a/src/main/java/de/neemann/digital/gui/components/data/DataSample.java +++ b/src/main/java/de/neemann/digital/gui/components/data/DataSample.java @@ -2,6 +2,8 @@ package de.neemann.digital.gui.components.data; import de.neemann.digital.core.Model; +import java.io.BufferedWriter; +import java.io.IOException; import java.util.ArrayList; /** @@ -74,4 +76,16 @@ public class DataSample { values[i] = signals.get(i).getValue().getValueIgnoreBurn(); return this; } + + /** + * Write this sample as a single CSV line + * + * @param w the writer + * @throws IOException IOException + */ + public void writeTo(BufferedWriter w) throws IOException { + w.write("\"" + timeStamp + "\""); + for (int i = 0; i < values.length; i++) + w.write(",\"" + values[i] + "\""); + } } diff --git a/src/main/java/de/neemann/digital/gui/components/data/DataSet.java b/src/main/java/de/neemann/digital/gui/components/data/DataSet.java index f59e386b9..4943c8322 100644 --- a/src/main/java/de/neemann/digital/gui/components/data/DataSet.java +++ b/src/main/java/de/neemann/digital/gui/components/data/DataSet.java @@ -7,6 +7,7 @@ import de.neemann.digital.draw.graphics.Style; import de.neemann.digital.draw.graphics.Vector; import de.neemann.digital.draw.shapes.Drawable; +import java.io.*; import java.util.ArrayList; import java.util.Iterator; @@ -192,16 +193,43 @@ public class DataSet implements Iterable, Drawable { return maxTextLength * Style.NORMAL.getFontSize() / 2 + BORDER + SEP; } + /** + * @return the preferred width of the graphical representation + */ public int getGraphicWidth() { return getTextBorder() + size() * SIZE; } + /** + * @return the preferred height of the graphical representation + */ public int getGraphicHeight() { return signalSize() * (SIZE + SEP) + 2 * BORDER; } + /** + * @return the signals stored + */ public ArrayList getSignals() { return signals; } + /** + * Stores the data in csv file + * + * @param file the file + * @throws IOException IOException + */ + public void saveCSV(File file) throws IOException { + try (BufferedWriter w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"))) { + w.write("\"step\""); + for (Model.Signal s : signals) + w.write(",\"" + s.getName() + '"'); + w.newLine(); + for (DataSample s : samples) { + s.writeTo(w); + w.newLine(); + } + } + } } diff --git a/src/main/java/de/neemann/digital/gui/components/data/DataSetDialog.java b/src/main/java/de/neemann/digital/gui/components/data/DataSetDialog.java index c7dea4120..4dca97c7c 100644 --- a/src/main/java/de/neemann/digital/gui/components/data/DataSetDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/data/DataSetDialog.java @@ -5,11 +5,17 @@ import de.neemann.digital.core.ModelEvent; import de.neemann.digital.core.ModelStateObserver; import de.neemann.digital.gui.components.OrderMerger; import de.neemann.digital.lang.Lang; +import de.neemann.gui.ErrorMessage; +import de.neemann.gui.ToolTipAction; import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.*; +import java.awt.event.ActionEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -30,7 +36,7 @@ public class DataSetDialog extends JDialog implements ModelStateObserver { * @param owner the parent frame * @param model the model used to collect the data * @param type the event type which triggers a new DataSample - * @param ordering + * @param ordering the ordering of the measurement values */ public DataSetDialog(Frame owner, Model model, ModelEvent type, List ordering) { super(owner, Lang.get("win_measures"), false); @@ -67,6 +73,28 @@ public class DataSetDialog extends JDialog implements ModelStateObserver { scrollPane.getViewport().setPreferredSize(dsc.getPreferredSize()); + JMenuBar bar = new JMenuBar(); + JMenu file = new JMenu(Lang.get("menu_file")); + bar.add(file); + file.add(new ToolTipAction(Lang.get("menu_saveData")) { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileFilter(new FileNameExtensionFilter("Comma Separated Values", "csv")); + if (fileChooser.showSaveDialog(DataSetDialog.this) == JFileChooser.APPROVE_OPTION) { + File file = fileChooser.getSelectedFile(); + if (!file.getName().endsWith(".csv")) + file = new File(file.getParentFile(), file.getName() + ".csv"); + try { + dataSet.saveCSV(file); + } catch (IOException e1) { + new ErrorMessage(Lang.get("msg_errorSavingData")).addCause(e1).show(DataSetDialog.this); + } + } + } + }.setToolTip(Lang.get("menu_saveData_tt")).createJMenuItem()); + setJMenuBar(bar); + pack(); setLocationRelativeTo(owner); } diff --git a/src/main/resources/lang/lang_de.properties b/src/main/resources/lang/lang_de.properties index 988403eba..f2b48e13d 100644 --- a/src/main/resources/lang/lang_de.properties +++ b/src/main/resources/lang/lang_de.properties @@ -203,6 +203,8 @@ menu_delete=L\u00F6schen menu_delete_tt=L\u00F6scht ausgew\u00E4hlte Elemente menu_editRunAttributes=Simulationseinstellungen menu_editRunAttributes_tt=Einstellungen f\u00FCr den Start der Simulation +menu_saveData=Daten speichern +menu_saveData_tt=Speichert die Daten als CSV Datei menu_about=\u00DCber Digital diff --git a/src/main/resources/lang/lang_en.properties b/src/main/resources/lang/lang_en.properties index 9ba6be87e..d2c9e2109 100644 --- a/src/main/resources/lang/lang_en.properties +++ b/src/main/resources/lang/lang_en.properties @@ -203,6 +203,8 @@ menu_delete=Delete elements menu_delete_tt=Delete selected single element or group of elements menu_editRunAttributes=Simulation Settings menu_editRunAttributes_tt=Settings used to start the simulation +menu_saveData=Save Data +menu_saveData_tt=Save data as CSV file win_saveChanges=Save Changes? win_confirmExit=Confirm Exit!