📄 linenumberborder.java~2~
字号:
return;
}
// Get the first and last lines to paint.
int topLine = visibleRect.y / cellHeight + 1;
int bottomLine = Math.min(topLine + visibleRect.height / cellHeight,
root.getElementCount()) + 1;
// Get where to start painting (top of the row), and where to paint
// the line number (drawString expects y==baseline).
// We need to be "scrolled up" up just enough for the missing part of
// the first line.
int actualTopY = y - (visibleRect.y % cellHeight);
Insets textAreaInsets = textArea.getInsets();
if (textAreaInsets != null) {
actualTopY += textAreaInsets.top;
}
int y2 = actualTopY + ascent;
// Highlight the current line's line number, if desired.
if (textArea.isCurrentLineHighlightEnabled() && currentLine >= topLine &&
currentLine < bottomLine) {
g.setColor(textArea.getCurrentLineHighlightColor());
g.fillRect(x, actualTopY + (currentLine - topLine) * cellHeight,
insets.left, cellHeight);
}
// Paint the "border" line.
g.setColor(Color.BLACK);
g.drawLine(x + insets.left - 4, 0, x + insets.left - 4,
visibleRect.height + 1);
g.setColor(getForeground());
FontMetrics metrics = g.getFontMetrics();
int rhs = x + insets.left - RHS_BORDER_WIDTH;
for (int i = topLine; i < bottomLine; i++) {
String number = Integer.toString(i);
int w = (int) metrics.getStringBounds(number, g).getWidth();
g.drawString(number, rhs - w, y2);
y2 += cellHeight;
}
}
/*****************************************************************************/
/**
* Paints line numbers for text areas with line wrap enabled.
*
* @param g The graphics context.
* @param root The root element of the document being painted.
* @param x The x-coordinate of the border.
* @param y The y-coordinate of the border.
* @param visibleRect The visible rectangle of the text area.
*/
public void paintWrappedLineNumbers(Graphics g, Element root, int x, int y,
Rectangle visibleRect) {
// The variables we use are as follows:
// - visibleRect is the "visible" area of the text area; e.g.
// [0,100, 300,100+(numLines*cellHeight)-1].
// actualTop.y is the topmost-pixel in the first logical line we
// paint. Note that we may well not paint this part of the logical
// line, as it may be broken into many physical lines, with the first
// few physical lines scrolled past. Note also that this is NOT the
// visible rect of this line number list; this line number list has
// visible rect == [0,0, insets.left-1,visibleRect.height-1].
// - offset (<=0) is the y-coordinate at which we begin painting when
// we begin painting with the first logical line. This can be
// negative, signifying that we've scrolled past the actual topmost
// part of this line.
// The algorithm is as follows:
// - Get the starting y-coordinate at which to paint. This may be
// above the first visible y-coordinate as we're in line-wrapping
// mode, but we always paint entire logical lines.
// - Paint that line's line number and highlight, if appropriate.
// Increment y to be just below the are we just painted (i.e., the
// beginning of the next logical line's view area).
// - Get the ending visual position for that line. We can now loop
// back, paint this line, and continue until our y-coordinate is
// past the last visible y-value.
// We avoid using modelToView/viewToModel where possible, as these
// methods trigger a parsing of the line into syntax tokens, which is
// costly. It's cheaper to just grab the child views' bounds.
// Some variables we'll be using.
RTextAreaUI ui = (RTextAreaUI) textArea.getUI();
Rectangle visibleEditorRect = ui.getVisibleEditorRect();
View v = ui.getRootView(textArea).getView(0);
boolean currentLineHighlighted = textArea.
isCurrentLineHighlightEnabled();
int lineCount = root.getElementCount();
int topPosition = textArea.viewToModel(
new Point(visibleRect.x, visibleRect.y));
int topLine = root.getElementIndex(topPosition);
// Compute the y at which to begin painting text, taking into account
// that 1 logical line => at least 1 physical line, so it may be that
// y<0. The computed y-value is the y-value of the top of the first
// (possibly) partially-visible view.
Rectangle r = LineNumberBorder.getChildViewBounds(v, topLine,
visibleEditorRect);
int offset = r.y - visibleRect.y;
int y2 = y + offset; // The y-coordinate at which we're painting.
FontMetrics metrics = g.getFontMetrics();
int rhs = x + insets.left - RHS_BORDER_WIDTH;
int visibleBottom = y2 + visibleRect.height;
// Keep painting lines until our y-coordinate is passed the visible
// end of the text area.
g.setColor(getForeground());
while (y2 < visibleBottom) {
r = LineNumberBorder.getChildViewBounds(v, topLine,
visibleEditorRect);
int lineEndY = (r.y + r.height) - visibleRect.y;
// Highlight the current line's line number, if desired.
if (currentLineHighlighted && topLine == currentLine - 1) {
g.setColor(textArea.getCurrentLineHighlightColor());
// FIXME: Why is the "+2" needed???
g.fillRect(x, y2, insets.left, lineEndY - y2 + 2);
g.setColor(getForeground());
}
// Paint the line number.
String number = Integer.toString(topLine + 1);
int width = (int) metrics.getStringBounds(number, g).getWidth();
g.drawString(number, rhs - width, y2 + ascent);
// The next possible y-coordinate is just after the last line
// painted.
y2 += r.height;
// Update topLine (we're actually using it for our "current line"
// variable now).
topLine++;
if (topLine >= lineCount) {
break;
}
}
// Paint the "border" line. Remember that the line number list
// doesn't scroll and always has visible rect ==
// [0,0, insets.left-1,visibleRect.height-1].
g.setColor(Color.BLACK);
int x2 = x + insets.left - 4;
g.drawLine(x2, y, x2, y + visibleRect.height - 1);
}
/*****************************************************************************/
/**
* Called whenever the text area fires a property change event.
*
* @param e The event.
*/
public void propertyChange(PropertyChangeEvent e) {
String name = e.getPropertyName();
// If they changed the background color of the text area.
if (name.equals("background")) {
Color bg = textArea.getBackground();
setBackground(bg == null ? Color.WHITE : bg);
scrollPane.repaint();
}
// If they changed the background to an image.
if (name.equals("background.image")) {
setBackground(Color.WHITE);
scrollPane.repaint();
}
// If they change the text area's font, we need to update cell heights
// to match the font's height.
else if (name.equals("font")) {
updateCellHeights();
}
// If they change the current line highlight in any way...
else if (name.equals(RTextArea.CURRENT_LINE_HIGHLIGHT_PROPERTY) ||
name.equals(RTextArea.CURRENT_LINE_HIGHLIGHT_COLOR_PROPERTY)) {
scrollPane.repaint();
}
// If they change the text area's syntax scheme (i.e., it is an
// RSyntaxTextArea), update cell heights.
else if (name.equals(RSyntaxTextArea.SYNTAX_SCHEME_PROPERTY)) {
updateCellHeights();
}
}
/*****************************************************************************/
/**
* Called whenever a character is removed (ie backspace, delete) in the
* text document we're line-numbering.
*/
public void removeUpdate(DocumentEvent e) {
int newNumLines = textArea.getDocument().getDefaultRootElement().
getElementCount();
if (newNumLines < currentNumLines) { // Used to be <=
// Adjust the amount of space the line numbers take up, if necessary.
if (newNumLines / 10 < currentNumLines / 10) {
updateCellWidths();
}
currentNumLines = newNumLines;
// Need to repaint in case they removed a line by pressing
// delete.
scrollPane.repaint();
}
}
/*****************************************************************************/
/**
* Sets the background color of the line number list.
*
* @param color The background color.
* @see #getBackground
*/
public void setBackground(Color background) {
if (background != null && !background.equals(this.background)) {
this.background = background;
//repaint();
}
}
/*****************************************************************************/
/**
* Sets the font used to render the line numbers.
*
* @param font The <code>java.awt.Font</code> to use to to render the line
* numbers. If <code>null</code>, a 10-point monospaced font
* will be used.
* @see #getFont
*/
public void setFont(Font font) {
if (font == null) {
font = new Font("monospaced", Font.PLAIN, 10);
}
this.font = font;
//repaint();
}
/*****************************************************************************/
/**
* Sets the foreground color of the line number list.
*
* @param color The foreground color.
* @see #getForeground
*/
public void setForeground(Color foreground) {
if (foreground != null && !foreground.equals(this.foreground)) {
this.foreground = foreground;
//repaint();
}
}
/*****************************************************************************/
/**
* Sets the color to use to paint line numbers.
*
* @param color The color to use when painting line numbers.
* @see #getLineNumberColor
*/
public void setLineNumberColor(Color color) {
setForeground(color);
//repaint();
}
/*****************************************************************************/
/**
* Messages from the viewport.
*
* @param change The change event.
*/
public void stateChanged(ChangeEvent e) {
scrollPane.repaint();
}
/*****************************************************************************/
/**
* Changes the height of the cells in the JList so that they are as tall as
* the height of a line of text in the text area. This should be called
* whenever the user changes the font in an <code>RTextArea</code> or a
* syntax style in an <code>RSyntaxTextArea</code>.
*/
public void updateCellHeights() {
cellHeight = textArea.getLineHeight();
ascent = textArea.getMaxAscent();
}
/*****************************************************************************/
/**
* Changes the width of the cells in the JList so you can see every digit
* of each.
*/
public void updateCellWidths() {
// Adjust the amount of space the line numbers take up, if necessary.
Font font = getFont();
if (font != null) {
FontMetrics fontMetrics = textArea.getFontMetrics(font);
int count = 0;
int numLines = textArea.getDocument().getDefaultRootElement().
getElementCount();
while (numLines >= 10) {
numLines = numLines / 10;
count++;
}
insets.left = Math.max(fontMetrics.charWidth('9') * (count + 2) + 5,
MIN_CELL_WIDTH);
//revalidate();
}
}
/*****************************************************************************/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -