📄 wrappedsyntaxview_test.java
字号:
updateChildren(changes, a);
Rectangle alloc = ((a != null) && isAllocationValid()) ?
getInsideAllocation(a) : null;
int pos = changes.getOffset();
View v = getViewAtPosition(pos, alloc);
if (v != null)
v.insertUpdate(changes, alloc, f);
}
/*****************************************************************************/
/**
* Returns whether or not the specified offset is in the last line in the
* document.
*
* @param offset The offset to check.
* @return Whether or not the offset is in the last line in the document.
*/
private final boolean isOffsetInLastLine(int offset) {
// FIXME: This could be optimized by using elements.
try {
RSyntaxTextArea ta = (RSyntaxTextArea)getContainer();
return ta.getLineOfOffset(offset)==(ta.getLineCount()-1);
} catch (BadLocationException ble) {
ble.printStackTrace();
System.exit(0);
}
return true;
}
/*****************************************************************************/
/**
* Loads all of the children to initialize the view.
* This is called by the <code>setParent</code> method.
* Subclasses can reimplement this to initialize their
* child views in a different manner. The default
* implementation creates a child view for each
* child element.
*
* @param f the view factory
*/
protected void loadChildren(ViewFactory f) {
Element e = getElement();
int n = e.getElementCount();
if (n > 0) {
View[] added = new View[n];
for (int i = 0; i < n; i++)
added[i] = new WrappedLine(e.getElement(i));
replace(0, 0, added);
}
}
/*****************************************************************************/
/**
* Provides a mapping, for a given region, from the document model
* coordinate space to the view coordinate space. The specified region is
* created as a union of the first and last character positions.<p>
*
* This is implemented to subtract the width of the second character, as
* this view's <code>modelToView</code> actually returns the width of the
* character instead of "1" or "0" like the View implementations in
* <code>javax.swing.text</code>. Thus, if we don't override this method,
* the <code>View</code> implementation will return one character's width
* too much for its consumers (implementations of
* <code>javax.swing.text.Highlighter</code>).
*
* @param p0 the position of the first character (>=0)
* @param b0 The bias of the first character position, toward the previous
* character or the next character represented by the offset, in
* case the position is a boundary of two views; <code>b0</code>
* will have one of these values:
* <ul>
* <li> <code>Position.Bias.Forward</code>
* <li> <code>Position.Bias.Backward</code>
* </ul>
* @param p1 the position of the last character (>=0)
* @param b1 the bias for the second character position, defined
* one of the legal values shown above
* @param a the area of the view, which encompasses the requested region
* @return the bounding box which is a union of the region specified
* by the first and last character positions
* @exception BadLocationException if the given position does
* not represent a valid location in the associated document
* @exception IllegalArgumentException if <code>b0</code> or
* <code>b1</code> are not one of the
* legal <code>Position.Bias</code> values listed above
* @see View#viewToModel
*/
public Shape modelToView(int p0, Position.Bias b0,
int p1, Position.Bias b1,
Shape a) throws BadLocationException {
Shape s0 = modelToView(p0, a, b0);
Shape s1;
if (p1 ==getEndOffset()) {
try {
s1 = modelToView(p1, a, b1);
} catch (BadLocationException ble) {
s1 = null;
}
if (s1 == null) {
// Assume extends left to right.
Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a :
a.getBounds();
s1 = new Rectangle(alloc.x + alloc.width - 1, alloc.y,
1, alloc.height);
}
}
else {
s1 = modelToView(p1, a, b1);
}
Rectangle r0 = s0.getBounds();
Rectangle r1 = (s1 instanceof Rectangle) ? (Rectangle) s1 :
s1.getBounds();
if (r0.y != r1.y) {
// If it spans lines, force it to be the width of the view.
Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a :
a.getBounds();
r0.x = alloc.x;
r0.width = alloc.width;
}
r0.add(r1);
// The next line is the only difference between this method and
// View's implementation. We're subtracting the width of the second
// character. This is because this method is used by Highlighter
// implementations to get the area to "highlight", and if we don't do
// this, one character too many is highlighted thanks to our
// modelToView() implementation returning the actual width of the
// character requested!
if (p1>p0) r0.width -= r1.width;
return r0;
}
/*****************************************************************************/
/**
* Returns the next tab stop position after a given reference position.
* This implementation does not support things like centering so it
* ignores the tabOffset argument.
*
* @param x the current position >= 0
* @param tabOffset the position within the text stream
* that the tab occurred at >= 0.
* @return the tab stop, measured in points >= 0
*/
public float nextTabStop(float x, int tabOffset) {
if (tabSize == 0)
return x;
int ntabs = ((int) x - tabBase) / tabSize;
return tabBase + ((ntabs + 1) * tabSize);
}
/*****************************************************************************/
/**
* 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();
tabBase = alloc.x;
Graphics2D g2d = (Graphics2D)g;
host = (RSyntaxTextArea)getContainer();
colorScheme = host.getSyntaxHighlightingColorScheme();
int ascent = host.getMaxAscent();
int fontHeight = host.getLineHeight();
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(g2d, alloc, view, fontHeight, tempRect.y+ascent);
}
}
}
/*****************************************************************************/
/**
* Gives notification that something was removed from the
* document in a location that this view is responsible for.
* This is implemented to simply update the children.
*
* @param changes The change information from the associated document.
* @param a the current allocation of the view
* @param f the factory to use to rebuild if the view has children
* @see View#removeUpdate
*/
public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f) {
updateChildren(changes, a);
Rectangle alloc = ((a != null) && isAllocationValid()) ?
getInsideAllocation(a) : null;
int pos = changes.getOffset();
View v = getViewAtPosition(pos, alloc);
if (v != null)
v.removeUpdate(changes, alloc, f);
}
/*****************************************************************************/
/**
* Makes a <code>Segment</code> point to the text in our
* document referenced by the specified element. Note that
* <code>line</code> MUST be a valid line number in the document.
*
* @param line The line number you want to get.
* @param document The document from which you want to get the text.
* @param seg The segment in which to load the text.
*/
private void setSegment(int line, Document document, Segment seg) {
Element map = getElement();
int numLines = map.getElementCount();
Element element = map.getElement(line);
if (element==null) {
System.err.println("Error in setSharedDocument - Invalid line number: " + line);
System.exit(0);
}
int startOffset = element.getStartOffset();
int endOffset = (line==numLines-1 ? element.getEndOffset() :
element.getEndOffset() - 1);
setSegment(startOffset, endOffset, document, seg);
}
/*****************************************************************************/
/**
* Makes a <code>Segment</code> point to the text in our
* document between the given positions. Note that the positions MUST be
* valid positions in the document.
*
* @param p0 The first position in the document.
* @param p1 The second position in the document.
* @param document The document from which you want to get the text.
* @param seg The segment in which to load the text.
*/
private void setSegment(int p0, int p1, Document document,
Segment seg) {
try {
//System.err.println("... in setSharedSegment, p0/p1==" + p0 + "/" + p1);
document.getText(p0, p1-p0, seg);
//System.err.println("... in setSharedSegment: s=='" + s + "'; line/numLines==" + line + "/" + numLines);
} catch (BadLocationException ble) {
ble.printStackTrace();
System.exit(0);
}
}
/*****************************************************************************/
/**
* Sets the size of the view. This should cause layout of the view along
* the given axis, if it has any layout duties.
*
* @param width the width >= 0
* @param height the height >= 0
*/
public void setSize(float width, float height) {
updateMetrics();
if ((int) width != getWidth()) {
// invalidate the view itself since the childrens
// desired widths will be based upon this views width.
preferenceChanged(null, true, true);
widthChanging = true;
}
super.setSize(width, height);
widthChanging = false;
}
/*****************************************************************************/
/**
* Update the child views in response to a
* document event.
*/
void updateChildren(DocumentEvent e, Shape a) {
Element elem = getElement();
DocumentEvent.ElementChange ec = e.getChange(elem);
// This occurs when syntax highlighting only changes on lines
// (i.e. beginning a multiline comment).
if (e.getType()==DocumentEvent.EventType.CHANGE) {
//System.err.println("Updating the damage due to a CHANGE event...");
// FIXME: Make me repaint more intelligently.
getContainer().repaint();
//damageLineRange(startLine,endLine, a, host);
}
else if (ec != null) {
// the structure of this element changed.
Element[] removedElems = ec.getChildrenRemoved();
Element[] addedElems = ec.getChildrenAdded();
View[] added = new View[addedElems.length];
for (int i = 0; i < addedElems.length; i++)
added[i] = new WrappedLine(addedElems[i]);
//System.err.println("Replacing " + removedElems.length +
// " children with " + addedElems.length);
replace(ec.getIndex(), removedElems.length, added);
// should damge a little more intelligently.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -