package org.signalml.app.view.tag; import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import java.util.List; import javax.swing.JComponent; import org.signalml.plugin.export.signal.Tag; import org.signalml.plugin.export.signal.tagStyle.TagAttributeValue; /** * Renderer capable of rendering tag attributes on a tag. * * @author Piotr Szachewicz */ public class TagAttributesRenderer extends JComponent { /** * The forementioned tag. */ private Tag tag; /** * The top padding of the filled rectangle in which tag attributes are * displayed. */ private static int paddingTop = 10; /** * The right padding of the filled rectangle in which tag attributes are * displayed. */ private static int paddingRight = 10; /** * The bottom padding of the filled rectangle in which tag attributes are * displayed. */ private static int paddingBottom = 10; /** * The left padding of the filled rectangle in which tag attributes are * displayed. */ private static int paddingLeft = 10; /** * The top margin of the filled rectangle set when the tag is a marker. */ private static int marginTopForMarkers = 30; /** * Space between each line used when printing attributes. */ private static int spaceBetweenLines = 5; /** * Stroke used to border the filled rectangle. */ private static final BasicStroke ATTRIBUTES_BORDER_STROKE = new BasicStroke(1F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10F, new float[] {3, 3}, 3F); /** * Returns the attributes renderer for the given tag. * @param tag a Tag for which renderer will be returned * @return renderer for the given tag */ public Component getTagAttributesRendererComponent(Tag tag) { this.tag = tag; return this; } @Override protected void paintComponent(Graphics gOrig) { if (tag == null || !tag.getStyle().isVisible() || !doesTagHaveVisibleAttributes(tag)) return; Graphics2D g = (Graphics2D) gOrig; drawRectangleAndBorder(g); printAttributes(g); } /** * Draws the filled rectangle with a border in which the attributes will * be printed. * @param g Graphics2D object used for drawing */ protected void drawRectangleAndBorder(Graphics2D g) { Point rectangleStartPoint; if (tag.isMarker()) { rectangleStartPoint = new Point(0, marginTopForMarkers); } else { rectangleStartPoint = new Point(0, 0); } Rectangle rect = new Rectangle(rectangleStartPoint, getAttributesRectangleDimensions(g, tag)); g.setColor(new Color(0, 0, 0)); g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f)); g.fill(rect); g.setColor(Color.BLACK); g.setStroke(ATTRIBUTES_BORDER_STROKE); g.drawRect(rect.x, rect.y, rect.width - 1, rect.height - 1); } /** * Draws the tag attributes in the filled rectangle. * @param g a Graphics2D instance used for drawing */ protected void printAttributes(Graphics2D g) { int y = getCurrentFontHeight(g) + paddingTop; if (tag.isMarker()) { y += marginTopForMarkers; } g.setColor(Color.WHITE); g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f)); for (TagAttributeValue a : tag.getAttributes().getAttributesList()) { if (!a.getAttributeDefinition().isVisible()) { continue; } String display = getAttributeDisplayString(a); g.drawString(display, paddingLeft, y); y += getCurrentFontHeight(g) + spaceBetweenLines; } } /** * Returns, whether the given tag has any visible attributes. * @param tag tag to be investigated * @return true if the given tag has any attributes whose definitions * state that they should be visible, false otherwise */ protected boolean doesTagHaveVisibleAttributes(Tag tag) { List<TagAttributeValue> attributesList = tag.getAttributes().getAttributesList(); if (attributesList.size() == 0) { return false; } for (TagAttributeValue v : attributesList) { if (v.getAttributeDefinition().isVisible()) { return true; } } return false; } /** * Returns a string that should be displayed for the given {@link TagAttributeValue}. * @param a {@link TagAttributeValue} for which the string will be * returned * @return the string that should be displayed */ protected String getAttributeDisplayString(TagAttributeValue a) { String displayValue = a.getAttributeDefinition().getDisplayName(); String value = a.getAttributeValue(); if (value.length() > 15) { value = value.substring(0, 15); } return displayValue + ": " + value; } /** * Returns the height of the currently selected font. * @param g Graphics2D object used for drawing * @return the height of the currently selected font */ protected int getCurrentFontHeight(Graphics2D g) { FontMetrics metrics = new FontMetrics(g.getFont()) { }; return metrics.getHeight(); } /** * Returns the dimensions of the filled rectangle that is shown under * the attributes. * * @param g the Graphics2D object used for drawing * @param tag the currently rendered tag * @return the dimensions of the attributes rectangle */ protected Dimension getAttributesRectangleDimensions(Graphics2D g, Tag tag) { FontMetrics metrics = new FontMetrics(g.getFont()) { }; int rectangleWidth = 0; int rectangleHeight = 0; int numberOfVisibleAttributes = 0; for (TagAttributeValue a : tag.getAttributes().getAttributesList()) { if (!a.getAttributeDefinition().isVisible()) { continue; } String displayString = getAttributeDisplayString(a); Rectangle2D bounds = metrics.getStringBounds(displayString, null); int widthInPixels = (int) bounds.getWidth(); int heightInPixels = (int) bounds.getHeight(); if (widthInPixels > rectangleWidth) { rectangleWidth = widthInPixels; } rectangleHeight += heightInPixels; numberOfVisibleAttributes++; } rectangleHeight += (numberOfVisibleAttributes - 1) * spaceBetweenLines; rectangleHeight += paddingTop; rectangleHeight += paddingBottom; rectangleWidth += paddingLeft; rectangleWidth += paddingRight; return new Dimension(rectangleWidth, rectangleHeight); } }