in csv export the selected number format is preserved, see #349

This commit is contained in:
hneemann 2019-09-27 14:46:19 +02:00
parent 957aea4a24
commit 8718bb9a65
4 changed files with 99 additions and 4 deletions

View File

@ -182,6 +182,13 @@ public final class Signal implements Comparable<Signal> {
return bidirectionalReader;
}
/**
* @return the format to be used to visualize the signal values
*/
public IntFormat getFormat() {
return format;
}
/**
* Setter interface to set a value
*/

View File

@ -5,10 +5,12 @@
*/
package de.neemann.digital.data;
import de.neemann.digital.core.IntFormat;
import de.neemann.digital.core.Observable;
import de.neemann.digital.testing.parser.TestRow;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
@ -198,7 +200,18 @@ public class ValueTable extends Observable implements Iterable<TestRow> {
* @throws IOException IOException
*/
public void saveCSV(File file) throws IOException {
saveCSV(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8")));
saveCSV(file, null);
}
/**
* Stores the data in csv file
*
* @param file the file
* @param columnInfo information of how to format the values, maybe null
* @throws IOException IOException
*/
public void saveCSV(File file, ColumnInfo[] columnInfo) throws IOException {
saveCSV(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)), columnInfo);
}
/**
@ -208,6 +221,10 @@ public class ValueTable extends Observable implements Iterable<TestRow> {
* @throws IOException IOException
*/
public void saveCSV(BufferedWriter w) throws IOException {
saveCSV(w, null);
}
void saveCSV(BufferedWriter w, ColumnInfo[] columnInfo) throws IOException {
try {
w.write("\"step\"");
for (String s : names)
@ -216,7 +233,14 @@ public class ValueTable extends Observable implements Iterable<TestRow> {
int row = 0;
for (TestRow s : this) {
w.write("\"" + (row++) + "\"");
for (Value value : s.getValues()) w.write(",\"" + value + "\"");
if (columnInfo == null) {
for (Value value : s.getValues())
w.write(",\"" + value + "\"");
} else {
int i = 0;
for (Value value : s.getValues())
w.write(",\"" + columnInfo[i++].format(value) + "\"");
}
w.write("\n");
}
} finally {
@ -266,4 +290,36 @@ public class ValueTable extends Observable implements Iterable<TestRow> {
return sb.toString();
}
/**
* Columns formatting information
*/
public static final class ColumnInfo {
private int bits;
private IntFormat format;
/**
* Creates a new instance
*
* @param format the format to use
* @param bits the number of bits to output
*/
public ColumnInfo(IntFormat format, int bits) {
this.format = format;
this.bits = bits;
}
private String format(Value value) {
switch (value.getType()) {
case HIGHZ:
return "Z";
case DONTCARE:
return "X";
case CLOCK:
return "C";
default:
return format.formatToEdit(new de.neemann.digital.core.Value(value.getValue(), bits));
}
}
}
}

View File

@ -41,6 +41,8 @@ public class GraphDialog extends JDialog implements Observer {
private static final Icon ICON_ZOOM_IN = IconCreator.create("View-zoom-in.png");
private static final Icon ICON_ZOOM_OUT = IconCreator.create("View-zoom-out.png");
private ValueTable.ColumnInfo[] columnInfo;
/**
* Creates a instance prepared for "live logging"
*
@ -66,9 +68,11 @@ public class GraphDialog extends JDialog implements Observer {
}
}.order(signals);
ValueTableObserver valueTableObserver = new ValueTableObserver(microStep, signals, MAX_SAMPLE_SIZE);
GraphDialog graphDialog = new GraphDialog(owner, title, valueTableObserver.getLogData(), model);
GraphDialog graphDialog = new GraphDialog(owner, title, valueTableObserver.getLogData(), model)
.setColumnInfo(createColumnsInfo(signals));
graphDialog.addWindowListener(new WindowAdapter() {
@Override
@ -85,6 +89,15 @@ public class GraphDialog extends JDialog implements Observer {
return graphDialog;
}
private static ValueTable.ColumnInfo[] createColumnsInfo(ArrayList<Signal> signals) {
ValueTable.ColumnInfo[] info = new ValueTable.ColumnInfo[signals.size()];
for (int i = 0; i < signals.size(); i++) {
Signal s = signals.get(i);
info[i] = new ValueTable.ColumnInfo(s.getFormat(), s.getValue().getBits());
}
return info;
}
/**
* Creates a new instance
*
@ -163,7 +176,7 @@ public class GraphDialog extends JDialog implements Observer {
JFileChooser fileChooser = new MyFileChooser();
fileChooser.setFileFilter(new FileNameExtensionFilter("Comma Separated Values", "csv"));
new SaveAsHelper(GraphDialog.this, fileChooser, "csv")
.checkOverwrite(logData::saveCSV);
.checkOverwrite(file -> logData.saveCSV(file, columnInfo));
}
}.setToolTip(Lang.get("menu_saveData_tt")).createJMenuItem());
file.add(new ExportAction(Lang.get("menu_exportSVG"), GraphicSVG::new).createJMenuItem());
@ -181,6 +194,11 @@ public class GraphDialog extends JDialog implements Observer {
setLocationRelativeTo(owner);
}
private GraphDialog setColumnInfo(ValueTable.ColumnInfo[] columnInfo) {
this.columnInfo = columnInfo;
return this;
}
private final AtomicBoolean paintPending = new AtomicBoolean();
@Override

View File

@ -5,6 +5,7 @@
*/
package de.neemann.digital.data;
import de.neemann.digital.core.IntFormat;
import de.neemann.digital.testing.parser.TestRow;
import junit.framework.TestCase;
@ -40,6 +41,19 @@ public class ValueTableTest extends TestCase {
"\"1\",\"0\",\"1\",\"Z\"\n", sw.toString());
}
public void testCSV2() throws Exception {
StringWriter sw = new StringWriter();
ValueTable.ColumnInfo[] infos = new ValueTable.ColumnInfo[]{
new ValueTable.ColumnInfo(IntFormat.hex, 4),
new ValueTable.ColumnInfo(IntFormat.oct, 4),
new ValueTable.ColumnInfo(IntFormat.bin, 4),
};
t.saveCSV(new BufferedWriter(sw), infos);
assertEquals("\"step\",\"A\",\"B\",\"C\"\n" +
"\"0\",\"0x0\",\"000\",\"0b0000\"\n" +
"\"1\",\"0x0\",\"001\",\"Z\"\n", sw.toString());
}
public void testMax() {
ValueTable t = new ValueTable("A", "B", "C")
.add(new TestRow(new Value(0), new Value(4), new Value(1)))