📄 wrappedsyntaxview.java
字号:
/*
* 02/24/2004
*
* WrappedSyntaxView.java - The View object used by RSyntaxTextArea when
* word wrap is enabled.
* Copyright (C) 2004 Robert Futrell
* email@address.com
* www.website.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.fife.ui.rsyntaxtextarea;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import javax.swing.text.*;
/**
* The <code>javax.swing.text.View</code> object used by
* <code>RSyntaxTextArea</code> when word wrap is enabled.
* It implements syntax highlighting for programming languages
* in a single font with word wrap. Note that this view is NOT aware of
* <code>RSyntaxTextArea</code>'s different styles per token type.
*
* @author Robert Futrell
* @version 0.4
*/
public class WrappedSyntaxView extends WrappedPlainView {
/**
* This is reused to keep from allocating/deallocating.
*/
private Segment s;
/**
* Another variable initialized once to keep from allocating/deallocating.
* This is used when determining whether a child view is in the graphics
* context's clip bounds.
*/
private Rectangle tempRect;
/**
* Used in loops below so we don't have to keep allocating.
*/
private Token token;
/**
* Cached for each paint() call so each drawLine() call has access to it.
*/
private RSyntaxTextArea host;
private FontMetrics metrics;
private SyntaxHighlightingColorScheme colorScheme;
/**
* The end-of-line marker.
*/
private static final char[] eolMarker = { '.' };
/*****************************************************************************/
/**
* Constructs a new <code>WrappedSyntaxView</code> wrapped around an element.
*
* @param elem The element representing the text to display.
*/
public WrappedSyntaxView(Element elem) {
super(elem, true);
s = new Segment();
tempRect = new Rectangle();
}
/*****************************************************************************/
/**
* Draws text at a specified location, taking tabs into account.<br><br>
*
* NOTE: This is basically ripped off from
* <code>javax.swing.text.Utilities</code>, but slightly optimized for our
* situation.
*
* @param token The token to paint.
* @param x The x-coordinate at which to paint.
* @param y The y-coordinate at which to paint.
* @param g The graphics context in which to paint.
* @param startOffset The offset into the current document at which
* <code>text</code> begins.
* @return The x-coordinate representing the end of the painted text.
*/
public final int drawTabbedText(Token token, int x, int y,
Graphics g, int startOffset,
Color fg, Color bg) {
char[] text = token.text;
int start = token.textOffset;
int end = start + token.textCount;
int nextX = x;
int flushLen = 0;
int flushIndex = start;
for (int i=start; i<end; i++) {
if (text[i] == '\t') {
if (flushLen > 0) {
g.setColor(fg);
g.drawChars(text, flushIndex, flushLen, x, y);
flushLen = 0;
}
flushIndex = i + 1;
int nextNextX = (int)nextTabStop((float)nextX, startOffset+i);
if (bg!=null) {
Graphics2D xorGfx = (Graphics2D)g.create();
Color hostBG = host.getBackground();
xorGfx.setXORMode(hostBG!=null ? hostBG : Color.WHITE);
xorGfx.setColor(bg);
xorGfx.fillRect(nextX,y-metrics.getAscent(), nextNextX-nextX,metrics.getHeight());
xorGfx.dispose();
}
nextX = x = nextNextX;
}
else {
flushLen += 1;
nextX += metrics.charWidth(text[i]);
}
}
if (flushLen > 0) {
if (bg!=null) {
Graphics2D xorGfx = (Graphics2D)g.create();
Color hostBG = host.getBackground();
xorGfx.setXORMode(hostBG!=null ? hostBG : Color.WHITE);
xorGfx.setColor(bg);
xorGfx.fillRect(x,y-metrics.getAscent(), nextX-x,metrics.getHeight());
xorGfx.dispose();
}
g.setColor(fg);
g.drawChars(text, flushIndex, flushLen, x, y);
}
return nextX;
}
/*****************************************************************************/
/**
* Draws a single view (i.e., a line of text for a wrapped view), wrapping
* the text onto multiple lines if necessary.
*
* @param g The graphics context in which to paint.
* @param r The rectangle in which to paint.
* @param view The <code>View</code> to paint.
* @param fontHeight The height of the font being used.
* @param y The y-coordinate at which to begin painting.
*/
protected void drawView(Graphics g, Rectangle r, View view,
int fontHeight, int y) {
int x = r.x;
LayeredHighlighter dh = (LayeredHighlighter)host.getHighlighter();
RSyntaxDocument document = (RSyntaxDocument)getDocument();
Element map = getElement();
int p0 = view.getStartOffset();
int p1 = view.getEndOffset();
int lineNumber = map.getElementIndex(p0);
// try {
// document.getText(p0,p1-p0-1, s);
// } catch (BadLocationException ble) {
// ble.printStackTrace();
// System.exit(0);
// }
int start = p0 - s.offset;
// token = document.getTokenList(s, p0, lineNumber);
token = document.getTokenListForLine(lineNumber);
while (token!=null && token.isPaintable()) {
int p = calculateBreakPosition(p0, p1);
if (p==p1)
dh.paintLayeredHighlights(g, p0,p-1, r, host, this);
else
dh.paintLayeredHighlights(g, p0,p, r, host, this);
while (token!=null && token.isPaintable() && token.offset+token.textCount-1<=p) {
SyntaxScheme scheme = colorScheme.syntaxSchemes[token.type];
// DON'T call Token.paint, as this view doesn't respect
// token styles.
x = drawTabbedText(token, x,y, g, token.offset,
scheme.foreground, scheme.background);
token = token.getNextToken();
}
if (token!=null && token.isPaintable() && token.offset<p) {
int tokenOffset = token.offset;
Token temp = new DefaultToken(s, tokenOffset-start,p-1-start, tokenOffset, token.type);
SyntaxScheme scheme = colorScheme.syntaxSchemes[token.type];
// DON'T call Token.paint, as this view doesn't respect
// token styles.
drawTabbedText(temp, x,y, g, token.offset,
scheme.foreground, scheme.background);
temp = token.getNextToken();
token = new DefaultToken(s, p-start,tokenOffset+token.textCount-1-start, p, token.type);
token.setNextToken(temp);
temp = null;
}
p0 = (p==p0) ? p1 : p;
x = r.x;
y += fontHeight;
} // End of while (token!=null && token.type>Token.NULL).
}
/*****************************************************************************/
/**
* Paints the word-wrapped text.
*
* @param g The graphics context in which to paint.
* @param a The shape (usually a rectangle) in which to paint.
*/
public void paint(Graphics g, Shape a) {
Rectangle alloc = (a instanceof Rectangle) ?
(Rectangle)a : a.getBounds();
host = (RSyntaxTextArea)getContainer();
colorScheme = host.getSyntaxHighlightingColorScheme();
metrics = g.getFontMetrics();
int ascent = metrics.getAscent();
int fontHeight = metrics.getHeight();
int n = getViewCount(); // Number of lines.
int x = alloc.x + getLeftInset();
int y = alloc.y + getTopInset();
Rectangle clip = g.getClipBounds();
for (int i = 0; i < n; i++) {
tempRect.x = x + getOffset(X_AXIS, i);
tempRect.y = y + getOffset(Y_AXIS, i);
tempRect.width = getSpan(X_AXIS, i);
tempRect.height = getSpan(Y_AXIS, i);
//System.err.println("For line " + i + ": tempRect==" + tempRect);
if (tempRect.intersects(clip)) {
View view = getView(i);
drawView(g, alloc, view, fontHeight, tempRect.y+ascent);
}
}
}
/*****************************************************************************/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -