/** Call this method to view a parse tree in a dialog box visually. */ public static Future<JFrame> inspect(Tree t, List<String> ruleNames) { TreeViewer viewer = new TreeViewer(ruleNames, t); return viewer.open(); }
@Override public void stateChanged(ChangeEvent e) { int v = scaleSlider.getValue(); viewer.setScale(v / 1000.0 + 1.0); } }
public TreeViewer(List<String> ruleNames, Tree tree) { setRuleNames(ruleNames); if ( tree!=null ) { setTree(tree); } setFont(font); }
@Override public double getWidth(Tree tree) { FontMetrics fontMetrics = viewer.getFontMetrics(viewer.font); String s = viewer.getText(tree); int w = fontMetrics.stringWidth(s) + viewer.nodeWidthPadding*2; return w; }
protected void paintBox(Graphics g, Tree tree) { Rectangle2D.Double box = getBoundsOfNode(tree); ctx.stop != null && ctx.stop.getTokenIndex() < ctx.start.getTokenIndex(); if ( isHighlighted(tree) || boxColor!=null || tree instanceof ErrorNode || ruleFailedAndMatchedNothing) if ( isHighlighted(tree) ) g.setColor(highlightedBoxColor); else if ( tree instanceof ErrorNode || ruleFailedAndMatchedNothing ) g.setColor(LIGHT_RED); else g.setColor(boxColor); String s = getText(tree); String[] lines = s.split("\n"); FontMetrics m = getFontMetrics(font); int x = (int) box.x + arcSize / 2 + nodeWidthPadding; int y = (int) box.y + m.getAscent() + m.getLeading() + 1 + nodeHeightPadding; for (int i = 0; i < lines.length; i++) { text(g, lines[i], x, y); y += m.getHeight();
double lastKnownViewerScale = prefs.getDouble(DIALOG_VIEWER_SCALE_PREFS_KEY, viewer.getScale()); viewer.setScale(lastKnownViewerScale); UIManager.put("Tree.leafIcon", empty); Tree parseTreeRoot = viewer.getTree().getRoot(); TreeNodeWrapper nodeRoot = new TreeNodeWrapper(parseTreeRoot, viewer); fillTree(nodeRoot, parseTreeRoot, viewer); final JTree tree = new JTree(nodeRoot); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
protected void paintEdges(Graphics g, Tree parent) { if (!getTree().isLeaf(parent)) { BasicStroke stroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); ((Graphics2D)g).setStroke(stroke); Rectangle2D.Double parentBounds = getBoundsOfNode(parent); double x1 = parentBounds.getCenterX(); double y1 = parentBounds.getMaxY(); for (Tree child : getTree().getChildren(parent)) { Rectangle2D.Double childBounds = getBoundsOfNode(child); double x2 = childBounds.getCenterX(); double y2 = childBounds.getMinY(); if (getUseCurvedEdges()) { CubicCurve2D c = new CubicCurve2D.Double(); double ctrlx1 = x1; double ctrly1 = (y1+y2)/2; double ctrlx2 = x2; double ctrly2 = y1; c.setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2); ((Graphics2D) g).draw(c); } else { g.drawLine((int) x1, (int) y1, (int) x2, (int) y2); } paintEdges(g, child); } } }
paintEdges(g, getTree().getRoot()); paintBox(g, Tree);
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("<","<").replace(">",">"); 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)); }
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); } } }
AltLabelTextProvider treeText = new AltLabelTextProvider(previewState.parsingResult.parser, previewState.g); treeViewers[i].setTreeTextProvider(treeText); treeViewers[i].setTree(ctx); treeViewers[i].addHighlightedNodes(new ArrayList<Tree>() {{ add(root); }});
protected boolean isHighlighted(Tree node) { return getHighlightedNodeIndex(node) >= 0; }
@Override public void setTree(Tree root) { LookAndFeel theme = UIManager.getLookAndFeel(); UIDefaults themeDefaults = theme.getDefaults(); Color textColor = (Color)themeDefaults.get("textText"); setTextColor(textColor); super.setTree(root); }
public void setRuleNames(List<String> ruleNames) { setTreeTextProvider(new DefaultTreeTextProvider(ruleNames)); }
void showGuiTreeView(final String code) { final org.antlr.v4.runtime.CharStream stream = new ANTLRInputStream(code); final MyLexer lexer = new MyLexer(stream); final CommonTokenStream tokens = new CommonTokenStream(lexer); final MyParser parser = new MyParser(tokens); final ParseTree tree = parser.expr(); final List<String> ruleNames = Arrays.asList(MyParser.ruleNames); final TreeViewer view = new TreeViewer(ruleNames, tree); view.open(); }
private static void fillTree(TreeNodeWrapper node, Tree tree, TreeViewer viewer) { if (tree == null) { return; } for (int i = 0; i < tree.getChildCount(); i++) { Tree childTree = tree.getChild(i); TreeNodeWrapper childNode = new TreeNodeWrapper(childTree, viewer); node.add(childNode); fillTree(childNode, childTree, viewer); } }
/** * show the parseTree * * @param parseTree - the parse Tree to show * @param inputText - the input Text * @param ruleNames - the ruleNames to show */ public void showParseTree(ParseTree parseTree, String inputText, String[] ruleNames) { // http://stackoverflow.com/questions/30134121/drawing-parse-tree-in-antlr4-using-java/30137407#30137407 List<String> ruleNamesList = Arrays.asList(ruleNames); // http://stackoverflow.com/questions/34832518/antlr4-dotgenerator-example TreeViewer tv = new TreeViewer(ruleNamesList, parseTree); double scale = 1; if (showTreeViewer(tv, sourceFileName, inputText, scale) == JOptionPane.CANCEL_OPTION) { System.exit(1); } /* * DotGenerator gen = new DotGenerator(); * StringTemplate st = gen.toDOT((Tree) tree); * System.out.println(st); */ }
@Override protected void paintBox(Graphics g, Tree tree) { super.paintBox(g, tree); Rectangle2D.Double box = getBoundsOfNode(tree); if ( tree instanceof PreviewInterpreterRuleContext ) { PreviewInterpreterRuleContext ctx = (PreviewInterpreterRuleContext)tree; if ( highlightUnreachedNodes && !ctx.reached ) { g.setColor(JBColor.orange); g.drawRoundRect((int) box.x, (int) box.y, (int) box.width - 1, (int) box.height - 1, arcSize, arcSize); } } }
protected void paintBox(Graphics g, Tree tree) { Rectangle2D.Double box = getBoundsOfNode(tree); ctx.stop != null && ctx.stop.getTokenIndex() < ctx.start.getTokenIndex(); if ( isHighlighted(tree) || boxColor!=null || tree instanceof ErrorNode || ruleFailedAndMatchedNothing) if ( isHighlighted(tree) ) g.setColor(highlightedBoxColor); else if ( tree instanceof ErrorNode || ruleFailedAndMatchedNothing ) g.setColor(LIGHT_RED); else g.setColor(boxColor); String s = getText(tree); String[] lines = s.split("\n"); FontMetrics m = getFontMetrics(font); int x = (int) box.x + arcSize / 2 + nodeWidthPadding; int y = (int) box.y + m.getAscent() + m.getLeading() + 1 + nodeHeightPadding; for (int i = 0; i < lines.length; i++) { text(g, lines[i], x, y); y += m.getHeight();
double lastKnownViewerScale = prefs.getDouble(DIALOG_VIEWER_SCALE_PREFS_KEY, viewer.getScale()); viewer.setScale(lastKnownViewerScale); UIManager.put("Tree.leafIcon", empty); Tree parseTreeRoot = viewer.getTree().getRoot(); TreeNodeWrapper nodeRoot = new TreeNodeWrapper(parseTreeRoot, viewer); fillTree(nodeRoot, parseTreeRoot, viewer); final JTree tree = new JTree(nodeRoot); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);