added SVG export to the TestRig

This commit is contained in:
rlfnb 2017-06-15 09:07:55 +02:00
parent b8fd54780a
commit 639a6995f1
2 changed files with 149 additions and 30 deletions

View File

@ -165,4 +165,5 @@ YYYY/MM/DD, github id, Full name, email
2017/09/09, brauliobz, Bráulio Bezerra, brauliobezerra@gmail.com
2017/09/11, sachinjain024, Sachin Jain, sachinjain024@gmail.com
2017/10/06, bramp, Andrew Brampton, brampton@gmail.com
2017/10/15, simkimsia, Sim Kim Sia, kimcity@gmail.com
2017/10/15, simkimsia, Sim Kim Sia, kimcity@gmail.com
2017/05/29, rlfnb, Ralf Neeb, rlfnb@rlfnb.de

View File

@ -37,7 +37,10 @@ import java.awt.geom.CubicCurve2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@ -245,6 +248,69 @@ public class TreeViewer extends JComponent {
}
}
protected void generateEdges(Writer writer, Tree parent) throws IOException {
if (!getTree().isLeaf(parent)) {
Rectangle2D.Double b1 = getBoundsOfNode(parent);
double x1 = b1.getCenterX();
double y1 = b1.getCenterY();
for (Tree child : getTree().getChildren(parent)) {
Rectangle2D.Double childBounds = getBoundsOfNode(child);
double x2 = childBounds.getCenterX();
double y2 = childBounds.getMinY();
writer.write(line(""+x1, ""+y1, ""+x2, ""+y2,
"stroke:black; stroke-width:1px;"));
generateEdges(writer, child);
}
}
}
protected void generateBox(Writer writer, Tree parent) throws IOException {
// draw the box in the background
Rectangle2D.Double box = getBoundsOfNode(parent);
writer.write(rect(""+box.x, ""+box.y, ""+box.width, ""+box.height,
"fill:orange; stroke:rgb(0,0,0);", "rx=\"1\""));
// draw the text on top of the box (possibly multiple lines)
String line = getText(parent).replace("<","&lt;").replace(">","&gt;");
int fontSize = 10;
int x = (int) box.x + 2;
int y = (int) box.y + fontSize - 1;
String style = String.format("font-family:sans-serif;font-size:%dpx;",
fontSize);
writer.write(text(""+x, ""+y, style, line));
}
private static String line(String x1, String y1, String x2, String y2,
String style) {
return String
.format("<line x1=\"%s\" y1=\"%s\" x2=\"%s\" y2=\"%s\" style=\"%s\" />\n",
x1, y1, x2, y2, style);
}
private static String rect(String x, String y, String width, String height,
String style, String extraAttributes) {
return String
.format("<rect x=\"%s\" y=\"%s\" width=\"%s\" height=\"%s\" style=\"%s\" %s/>\n",
x, y, width, height, style, extraAttributes);
}
private static String text(String x, String y, String style, String text) {
return String.format(
"<text x=\"%s\" y=\"%s\" style=\"%s\">\n%s\n</text>\n", x, y,
style, text);
}
private void paintSVG(Writer writer) throws IOException {
generateEdges(writer, getTree().getRoot());
for (Tree tree : treeLayout.getNodeBounds().keySet()) {
generateBox(writer, tree);
}
}
@Override
protected Graphics getComponentGraphics(Graphics g) {
Graphics2D g2d=(Graphics2D)g;
@ -307,6 +373,18 @@ public class TreeViewer extends JComponent {
);
wrapper.add(png);
// Add an export-to-png button right of the "OK" button
JButton svg = new JButton("Export as SVG");
svg.addActionListener(
new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
generateSVGFile(viewer, dialog);
}
}
);
wrapper.add(svg);
bottomPanel.add(wrapper, BorderLayout.SOUTH);
// Add scale slider
@ -418,29 +496,7 @@ public class TreeViewer extends JComponent {
g.dispose();
try {
File suggestedFile = generateNonExistingPngFile();
JFileChooser fileChooser = new JFileChooserConfirmOverwrite();
fileChooser.setCurrentDirectory(suggestedFile.getParentFile());
fileChooser.setSelectedFile(suggestedFile);
FileFilter pngFilter = new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.isFile()) {
return pathname.getName().toLowerCase().endsWith(".png");
}
return true;
}
@Override
public String getDescription() {
return "PNG Files (*.png)";
}
};
fileChooser.addChoosableFileFilter(pngFilter);
fileChooser.setFileFilter(pngFilter);
JFileChooser fileChooser = getFileChooser(".png", "PNG files");
int returnValue = fileChooser.showSaveDialog(dialog);
if (returnValue == JFileChooser.APPROVE_OPTION) {
@ -469,23 +525,85 @@ public class TreeViewer extends JComponent {
}
}
private static File generateNonExistingPngFile() {
private static JFileChooser getFileChooser(final String fileEnding,
final String description) {
File suggestedFile = generateNonExistingFile(fileEnding);
JFileChooser fileChooser = new JFileChooserConfirmOverwrite();
fileChooser.setCurrentDirectory(suggestedFile.getParentFile());
fileChooser.setSelectedFile(suggestedFile);
FileFilter filter = new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.isFile()) {
return pathname.getName().toLowerCase().endsWith(fileEnding);
}
return true;
}
@Override
public String getDescription() {
return description+" (*"+fileEnding+")";
}
};
fileChooser.addChoosableFileFilter(filter);
fileChooser.setFileFilter(filter);
return fileChooser;
}
private static void generateSVGFile(TreeViewer viewer, JFrame dialog) {
try {
JFileChooser fileChooser = getFileChooser(".svg", "SVG files");
int returnValue = fileChooser.showSaveDialog(dialog);
if (returnValue == JFileChooser.APPROVE_OPTION) {
File svgFile = fileChooser.getSelectedFile();
// save the new svg file here!
BufferedWriter writer = new BufferedWriter(new FileWriter(svgFile));
// HACK: multiplying with 1.1 should be replaced wit an accurate number
writer.write("<svg width=\"" + viewer.getSize().getWidth() * 1.1 + "\" height=\"" + viewer.getSize().getHeight() * 1.1 + "\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">");
viewer.paintSVG(writer);
writer.write("</svg>");
writer.flush();
writer.close();
try {
// Try to open the parent folder using the OS' native file manager.
Desktop.getDesktop().open(svgFile.getParentFile());
} catch (Exception ex) {
// We could not launch the file manager: just show a popup that we
// succeeded in saving the PNG file.
JOptionPane.showMessageDialog(dialog, "Saved SVG to: "
+ svgFile.getAbsolutePath());
ex.printStackTrace();
}
}
} catch (Exception ex) {
JOptionPane.showMessageDialog(dialog,
"Could not export to SVG: " + ex.getMessage(),
"Error",
JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
}
}
private static File generateNonExistingFile(String extension) {
final String parent = ".";
final String name = "antlr4_parse_tree";
final String extension = ".png";
File pngFile = new File(parent, name + extension);
File file = new File(parent, name + extension);
int counter = 1;
// Keep looping until we create a File that does not yet exist.
while (pngFile.exists()) {
pngFile = new File(parent, name + "_"+ counter + extension);
while (file.exists()) {
file = new File(parent, name + "_" + counter + extension);
counter++;
}
return pngFile;
return file;
}
private static void fillTree(TreeNodeWrapper node, Tree tree, TreeViewer viewer) {