mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-28 07:28:20 -04:00
test result dialog data is able to show the data as a graph.
This commit is contained in:
parent
2d25909f9e
commit
4cb80b3918
@ -5,6 +5,8 @@ import de.neemann.digital.draw.graphics.Orientation;
|
|||||||
import de.neemann.digital.draw.graphics.Style;
|
import de.neemann.digital.draw.graphics.Style;
|
||||||
import de.neemann.digital.draw.graphics.Vector;
|
import de.neemann.digital.draw.graphics.Vector;
|
||||||
import de.neemann.digital.draw.shapes.Drawable;
|
import de.neemann.digital.draw.shapes.Drawable;
|
||||||
|
import de.neemann.digital.gui.sync.NoSync;
|
||||||
|
import de.neemann.digital.gui.sync.Sync;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The dataSet stores the collected DataSamples.
|
* The dataSet stores the collected DataSamples.
|
||||||
@ -16,6 +18,7 @@ public class DataPlotter implements Drawable {
|
|||||||
private final ValueTable data;
|
private final ValueTable data;
|
||||||
private final int maxTextLength;
|
private final int maxTextLength;
|
||||||
private double size = SIZE;
|
private double size = SIZE;
|
||||||
|
private Sync modelSync = NoSync.INST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
@ -44,7 +47,7 @@ public class DataPlotter implements Drawable {
|
|||||||
* @param width width of the frame
|
* @param width width of the frame
|
||||||
*/
|
*/
|
||||||
public void fitInside(int width) {
|
public void fitInside(int width) {
|
||||||
size = ((double) (width - getTextBorder())) / data.getRows();
|
modelSync.access(() -> size = ((double) (width - getTextBorder())) / data.getRows());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,43 +66,45 @@ public class DataPlotter implements Drawable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawTo(Graphic g, Style highLight) {
|
public void drawTo(Graphic g, Style highLight) {
|
||||||
int x = getTextBorder();
|
modelSync.access(() -> {
|
||||||
|
int x = getTextBorder();
|
||||||
|
|
||||||
int yOffs = SIZE / 2;
|
int yOffs = SIZE / 2;
|
||||||
int y = BORDER;
|
int y = BORDER;
|
||||||
int signals = data.getColumns();
|
int signals = data.getColumns();
|
||||||
for (int i = 0; i < signals; i++) {
|
|
||||||
String text = data.getColumnName(i);
|
|
||||||
g.drawText(new Vector(x - 2, y + yOffs), new Vector(x + 1, y + yOffs), text, Orientation.RIGHTCENTER, Style.NORMAL);
|
|
||||||
g.drawLine(new Vector(x, y - SEP2), new Vector(x + (int) (size * data.getRows()), y - SEP2), Style.DASH);
|
|
||||||
y += SIZE + SEP;
|
|
||||||
}
|
|
||||||
g.drawLine(new Vector(x, y - SEP2), new Vector(x + (int) (size * data.getRows()), y - SEP2), Style.DASH);
|
|
||||||
|
|
||||||
|
|
||||||
int[] lastRy = new int[signals];
|
|
||||||
boolean first = true;
|
|
||||||
double pos = 0;
|
|
||||||
for (Value[] s : data) {
|
|
||||||
int xx = (int) (pos + x);
|
|
||||||
g.drawLine(new Vector(xx, BORDER - SEP2), new Vector(xx, (SIZE + SEP) * signals + BORDER - SEP2), Style.DASH);
|
|
||||||
y = BORDER;
|
|
||||||
for (int i = 0; i < signals; i++) {
|
for (int i = 0; i < signals; i++) {
|
||||||
|
String text = data.getColumnName(i);
|
||||||
long width = data.getMax(i);
|
g.drawText(new Vector(x - 2, y + yOffs), new Vector(x + 1, y + yOffs), text, Orientation.RIGHTCENTER, Style.NORMAL);
|
||||||
if (width == 0) width = 1;
|
g.drawLine(new Vector(x, y - SEP2), new Vector(x + (int) (size * data.getRows()), y - SEP2), Style.DASH);
|
||||||
int ry = (int) (SIZE - (SIZE * s[i].getValue()) / width);
|
|
||||||
g.drawLine(new Vector(xx, y + ry), new Vector((int) (xx + size), y + ry), Style.NORMAL);
|
|
||||||
if (!first && ry != lastRy[i])
|
|
||||||
g.drawLine(new Vector(xx, y + lastRy[i]), new Vector(xx, y + ry), Style.NORMAL);
|
|
||||||
|
|
||||||
lastRy[i] = ry;
|
|
||||||
y += SIZE + SEP;
|
y += SIZE + SEP;
|
||||||
}
|
}
|
||||||
first = false;
|
g.drawLine(new Vector(x, y - SEP2), new Vector(x + (int) (size * data.getRows()), y - SEP2), Style.DASH);
|
||||||
pos += size;
|
|
||||||
}
|
|
||||||
g.drawLine(new Vector(x, BORDER - SEP2), new Vector(x, (SIZE + SEP) * signals + BORDER - SEP2), Style.DASH);
|
int[] lastRy = new int[signals];
|
||||||
|
boolean first = true;
|
||||||
|
double pos = 0;
|
||||||
|
for (Value[] s : data) {
|
||||||
|
int xx = (int) (pos + x);
|
||||||
|
g.drawLine(new Vector(xx, BORDER - SEP2), new Vector(xx, (SIZE + SEP) * signals + BORDER - SEP2), Style.DASH);
|
||||||
|
y = BORDER;
|
||||||
|
for (int i = 0; i < signals; i++) {
|
||||||
|
|
||||||
|
long width = data.getMax(i);
|
||||||
|
if (width == 0) width = 1;
|
||||||
|
int ry = (int) (SIZE - (SIZE * s[i].getValue()) / width);
|
||||||
|
g.drawLine(new Vector(xx, y + ry), new Vector((int) (xx + size), y + ry), Style.NORMAL);
|
||||||
|
if (!first && ry != lastRy[i])
|
||||||
|
g.drawLine(new Vector(xx, y + lastRy[i]), new Vector(xx, y + ry), Style.NORMAL);
|
||||||
|
|
||||||
|
lastRy[i] = ry;
|
||||||
|
y += SIZE + SEP;
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
pos += size;
|
||||||
|
}
|
||||||
|
g.drawLine(new Vector(x, BORDER - SEP2), new Vector(x, (SIZE + SEP) * signals + BORDER - SEP2), Style.DASH);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getTextBorder() {
|
private int getTextBorder() {
|
||||||
@ -117,7 +122,24 @@ public class DataPlotter implements Drawable {
|
|||||||
* @return the current width of the graphical representation
|
* @return the current width of the graphical representation
|
||||||
*/
|
*/
|
||||||
public int getCurrentGraphicWidth() {
|
public int getCurrentGraphicWidth() {
|
||||||
return getTextBorder() + (int) (data.getRows() * size);
|
return modelSync.access(new Runnable() {
|
||||||
|
private int r;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
r = DataPlotter.this.getTextBorder() + (int) (data.getRows() * size);
|
||||||
|
}
|
||||||
|
}).r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets lock to access the data
|
||||||
|
*
|
||||||
|
* @param modelSync the lock
|
||||||
|
* @return this for chained calls
|
||||||
|
*/
|
||||||
|
public DataPlotter setModelSync(Sync modelSync) {
|
||||||
|
this.modelSync = modelSync;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1003,9 +1003,9 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
|
|||||||
windowPosManager.register("probe", new ProbeDialog(this, model, updateEvent, ordering, modelSync)).setVisible(true);
|
windowPosManager.register("probe", new ProbeDialog(this, model, updateEvent, ordering, modelSync)).setVisible(true);
|
||||||
|
|
||||||
if (settings.get(Keys.SHOW_DATA_GRAPH))
|
if (settings.get(Keys.SHOW_DATA_GRAPH))
|
||||||
windowPosManager.register("dataSet", new DataSetDialog(this, model, updateEvent == ModelEvent.MICROSTEP, ordering, modelSync)).setVisible(true);
|
windowPosManager.register("dataSet", DataSetDialog.createLiveDialog(this, model, updateEvent == ModelEvent.MICROSTEP, ordering, modelSync)).setVisible(true);
|
||||||
if (settings.get(Keys.SHOW_DATA_GRAPH_MICRO))
|
if (settings.get(Keys.SHOW_DATA_GRAPH_MICRO))
|
||||||
windowPosManager.register("dataSetMicro", new DataSetDialog(this, model, true, ordering, modelSync)).setVisible(true);
|
windowPosManager.register("dataSetMicro", DataSetDialog.createLiveDialog(this, model, true, ordering, modelSync)).setVisible(true);
|
||||||
|
|
||||||
if (modelModifier != null)
|
if (modelModifier != null)
|
||||||
modelModifier.preInit(model);
|
modelModifier.preInit(model);
|
||||||
|
@ -3,6 +3,7 @@ package de.neemann.digital.gui.components.data;
|
|||||||
import de.neemann.digital.data.DataPlotter;
|
import de.neemann.digital.data.DataPlotter;
|
||||||
import de.neemann.digital.data.ValueTable;
|
import de.neemann.digital.data.ValueTable;
|
||||||
import de.neemann.digital.draw.graphics.GraphicSwing;
|
import de.neemann.digital.draw.graphics.GraphicSwing;
|
||||||
|
import de.neemann.digital.gui.sync.Sync;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@ -15,15 +16,20 @@ import java.awt.*;
|
|||||||
*/
|
*/
|
||||||
public class DataSetComponent extends JComponent {
|
public class DataSetComponent extends JComponent {
|
||||||
private final DataPlotter plotter;
|
private final DataPlotter plotter;
|
||||||
|
/**
|
||||||
|
* The data stored in the plotter needs to be seen as part of the model.
|
||||||
|
* So a lock is necessary to access the data.
|
||||||
|
*/
|
||||||
private JScrollPane scrollPane;
|
private JScrollPane scrollPane;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new dataSet
|
* Creates a new dataSet
|
||||||
*
|
*
|
||||||
* @param dataSet the dataSet to paint
|
* @param dataSet the dataSet to paint
|
||||||
|
* @param modelSync lock to access the model
|
||||||
*/
|
*/
|
||||||
public DataSetComponent(ValueTable dataSet) {
|
public DataSetComponent(ValueTable dataSet, Sync modelSync) {
|
||||||
plotter = new DataPlotter(dataSet);
|
plotter = new DataPlotter(dataSet).setModelSync(modelSync);
|
||||||
addMouseWheelListener(e -> {
|
addMouseWheelListener(e -> {
|
||||||
double f = Math.pow(0.9, e.getWheelRotation());
|
double f = Math.pow(0.9, e.getWheelRotation());
|
||||||
scale(f, e.getX());
|
scale(f, e.getX());
|
||||||
@ -55,8 +61,8 @@ public class DataSetComponent extends JComponent {
|
|||||||
public void scale(double f, int xPos) {
|
public void scale(double f, int xPos) {
|
||||||
revalidate();
|
revalidate();
|
||||||
repaint();
|
repaint();
|
||||||
f=plotter.scale(f);
|
f = plotter.scale(f);
|
||||||
|
// keep relative mouse position
|
||||||
int x = (int) (xPos * f) - (xPos - (int) scrollPane.getViewport().getViewRect().getX());
|
int x = (int) (xPos * f) - (xPos - (int) scrollPane.getViewport().getViewRect().getX());
|
||||||
if (x < 0) x = 0;
|
if (x < 0) x = 0;
|
||||||
scrollPane.getViewport().setViewPosition(new Point(x, 0));
|
scrollPane.getViewport().setViewPosition(new Point(x, 0));
|
||||||
|
@ -7,6 +7,7 @@ import de.neemann.digital.core.Signal;
|
|||||||
import de.neemann.digital.data.ValueTable;
|
import de.neemann.digital.data.ValueTable;
|
||||||
import de.neemann.digital.gui.SaveAsHelper;
|
import de.neemann.digital.gui.SaveAsHelper;
|
||||||
import de.neemann.digital.gui.components.OrderMerger;
|
import de.neemann.digital.gui.components.OrderMerger;
|
||||||
|
import de.neemann.digital.gui.sync.NoSync;
|
||||||
import de.neemann.digital.gui.sync.Sync;
|
import de.neemann.digital.gui.sync.Sync;
|
||||||
import de.neemann.digital.lang.Lang;
|
import de.neemann.digital.lang.Lang;
|
||||||
import de.neemann.gui.IconCreator;
|
import de.neemann.gui.IconCreator;
|
||||||
@ -32,27 +33,29 @@ public class DataSetDialog extends JDialog implements ModelStateObserver {
|
|||||||
private final DataSetComponent dsc;
|
private final DataSetComponent dsc;
|
||||||
private final JScrollPane scrollPane;
|
private final JScrollPane scrollPane;
|
||||||
private final Sync modelSync;
|
private final Sync modelSync;
|
||||||
private ValueTable logData;
|
|
||||||
private DataSetObserver dataSetObserver;
|
private DataSetObserver dataSetObserver;
|
||||||
|
|
||||||
private static final Icon ICON_EXPAND = IconCreator.create("View-zoom-fit.png");
|
private static final Icon ICON_EXPAND = IconCreator.create("View-zoom-fit.png");
|
||||||
private static final Icon ICON_ZOOM_IN = IconCreator.create("View-zoom-in.png");
|
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 static final Icon ICON_ZOOM_OUT = IconCreator.create("View-zoom-out.png");
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a instance prepared for "live logging"
|
||||||
*
|
*
|
||||||
* @param owner the parent frame
|
* @param owner the parent frame
|
||||||
* @param model the model used to collect the data
|
* @param model the model
|
||||||
* @param microStep true the event type which triggers a new DataSample
|
* @param microStep stepping mode
|
||||||
* @param ordering the ordering of the measurement values
|
* @param ordering the ordering to use
|
||||||
* @param modelSync used to access the running model
|
* @param modelSync the lock to access the model
|
||||||
|
* @return the created instance
|
||||||
*/
|
*/
|
||||||
public DataSetDialog(Frame owner, Model model, boolean microStep, List<String> ordering, Sync modelSync) {
|
public static DataSetDialog createLiveDialog(Frame owner, Model model, boolean microStep, List<String> ordering, Sync modelSync) {
|
||||||
super(owner, createTitle(microStep), false);
|
String title;
|
||||||
this.modelSync = modelSync;
|
if (microStep)
|
||||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
title = Lang.get("win_measures_microstep");
|
||||||
setAlwaysOnTop(true);
|
else
|
||||||
|
title = Lang.get("win_measures_fullstep");
|
||||||
|
|
||||||
ArrayList<Signal> signals = model.getSignalsCopy();
|
ArrayList<Signal> signals = model.getSignalsCopy();
|
||||||
new OrderMerger<String, Signal>(ordering) {
|
new OrderMerger<String, Signal>(ordering) {
|
||||||
@ -62,11 +65,40 @@ public class DataSetDialog extends JDialog implements ModelStateObserver {
|
|||||||
}
|
}
|
||||||
}.order(signals);
|
}.order(signals);
|
||||||
|
|
||||||
|
DataSetObserver dataSetObserver = new DataSetObserver(microStep, signals, MAX_SAMPLE_SIZE);
|
||||||
|
ValueTable logData = dataSetObserver.getLogData();
|
||||||
|
|
||||||
dataSetObserver = new DataSetObserver(microStep, signals, MAX_SAMPLE_SIZE);
|
return new DataSetDialog(owner, title, model, logData, dataSetObserver, modelSync);
|
||||||
logData = dataSetObserver.getLogData();
|
}
|
||||||
|
|
||||||
dsc = new DataSetComponent(logData);
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param owner the parent frame
|
||||||
|
* @param title the frame title
|
||||||
|
* @param logData the data to visualize
|
||||||
|
*/
|
||||||
|
public DataSetDialog(Frame owner, String title, ValueTable logData) {
|
||||||
|
this(owner, title, null, logData, null, NoSync.INST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param owner the parent frame
|
||||||
|
* @param title the frame title
|
||||||
|
* @param model the model used to collect the data
|
||||||
|
* @param logData the data to visualize
|
||||||
|
* @param modelSync used to access the running model
|
||||||
|
*/
|
||||||
|
private DataSetDialog(Frame owner, String title, Model model, ValueTable logData, DataSetObserver dataSetObserver, Sync modelSync) {
|
||||||
|
super(owner, title, false);
|
||||||
|
this.dataSetObserver = dataSetObserver;
|
||||||
|
this.modelSync = modelSync;
|
||||||
|
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||||
|
setAlwaysOnTop(true);
|
||||||
|
|
||||||
|
dsc = new DataSetComponent(logData, modelSync);
|
||||||
scrollPane = new JScrollPane(dsc);
|
scrollPane = new JScrollPane(dsc);
|
||||||
getContentPane().add(scrollPane);
|
getContentPane().add(scrollPane);
|
||||||
dsc.setScrollPane(scrollPane);
|
dsc.setScrollPane(scrollPane);
|
||||||
@ -100,17 +132,18 @@ public class DataSetDialog extends JDialog implements ModelStateObserver {
|
|||||||
getContentPane().add(toolBar, BorderLayout.NORTH);
|
getContentPane().add(toolBar, BorderLayout.NORTH);
|
||||||
pack();
|
pack();
|
||||||
|
|
||||||
addWindowListener(new WindowAdapter() {
|
if (model != null)
|
||||||
@Override
|
addWindowListener(new WindowAdapter() {
|
||||||
public void windowOpened(WindowEvent e) {
|
@Override
|
||||||
modelSync.access(() -> model.addObserver(DataSetDialog.this));
|
public void windowOpened(WindowEvent e) {
|
||||||
}
|
modelSync.access(() -> model.addObserver(DataSetDialog.this));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void windowClosed(WindowEvent e) {
|
public void windowClosed(WindowEvent e) {
|
||||||
modelSync.access(() -> model.removeObserver(DataSetDialog.this));
|
modelSync.access(() -> model.removeObserver(DataSetDialog.this));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
scrollPane.getViewport().setPreferredSize(dsc.getPreferredSize());
|
scrollPane.getViewport().setPreferredSize(dsc.getPreferredSize());
|
||||||
|
|
||||||
@ -123,7 +156,7 @@ public class DataSetDialog extends JDialog implements ModelStateObserver {
|
|||||||
JFileChooser fileChooser = new MyFileChooser();
|
JFileChooser fileChooser = new MyFileChooser();
|
||||||
fileChooser.setFileFilter(new FileNameExtensionFilter("Comma Separated Values", "csv"));
|
fileChooser.setFileFilter(new FileNameExtensionFilter("Comma Separated Values", "csv"));
|
||||||
new SaveAsHelper(DataSetDialog.this, fileChooser, "csv")
|
new SaveAsHelper(DataSetDialog.this, fileChooser, "csv")
|
||||||
.checkOverwrite(file -> logData.saveCSV(file));
|
.checkOverwrite(logData::saveCSV);
|
||||||
}
|
}
|
||||||
}.setToolTip(Lang.get("menu_saveData_tt")).createJMenuItem());
|
}.setToolTip(Lang.get("menu_saveData_tt")).createJMenuItem());
|
||||||
|
|
||||||
@ -138,14 +171,6 @@ public class DataSetDialog extends JDialog implements ModelStateObserver {
|
|||||||
setLocationRelativeTo(owner);
|
setLocationRelativeTo(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String createTitle(boolean microStep) {
|
|
||||||
if (microStep)
|
|
||||||
return Lang.get("win_measures_microstep");
|
|
||||||
else
|
|
||||||
return Lang.get("win_measures_fullstep");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleEvent(ModelEvent event) {
|
public void handleEvent(ModelEvent event) {
|
||||||
modelSync.access(() -> {
|
modelSync.access(() -> {
|
||||||
|
@ -2,6 +2,7 @@ package de.neemann.digital.gui.components.testing;
|
|||||||
|
|
||||||
import de.neemann.digital.core.Model;
|
import de.neemann.digital.core.Model;
|
||||||
import de.neemann.digital.core.NodeException;
|
import de.neemann.digital.core.NodeException;
|
||||||
|
import de.neemann.digital.data.ValueTable;
|
||||||
import de.neemann.digital.data.ValueTableModel;
|
import de.neemann.digital.data.ValueTableModel;
|
||||||
import de.neemann.digital.data.Value;
|
import de.neemann.digital.data.Value;
|
||||||
import de.neemann.digital.draw.elements.Circuit;
|
import de.neemann.digital.draw.elements.Circuit;
|
||||||
@ -9,15 +10,18 @@ import de.neemann.digital.draw.elements.PinException;
|
|||||||
import de.neemann.digital.draw.library.ElementLibrary;
|
import de.neemann.digital.draw.library.ElementLibrary;
|
||||||
import de.neemann.digital.draw.library.ElementNotFoundException;
|
import de.neemann.digital.draw.library.ElementNotFoundException;
|
||||||
import de.neemann.digital.draw.model.ModelCreator;
|
import de.neemann.digital.draw.model.ModelCreator;
|
||||||
|
import de.neemann.digital.gui.components.data.DataSetDialog;
|
||||||
import de.neemann.digital.lang.Lang;
|
import de.neemann.digital.lang.Lang;
|
||||||
import de.neemann.digital.testing.*;
|
import de.neemann.digital.testing.*;
|
||||||
import de.neemann.gui.ErrorMessage;
|
import de.neemann.gui.ErrorMessage;
|
||||||
import de.neemann.gui.IconCreator;
|
import de.neemann.gui.IconCreator;
|
||||||
import de.neemann.gui.LineBreaker;
|
import de.neemann.gui.LineBreaker;
|
||||||
|
import de.neemann.gui.ToolTipAction;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.table.DefaultTableCellRenderer;
|
import javax.swing.table.DefaultTableCellRenderer;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
@ -32,6 +36,8 @@ public class TestResultDialog extends JDialog {
|
|||||||
private static final Icon ICON_FAILED = IconCreator.create("testFailed.png");
|
private static final Icon ICON_FAILED = IconCreator.create("testFailed.png");
|
||||||
private static final Icon ICON_PASSED = IconCreator.create("testPassed.png");
|
private static final Icon ICON_PASSED = IconCreator.create("testPassed.png");
|
||||||
|
|
||||||
|
private final ArrayList<ValueTable> resultTableData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new result dialog.
|
* Creates a new result dialog.
|
||||||
*
|
*
|
||||||
@ -50,6 +56,8 @@ public class TestResultDialog extends JDialog {
|
|||||||
|
|
||||||
Collections.sort(tsl);
|
Collections.sort(tsl);
|
||||||
|
|
||||||
|
resultTableData = new ArrayList<>();
|
||||||
|
|
||||||
JTabbedPane tp = new JTabbedPane();
|
JTabbedPane tp = new JTabbedPane();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int errorTabIndex = -1;
|
int errorTabIndex = -1;
|
||||||
@ -65,8 +73,9 @@ public class TestResultDialog extends JDialog {
|
|||||||
table.setDefaultRenderer(Value.class, new ValueRenderer());
|
table.setDefaultRenderer(Value.class, new ValueRenderer());
|
||||||
table.setDefaultRenderer(Integer.class, new NumberRenderer());
|
table.setDefaultRenderer(Integer.class, new NumberRenderer());
|
||||||
final Font font = table.getFont();
|
final Font font = table.getFont();
|
||||||
table.getColumnModel().getColumn(0).setMaxWidth(font.getSize()*4);
|
table.getColumnModel().getColumn(0).setMaxWidth(font.getSize() * 4);
|
||||||
table.setRowHeight(font.getSize() * 6 / 5);
|
table.setRowHeight(font.getSize() * 6 / 5);
|
||||||
|
resultTableData.add(testExecuter.getResult());
|
||||||
|
|
||||||
String tabName;
|
String tabName;
|
||||||
Icon tabIcon;
|
Icon tabIcon;
|
||||||
@ -89,6 +98,21 @@ public class TestResultDialog extends JDialog {
|
|||||||
if (errorTabIndex >= 0)
|
if (errorTabIndex >= 0)
|
||||||
tp.setSelectedIndex(errorTabIndex);
|
tp.setSelectedIndex(errorTabIndex);
|
||||||
|
|
||||||
|
|
||||||
|
JMenuBar bar = new JMenuBar();
|
||||||
|
JMenu view = new JMenu(Lang.get("menu_view"));
|
||||||
|
ToolTipAction asGraph = new ToolTipAction(Lang.get("menu_showDataAsGraph")) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
int tab = tp.getSelectedIndex();
|
||||||
|
if (tab < 0) tab = 0;
|
||||||
|
new DataSetDialog(owner, Lang.get("win_testdata_N", tp.getTitleAt(tab)), resultTableData.get(tab)).setVisible(true);
|
||||||
|
}
|
||||||
|
}.setToolTip(Lang.get("menu_showDataAsGraph_tt"));
|
||||||
|
view.add(asGraph.createJMenuItem());
|
||||||
|
bar.add(view);
|
||||||
|
setJMenuBar(bar);
|
||||||
|
|
||||||
getContentPane().add(tp);
|
getContentPane().add(tp);
|
||||||
pack();
|
pack();
|
||||||
setLocationRelativeTo(owner);
|
setLocationRelativeTo(owner);
|
||||||
|
@ -20,20 +20,22 @@ public class LockSync implements Sync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void access(Runnable run) {
|
public <A extends Runnable> A access(A run) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
run.run();
|
run.run();
|
||||||
|
return run;
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accessNEx(Sync.ModelRun run) throws NodeException {
|
public <A extends Sync.ModelRun> A accessNEx(A run) throws NodeException {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
run.run();
|
run.run();
|
||||||
|
return run;
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,14 @@ public final class NoSync implements Sync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void access(Runnable run) {
|
public <A extends Runnable> A access(A run) {
|
||||||
run.run();
|
run.run();
|
||||||
|
return run;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accessNEx(Sync.ModelRun run) throws NodeException {
|
public <A extends Sync.ModelRun> A accessNEx(A run) throws NodeException {
|
||||||
run.run();
|
run.run();
|
||||||
|
return run;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,16 +13,20 @@ public interface Sync {
|
|||||||
* Calls the given runnable
|
* Calls the given runnable
|
||||||
*
|
*
|
||||||
* @param run the runnable to execute
|
* @param run the runnable to execute
|
||||||
|
* @param <A> the type oth the runnable
|
||||||
|
* @return the given runnable. Used for chained calls
|
||||||
*/
|
*/
|
||||||
void access(Runnable run);
|
<A extends Runnable> A access(A run);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as access, but catches an exception
|
* Same as access, but catches an exception
|
||||||
*
|
*
|
||||||
* @param run the runnable to execute
|
* @param run the runnable to execute
|
||||||
|
* @param <A> the type oth the runnable
|
||||||
|
* @return the given runnable. Used for chained calls
|
||||||
* @throws NodeException NodeException
|
* @throws NodeException NodeException
|
||||||
*/
|
*/
|
||||||
void accessNEx(ModelRun run) throws NodeException;
|
<A extends Sync.ModelRun> A accessNEx(A run) throws NodeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like runnable but throws an exception
|
* Like runnable but throws an exception
|
||||||
|
@ -863,7 +863,7 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
|
|||||||
<string name="menu_undo_tt">Letzte Aktion rückgängig machen</string>
|
<string name="menu_undo_tt">Letzte Aktion rückgängig machen</string>
|
||||||
<string name="menu_redo">Wiederherstellen</string>
|
<string name="menu_redo">Wiederherstellen</string>
|
||||||
<string name="menu_redo_tt">Letzte rückgängig gemachte Aktion wieder herstellen.</string>
|
<string name="menu_redo_tt">Letzte rückgängig gemachte Aktion wieder herstellen.</string>
|
||||||
<string name="menu_showDataAsGraph">Als Graph anzeigen.</string>
|
<string name="menu_showDataAsGraph">Zeige Graph</string>
|
||||||
<string name="menu_showDataAsGraph_tt">Zeigt die Daten als Graph an.</string>
|
<string name="menu_showDataAsGraph_tt">Zeigt die Daten als Graph an.</string>
|
||||||
|
|
||||||
<string name="message">Digital
|
<string name="message">Digital
|
||||||
@ -947,6 +947,7 @@ Die Icons stammen aus dem Tango Desktop Project.</string>
|
|||||||
<string name="tt_moveItemDown">Eintrag nach unten schieben</string>
|
<string name="tt_moveItemDown">Eintrag nach unten schieben</string>
|
||||||
<string name="tt_moveItemUp">Eintrag nach oben schieben</string>
|
<string name="tt_moveItemUp">Eintrag nach oben schieben</string>
|
||||||
<string name="win_allSolutions">Alle möglichen Lösungen</string>
|
<string name="win_allSolutions">Alle möglichen Lösungen</string>
|
||||||
|
<string name="win_testdata_N">Testdaten {0}</string>
|
||||||
<string name="win_confirmExit">Beenden bestätigen!</string>
|
<string name="win_confirmExit">Beenden bestätigen!</string>
|
||||||
<string name="win_measures">Messwerte</string>
|
<string name="win_measures">Messwerte</string>
|
||||||
<string name="win_measures_fullstep">Messwerte im Vollschrittmodus</string>
|
<string name="win_measures_fullstep">Messwerte im Vollschrittmodus</string>
|
||||||
|
@ -851,6 +851,8 @@ The names of the variables may not be unique.</string>
|
|||||||
<string name="menu_undo_tt">Revert last modification</string>
|
<string name="menu_undo_tt">Revert last modification</string>
|
||||||
<string name="menu_redo">Redo</string>
|
<string name="menu_redo">Redo</string>
|
||||||
<string name="menu_redo_tt">Apply last reverted modification again.</string>
|
<string name="menu_redo_tt">Apply last reverted modification again.</string>
|
||||||
|
<string name="menu_showDataAsGraph">Show graph</string>
|
||||||
|
<string name="menu_showDataAsGraph_tt">Show the data as a Graph.</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="message">Digital
|
<string name="message">Digital
|
||||||
@ -941,6 +943,7 @@ The icons are taken from the Tango Desktop Project.</string>
|
|||||||
<string name="win_table">Table</string>
|
<string name="win_table">Table</string>
|
||||||
<string name="win_table_exportDialog">Export</string>
|
<string name="win_table_exportDialog">Export</string>
|
||||||
<string name="win_itempicker_title">Select</string>
|
<string name="win_itempicker_title">Select</string>
|
||||||
|
<string name="win_testdata_N">Testdata {0}</string>
|
||||||
|
|
||||||
<string name="btn_help">Help</string>
|
<string name="btn_help">Help</string>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user