diff --git a/runtime/Java/src/org/antlr/v4/runtime/RuleContext.java b/runtime/Java/src/org/antlr/v4/runtime/RuleContext.java index 5428ff2e1..fc10be7eb 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/RuleContext.java +++ b/runtime/Java/src/org/antlr/v4/runtime/RuleContext.java @@ -36,6 +36,8 @@ import org.antlr.v4.runtime.tree.ParseTreeListener; import org.antlr.v4.runtime.tree.Trees; import org.antlr.v4.runtime.tree.gui.TreeViewer; +import javax.print.PrintException; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -307,6 +309,13 @@ public class RuleContext implements ParseTree.RuleNode { viewer.open(); } + public void save(BaseRecognizer parser, String fileName) + throws IOException, PrintException + { + TreeViewer viewer = new TreeViewer(parser, this); + viewer.save(fileName); + } + /** Print out a whole tree, not just a node, in LISP format * (root child1 .. childN). Print just a node if this is a leaf. * We have to know the recognizer so we can get rule names. diff --git a/runtime/Java/src/org/antlr/v4/runtime/misc/GraphicsSupport.java b/runtime/Java/src/org/antlr/v4/runtime/misc/GraphicsSupport.java new file mode 100644 index 000000000..310b05972 --- /dev/null +++ b/runtime/Java/src/org/antlr/v4/runtime/misc/GraphicsSupport.java @@ -0,0 +1,120 @@ +/* + [The "BSD license"] + Copyright (c) 2011 Terence Parr + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.antlr.v4.runtime.misc; + +import javax.imageio.ImageIO; +import javax.print.*; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +public class GraphicsSupport { + /** + [The "BSD license"] + Copyright (c) 2011 Cay Horstmann + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + public static void saveImage(final JComponent comp, String fileName) + throws IOException, PrintException + { + if (fileName.endsWith(".ps") || fileName.endsWith(".eps")) { + DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE; + String mimeType = "application/postscript"; + StreamPrintServiceFactory[] factories = + StreamPrintServiceFactory.lookupStreamPrintServiceFactories(flavor, mimeType); + FileOutputStream out = new FileOutputStream(fileName); + if (factories.length > 0) { + PrintService service = factories[0].getPrintService(out); + SimpleDoc doc = new SimpleDoc(new Printable() { + public int print(Graphics g, PageFormat pf, int page) { + if (page >= 1) return Printable.NO_SUCH_PAGE; + else { + double sf1 = pf.getImageableWidth() / (comp.getWidth() + 1); + double sf2 = pf.getImageableHeight() / (comp.getHeight() + 1); + double s = Math.min(sf1, sf2); + Graphics2D g2 = (Graphics2D) g; + g2.translate((pf.getWidth() - pf.getImageableWidth()) / 2, + (pf.getHeight() - pf.getImageableHeight()) / 2); + g2.scale(s, s); + + comp.paint(g); + return Printable.PAGE_EXISTS; + } + } + }, flavor, null); + DocPrintJob job = service.createPrintJob(); + PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet(); + job.print(doc, attributes); + } + } else { + Rectangle rect = comp.getBounds(); + BufferedImage image = new BufferedImage(rect.width, rect.height, + BufferedImage.TYPE_INT_RGB); + Graphics2D g = (Graphics2D) image.getGraphics(); + g.setColor(Color.WHITE); + g.fill(rect); + g.setColor(Color.BLACK); + comp.paint(g); + String extension = fileName.substring(fileName.lastIndexOf('.') + 1); + ImageIO.write(image, extension, new File(fileName)); + g.dispose(); + } + } +} diff --git a/runtime/Java/src/org/antlr/v4/runtime/tree/BaseAST.java b/runtime/Java/src/org/antlr/v4/runtime/tree/BaseAST.java index 6b3fc5829..3413cea16 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/tree/BaseAST.java +++ b/runtime/Java/src/org/antlr/v4/runtime/tree/BaseAST.java @@ -32,7 +32,10 @@ package org.antlr.v4.runtime.tree; import org.antlr.v4.runtime.BaseRecognizer; import org.antlr.v4.runtime.tree.gui.TreeViewer; -import java.util.*; +import javax.print.PrintException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; /** A generic AST implementation with no payload. You must subclass to * actually have any user data. ANTLR v3 uses a list of children approach @@ -258,6 +261,13 @@ public abstract class BaseAST implements AST { viewer.open(); } + public void save(BaseRecognizer parser, String fileName) + throws IOException, PrintException + { + TreeViewer viewer = new TreeViewer(parser, this); + viewer.save(fileName); + } + /** Don't use standard tree printing mechanism since ASTs can have nil * root nodes. */ diff --git a/runtime/Java/src/org/antlr/v4/runtime/tree/gui/TreeViewer.java b/runtime/Java/src/org/antlr/v4/runtime/tree/gui/TreeViewer.java index 11cb910df..e2f347c70 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/tree/gui/TreeViewer.java +++ b/runtime/Java/src/org/antlr/v4/runtime/tree/gui/TreeViewer.java @@ -34,12 +34,15 @@ import org.abego.treelayout.TreeForTreeLayout; import org.abego.treelayout.TreeLayout; import org.abego.treelayout.util.DefaultConfiguration; import org.antlr.v4.runtime.BaseRecognizer; +import org.antlr.v4.runtime.misc.GraphicsSupport; import org.antlr.v4.runtime.tree.Tree; import org.antlr.v4.runtime.tree.Trees; +import javax.print.PrintException; import javax.swing.*; import java.awt.*; import java.awt.geom.Rectangle2D; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -211,6 +214,10 @@ public class TreeViewer extends JComponent { showInDialog(this); } + public void save(String fileName) throws IOException, PrintException { + GraphicsSupport.saveImage(this, fileName); + } + // --------------------------------------------------- public void setFontSize(int sz) { diff --git a/tool/playground/TestT.java b/tool/playground/TestT.java index c61828e14..02127bad5 100644 --- a/tool/playground/TestT.java +++ b/tool/playground/TestT.java @@ -50,7 +50,7 @@ public class TestT { System.out.println(tree.toStringTree(p)); TreeViewer v = new TreeViewer(p, tree); v.setHighlightedBoxColor(new Color(217, 189, 187)); - v.addHighlightNodes(new ArrayList(){{ + v.addHighlightNodes(new ArrayList() {{ ParseTree c0 = tree.getChild(0); add(c0); add(c0.getChild(0));