/* * Copyright (c) 2012 Sam Harwell, Tunnel Vision Laboratories LLC * All rights reserved. * * The source code of this document is proprietary work, and is not licensed for * distribution. For information about licensing, contact Sam Harwell at: * sam@tunnelvisionlabs.com */ package org.antlr.works.editor.grammar.syndiag; import java.awt.AWTEvent; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.event.MouseEvent; import java.awt.geom.Rectangle2D; import javax.swing.JComponent; import javax.swing.text.AttributeSet; import javax.swing.text.Document; import javax.swing.text.StyleConstants; import javax.swing.text.StyleContext; import org.antlr.netbeans.editor.text.DocumentSnapshot; import org.antlr.netbeans.editor.text.SnapshotPosition; import org.antlr.netbeans.editor.text.SnapshotPositionRegion; import org.antlr.netbeans.editor.text.TrackingPosition; import org.antlr.netbeans.editor.text.VersionedDocument; import org.antlr.v4.tool.Grammar; import org.netbeans.api.editor.settings.FontColorNames; import org.netbeans.modules.editor.NbEditorUtilities; import org.openide.text.Line; import org.openide.util.Parameters; /** * * @author Sam Harwell */ public class Node extends JComponent implements Element { private final String label; private final SnapshotPositionRegion sourceSpan; private final int labelPaddingX; private final int labelPaddingY; private final int arcSize; public Node(String label, SnapshotPositionRegion sourceSpan, int labelPaddingX, int labelPaddingY, int arcSize, AttributeSet attributes) { Parameters.notNull("label", label); this.label = label; this.sourceSpan = sourceSpan; this.labelPaddingX = labelPaddingX; this.labelPaddingY = labelPaddingY; this.arcSize = arcSize; AttributeSet defaultAttributes = Diagram.lookupAttributes(FontColorNames.DEFAULT_COLORING); Color foreground = (Color)attributes.getAttribute(StyleConstants.Foreground); if (foreground == null) { foreground = (Color)defaultAttributes.getAttribute(StyleConstants.Foreground); } if (foreground != null) { this.setForeground(foreground); } StyleContext context = new StyleContext(); Font font = context.getFont(attributes); if (font == null) { font = context.getFont(defaultAttributes); } if (font != null) { this.setFont(font); } Color background = (Color)attributes.getAttribute(StyleConstants.Background); if (background == null) { background = (Color)defaultAttributes.getAttribute(StyleConstants.Background); } if (background != null) { this.setBackground(background); } Dimension size = getLabelSize(); setPreferredSize(size); enableEvents(AWTEvent.MOUSE_EVENT_MASK); } public String getLabel() { return label; } protected static String getCategory(String label) { Parameters.notNull("label", label); if (label.startsWith("'")) { return "stringliteral"; } else if (!label.isEmpty() && Grammar.isTokenName(label)) { return "lexerrule"; } else { return "parserrule"; } } @Override public void paint(Graphics g) { super.paint(g); Dimension size = getLabelSize(); Graphics2D g2 = (Graphics2D)g; Object prevAaHint = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING); Color previousColor = g2.getColor(); try { g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Color background = getBackground(); if (background != null) { g.setColor(background); g.fillRoundRect(0, 0, size.width - 1, size.height - 1, arcSize, arcSize); } g.setColor(Color.black); g.drawRoundRect(0, 0, size.width - 1, size.height - 1, arcSize, arcSize); FontMetrics m = getFontMetrics(getFont()); g.setColor(getForeground()); int x = labelPaddingX; int y = labelPaddingY + m.getAscent(); paintLabel(g, x, y); } finally { g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, prevAaHint); g2.setColor(previousColor); } } @Override public void updatePositions() { } @Override public int getConnectionPointY() { return (int)getBounds().getCenterY(); } @Override protected void processMouseEvent(MouseEvent e) { super.processMouseEvent(e); if (!e.isConsumed() && e.getClickCount() == 2) { if (sourceSpan != null) { VersionedDocument textBuffer = sourceSpan.getSnapshot().getVersionedDocument(); Document document = textBuffer.getDocument(); DocumentSnapshot currentSnapshot = textBuffer.getCurrentSnapshot(); TrackingPosition trackingTarget = sourceSpan.getSnapshot().createTrackingPosition(sourceSpan.getStart().getOffset(), TrackingPosition.Bias.Forward); SnapshotPosition targetPoint = trackingTarget.getPosition(currentSnapshot); int column = targetPoint.getContainingLine().getStart().difference(targetPoint); NbEditorUtilities.getLine(document, targetPoint.getOffset(), true).show(Line.ShowOpenType.OPEN, Line.ShowVisibilityType.FOCUS, column); } e.consume(); } } protected void paintLabel(Graphics g, int x, int y) { g.drawString(getLabel(), x, y); } protected final Dimension getLabelSize() { FontMetrics m = getFontMetrics(getFont()); Rectangle2D r = m.getStringBounds(this.label, getGraphics()); int labelWidth = (int)r.getWidth() + 2 * this.labelPaddingX; int labelHeight = (int)r.getHeight() + 2 * this.labelPaddingY; Dimension size = new Dimension(labelWidth, labelHeight); return size; } }