/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package eric.JSprogram; //package text; import java.awt.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.text.*; public class LineNumber extends JComponent { // private final static Color DEFAULT_BACKGROUND = new Color(235, 230, 225); private final static Color DEFAULT_BACKGROUND = new Color(14, 221, 29); private final static Color DEFAULT_FOREGROUND = Color.black; private final static Font DEFAULT_FONT = new Font("monospaced", Font.PLAIN, 12); // LineNumber height (abends when I use MAX_VALUE) private final static int HEIGHT = Integer.MAX_VALUE - 1000000; // Set right/left margin private final static int MARGIN = 5; // Variables for this LineNumber component private FontMetrics fontMetrics; private int lineHeight; private int currentDigits; // Metrics of the component used in the constructor private JComponent component; private int componentFontHeight; private int componentFontAscent; /** * Convenience constructor for Text Components */ public LineNumber(JComponent component) { if (component == null) { setFont( DEFAULT_FONT ); this.component = this; } else { setFont( component.getFont() ); this.component = component; } setBackground( DEFAULT_BACKGROUND ); setForeground( DEFAULT_FOREGROUND ); setPreferredWidth( 99 ); } /** * Calculate the width needed to display the maximum line number */ public void setPreferredWidth(int lines) { int digits = String.valueOf(lines).length(); // Update sizes when number of digits in the line number changes if (digits != currentDigits && digits > 1) { currentDigits = digits; int width = fontMetrics.charWidth( '0' ) * digits; Dimension d = getPreferredSize(); d.setSize(2 * MARGIN + width, HEIGHT); setPreferredSize( d ); setSize( d ); } } /** * Reset variables that are dependent on the font. */ public void setFont(Font font) { super.setFont(font); fontMetrics = getFontMetrics( getFont() ); componentFontHeight = fontMetrics.getHeight(); componentFontAscent = fontMetrics.getAscent(); } /** * The line height defaults to the line height of the font for this * component. */ public int getLineHeight() { if (lineHeight == 0) return componentFontHeight; else return lineHeight; } /** * Override the default line height with a positive value. * For example, when you want line numbers for a JTable you could * use the JTable row height. */ public void setLineHeight(int lineHeight) { if (lineHeight > 0) this.lineHeight = lineHeight; } public int getStartOffset() { return component.getInsets().top + componentFontAscent; } public void paintComponent(Graphics g) { int lineHeight = getLineHeight(); int startOffset = getStartOffset(); Rectangle drawHere = g.getClipBounds(); // Paint the background g.setColor( getBackground() ); g.fillRect(drawHere.x, drawHere.y, drawHere.width, drawHere.height); // Determine the number of lines to draw in the foreground. g.setColor( getForeground() ); int startLineNumber = (drawHere.y / lineHeight) + 1; int endLineNumber = startLineNumber + (drawHere.height / lineHeight); int start = (drawHere.y / lineHeight) * lineHeight + startOffset; for (int i = startLineNumber; i <= endLineNumber; i++) { String lineNumber = String.valueOf(i); int stringWidth = fontMetrics.stringWidth( lineNumber ); int rowWidth = getSize().width; g.drawString(lineNumber, rowWidth - stringWidth - MARGIN, start); start += lineHeight; } int rows = component.getSize().height / componentFontHeight; setPreferredWidth( rows ); } public static void main(String[] args) { JFrame frame = new JFrame("LineNumberDemo"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); JPanel panel = new JPanel(); frame.setContentPane( panel ); panel.setBorder(BorderFactory.createEmptyBorder(20,20,20,20)); panel.setLayout(new BorderLayout()); JTextArea textPane = new JTextArea(); textPane.setFont( new Font("monospaced", Font.PLAIN, 12) ); textPane.setText("abc"); JScrollPane scrollPane = new JScrollPane(textPane); panel.add(scrollPane); scrollPane.setPreferredSize(new Dimension(300, 250)); LineNumber lineNumber = new LineNumber( textPane ); scrollPane.setRowHeaderView(lineNumber ); frame.pack(); frame.setVisible(true); } }