package org.rr.commons.swing.icon; import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.RenderingHints; import java.awt.geom.Rectangle2D; import javax.swing.Icon; import org.rr.commons.collection.Pair; /** * An {@link Icon} implementation which only shows a text at a configurable position. It can be used with {@link DecoratedIcon} to create a * text overlay for another icon. */ public class TextIcon implements Icon { private final int width; private final int height; private final String text; private final Font font; private final Location location; private final Insets insets; private final Color bgColor; private final Color fgColor; public static enum Location { UPPER_LEFT, UPPER_RIGHT, LOWER_LEFT, LOWER_RIGHT }; public TextIcon(int width, int height, String text, Font font, Location location, Insets insets, Color fgColor, Color bgColor) { this.width = width; this.height = height; this.text = text; this.font = font; this.location = location; this.insets = insets; this.bgColor = bgColor; this.fgColor = fgColor; } public int getIconWidth() { return width; } public int getIconHeight() { return height; } public void paintIcon(Component c, Graphics g, int x, int y) { g = g.create(x, y, width, height); try { g.setFont(font); FontMetrics metrics = g.getFontMetrics(); Rectangle2D stringBounds = metrics.getStringBounds(text, g); Pair<Integer, Integer> textLocation = getTextLocation(g, stringBounds); int textX = textLocation.getE(); int textY = textLocation.getF(); if(bgColor != null) { paintTextBackground(g, stringBounds, textX, textY); } if(fgColor != null) { g.setColor(Color.WHITE); } setupAntialiasing(g); g.drawString(text, textX, textY); } finally { g.dispose(); } } protected void paintTextBackground(Graphics g, Rectangle2D stringBounds, int textX, int textY) { Color color = g.getColor(); g.setColor(bgColor); g.fillRect(textX - 1, (int) (textY - stringBounds.getHeight() + 1), (int) stringBounds.getWidth() + 1, (int) (stringBounds.getHeight() + 1)); g.setColor(color); } protected void setupAntialiasing(Graphics g) { ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP); } private Pair<Integer, Integer> getTextLocation(Graphics g, Rectangle2D stringBounds) { int textX = 0; int textY = 0; switch (location) { case UPPER_LEFT: textX = insets.left; textY = insets.top + (int) stringBounds.getHeight(); break; case LOWER_LEFT: textX = insets.left; textY = height - insets.bottom; break; case UPPER_RIGHT: textX = getIconWidth() - (int) stringBounds.getWidth() - insets.right; textY = insets.top + (int) stringBounds.getHeight(); break; case LOWER_RIGHT: textX = getIconWidth() - (int) stringBounds.getWidth() - insets.right; textY = height - insets.bottom; break; } return new Pair<Integer, Integer>(Math.max(0, textX), Math.max(0, textY)); } }