001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.drjava.ui;
038:
039: import java.awt.*;
040: import javax.swing.*;
041:
042: import edu.rice.cs.drjava.DrJava;
043: import edu.rice.cs.drjava.config.OptionConstants;
044:
045: /**
046: * The row header of the DefinitionsPane which displays the line numbers
047: * @version $Id: LineEnumRule.java 4255 2007-08-28 19:17:37Z mgricken $
048: */
049: public class LineEnumRule extends JComponent {
050: /** The magic number for Swing's JTextPane border padding. */
051: private static final int BORDER_PADDING = 3;
052:
053: /** Width of the rule */
054: static int SIZE = 35;
055:
056: /** Vertical increment between line numbers */
057: private int _increment;
058:
059: /** DefinitionsPane that this rule is displayed for */
060: protected DefinitionsPane _pane;
061:
062: /** font metrics for the DefPane's font */
063: protected FontMetrics _fm;
064: /** custom font for the line numbers */
065: protected Font _newFont;
066: /** font metrics for the new font */
067: protected FontMetrics _nfm;
068:
069: /**
070: * Create a new component to display line numbers along the left of
071: * the definitions pane.
072: * @param p the pane to show line numbers on
073: */
074: public LineEnumRule(DefinitionsPane p) {
075: _pane = p;
076: _fm = _pane.getFontMetrics(_pane.getFont());
077: _increment = _fm.getHeight();
078:
079: _newFont = _getLineNumFont();
080: _nfm = getFontMetrics(_newFont);
081: // XXX: 3 is the magic number for Swing's JTextPane border padding.
082: SIZE = (int) _nfm.getStringBounds("99999", getGraphics())
083: .getWidth() + 3;
084: }
085:
086: /**
087: * Return a new Dimension using our set width, and the height of the def. pane
088: * return Dimension
089: */
090: public Dimension getPreferredSize() {
091: return new Dimension(SIZE, (int) _pane.getPreferredSize()
092: .getHeight());
093: }
094:
095: /**
096: * Updates the row header's font information.
097: * Uses a custom config setting for this purpose.
098: */
099: public void updateFont() {
100: _fm = _pane.getFontMetrics(_pane.getFont());
101: _newFont = _getLineNumFont();
102: //_pane.getFont().deriveFont( 8f );
103: _nfm = getFontMetrics(_newFont);
104: // XXX: 3 is the magic number for Swing's JTextPane border padding.
105: SIZE = (int) _nfm.getStringBounds("99999", getGraphics())
106: .getWidth() + 3;
107: }
108:
109: /**
110: * Paints the line enumeration component.
111: */
112: public void paintComponent(Graphics g) {
113: Rectangle drawHere = g.getClipBounds();
114:
115: // Set a white background
116: Color backg = DrJava.getConfig().getSetting(
117: OptionConstants.DEFINITIONS_BACKGROUND_COLOR);
118: g.setColor(backg);
119: g.fillRect(drawHere.x, drawHere.y, drawHere.width,
120: drawHere.height);
121:
122: // Do the ruler labels in a small font that's black.
123: g.setFont(_newFont);
124: Color foreg = DrJava.getConfig().getSetting(
125: OptionConstants.DEFINITIONS_NORMAL_COLOR);
126: g.setColor(foreg);
127:
128: // Use clipping bounds to calculate first tick and last tick location.
129: int start = (drawHere.y / _increment) * _increment;
130: int end = (((drawHere.y + drawHere.height) / _increment) + 1)
131: * _increment;
132:
133: int baseline = (int) ((_nfm.getAscent() + _fm.getHeight() - _fm
134: .getDescent()) / 2.0);
135:
136: // ticks and labels
137: // final OpenDefinitionsDocument odd = _pane.getOpenDefDocument();
138: // final int endOffset = odd.getEndPosition().getOffset()-1;
139: // int lastLine = odd.getDefaultRootElement().getElementIndex(endOffset);
140: //
141: // if (odd.getLineStartPos(endOffset)!=odd.getLineEndPos(endOffset)) { ++lastLine; }
142: for (int i = start; i < end; i += _increment) {
143: // final int lineNo = i/_increment +1;
144: // if (lineNo>lastLine) break;
145: // String text = Integer.toString(lineNo);
146: String text = Integer.toString(i / _increment + 1);
147:
148: // When we paint, we get a good look at the Graphics hints.
149: // Use them to update our estimate of total width.
150: SIZE = (int) _nfm.getStringBounds("99999", g).getWidth()
151: + BORDER_PADDING;
152: int offset = SIZE
153: - ((int) (_nfm.getStringBounds(text, g).getWidth() + 1));
154:
155: //g.drawLine(SIZE-1, i, SIZE-tickLength-1, i);
156: if (text != null) {
157: // Add an arbitrary 3 pixels to line up the text properly with the
158: // def pane text baseline.
159: g.drawString(text, offset, i + baseline + 3);
160: }
161: }
162: }
163:
164: /**
165: * Get the font for line numbers, making sure that it is vertically smaller
166: * than the definitions pane font.
167: * @return a valid font for displaying line numbers
168: */
169: private Font _getLineNumFont() {
170: Font lnf = DrJava.getConfig().getSetting(
171: OptionConstants.FONT_LINE_NUMBERS);
172: FontMetrics mets = getFontMetrics(lnf);
173: Font mainFont = _pane.getFont();
174:
175: // Check the height of the line num font against the def pane font.
176: if (mets.getHeight() > _fm.getHeight()) {
177: // If the line num font has a larger size than the main font, try deriving
178: // a new version with the same size. (This may or may not produce a height
179: // smaller than the main font.)
180: float newSize;
181: if (lnf.getSize() > mainFont.getSize()) {
182: newSize = mainFont.getSize2D();
183: }
184: // Otherwise, just reduce the current size by one and try that.
185: else {
186: newSize = lnf.getSize2D() - 1f;
187: }
188:
189: // If that doesn't work, try reducing the size by one until it fits.
190: do {
191: lnf = lnf.deriveFont(newSize);
192: mets = getFontMetrics(lnf);
193: newSize -= 1f;
194: } while (mets.getHeight() > _fm.getHeight());
195: }
196:
197: return lnf;
198: }
199: }
|