📄 rprintutilities.java
字号:
// Replace tabs with how many spaces they should be.
if (tabSizeInSpaces == 0) {
curLineString.replaceAll("\t", "");
}
else {
int tabIndex = curLineString.indexOf('\t');
while (tabIndex > -1) {
int spacesNeeded = tabSizeInSpaces - (tabIndex % tabSizeInSpaces);
String replacementString = "";
for (int i=0; i<spacesNeeded; i++)
replacementString += " ";
curLineString = curLineString.replaceFirst("\t", replacementString); // Note that "\t" is actually a regex for this method.
tabIndex = curLineString.indexOf('\t');
}
}
// If this document line is too long to fit on one printed line on the page,
// break it up into multpile lines.
while (curLineString.length() > MAX_CHARS_PER_LINE) {
int breakPoint = getLineBreakPoint(curLineString, MAX_CHARS_PER_LINE) + 1;
numPrintedLines++;
if (numPrintedLines > STARTING_LINE_NUMBER) {
g.drawString(curLineString.substring(0,breakPoint), xOffset,y);
y += fontHeight;
if (numPrintedLines==STARTING_LINE_NUMBER+MAX_LINES_PER_PAGE)
return Printable.PAGE_EXISTS;
}
curLineString = curLineString.substring(breakPoint, curLineString.length());
}
currentDocLineNumber += 1; // We have printed one more line from the document.
numPrintedLines++;
if (numPrintedLines>STARTING_LINE_NUMBER) {
g.drawString(curLineString, xOffset,y);
y += fontHeight;
if (numPrintedLines==STARTING_LINE_NUMBER+MAX_LINES_PER_PAGE)
return Printable.PAGE_EXISTS;
}
}
// Now, the whole document has been "printed." Decide if this page had any text on it or not.
if (numPrintedLines > STARTING_LINE_NUMBER)
return Printable.PAGE_EXISTS;
return Printable.NO_SUCH_PAGE;
}
/*****************************************************************************/
/**
* Prints a <code>Document</code> using the specified font, word wrapping
* on the characters ' ', '\t', '\n', ',', '.', and ';'. This method is
* expected to be called from Printable 'print(Graphics g)' functions.
*
* @param g The graphics context to write to.
* @param textComponent The <code>javax.swing.text.JTextComponent</code> whose
* text you're printing.
* @param font The font to use for printing. If <code>null</code>, then
* <code>textComponent</code>'s font is used.
* @param pageIndex The page number to print.
* @param pageFormat The format to print the page with.
* @param tabSize The number of spaces to convert tabs to.
*
*/
public static int printDocumentWordWrap(Graphics g, JTextComponent textComponent,
Font font, int pageIndex,
PageFormat pageFormat,
int tabSize) {
// Initialize our graphics object.
g.setColor(Color.BLACK);
if (font!=null)
g.setFont(font);
else
g.setFont(textComponent.getFont());
// Initialize our static variables (these are used by our tab expander below).
tabSizeInSpaces = tabSize;
fontMetrics = g.getFontMetrics();
int fontHeight = fontMetrics.getHeight();
final int LINE_LENGTH_IN_PIXELS = (int)pageFormat.getImageableWidth();
final int MAX_LINES_PER_PAGE = (int)pageFormat.getImageableHeight() / fontHeight;
final int STARTING_LINE_NUMBER = MAX_LINES_PER_PAGE * pageIndex;
// Create our tab expander.
RPrintTabExpander tabExpander = new RPrintTabExpander();
// The (x,y) coordinate to print at (in pixels, not characters).
// Since y is the baseline of where we'll start printing (not the top-left
// corner), we offset it by the font's ascent ( + 1 just for good measure).
xOffset = (int)pageFormat.getImageableX();
int y = (int)pageFormat.getImageableY() + fontMetrics.getAscent() + 1;
// A counter to keep track of the number of lines that WOULD HAVE been printed if we were printing all lines.
int numPrintedLines = 0;
// Keep going while there are more lines in the document.
Document doc = textComponent.getDocument();
rootElement = doc.getDefaultRootElement();
numDocLines = rootElement.getElementCount(); // The number of lines in our document.
currentDocLineNumber = 0; // The line number of the document we're currently on.
int startingOffset = 0; // Used when a line is so long it has to be wrapped.
while (currentDocLineNumber<numDocLines) {
Segment currentLineSegment = new Segment();
// Get the current line (as an Element), and its starting and ending offset in doc.
Element currentLine = rootElement.getElement(currentDocLineNumber);
int currentLineStart = currentLine.getStartOffset();
int currentLineEnd = currentLine.getEndOffset();
// Put the chars of this line in currentLineSegment, but only starting at our desired offset
// (because this line may be the second part of a wrapped line, so we'd start after the part
// that has already been printed).
try {
doc.getText(currentLineStart+startingOffset, currentLineEnd-(currentLineStart+startingOffset),
currentLineSegment);
} catch (BadLocationException ble) {
System.err.println("BadLocationException in print (where there shouldn't be one!): " + ble);
return Printable.NO_SUCH_PAGE;
}
// Remove any spaces and/or tabs from the end of the segment (would cause problems if you left 'em).
currentLineSegment = removeEndingWhitespace(currentLineSegment);
// Figger out how long the line is, in pixels.
int currentLineLengthInPixels = Utilities.getTabbedTextWidth(currentLineSegment, fontMetrics, 0, tabExpander, 0);
//System.err.println("'" + currentLineSegment + "' - " + currentLineLengthInPixels + "/" + LINE_LENGTH_IN_PIXELS);
// If it'll fit by itself on a printed line, great.
if (currentLineLengthInPixels <= LINE_LENGTH_IN_PIXELS) {
currentDocLineNumber += 1; // We (will) have printed one more line from the document.
startingOffset = 0; // Start at the first character in the new document line.
}
// If it won't fit on a printed line by itself (i.e., it needs to be wrapped)...
else {
// Loop while the current line is too long to fit on a printed line.
int currentPos = -1;
while (currentLineLengthInPixels > LINE_LENGTH_IN_PIXELS) {
//System.err.println("'" + currentLineSegment + "' - " + currentLineLengthInPixels + "/" + LINE_LENGTH_IN_PIXELS);
// Remove any spaces and/or tabs from the end of the segment (would cause problems if you left 'em).
currentLineSegment = removeEndingWhitespace(currentLineSegment);
// currentPos will be the last position in the current text of a "line break character."
currentPos = -1;
String currentLineString = currentLineSegment.toString();
for (int i=0; i<breakChars.length; i++) {
int pos = currentLineString.lastIndexOf(breakChars[i]) + 1; // SO WE INCLUDE THE CHARACTER ON THE LINE.
//if (pos>-1 && pos>currentPos)
// currentPos = pos;
if (pos>0 && pos>currentPos & pos!=currentLineString.length())
currentPos = pos;
}
// If we didn't find a line break character, we'll simply break the line at
// the last character that fits on a printed line.
// So here, we set currentPos to be the position of the last character that fits
// on the current printed line.
if (currentPos == -1) {
// Fix currentLineSegment so that it contains exactly enough text to fit in
// LINE_LENGTH_IN_PIXELS pixels...
currentPos = 0;
do {
currentPos++;
try {
doc.getText(currentLineStart+startingOffset, currentPos, currentLineSegment);
} catch (BadLocationException ble) {
System.err.println(ble);
return Printable.NO_SUCH_PAGE;
}
currentLineLengthInPixels = Utilities.getTabbedTextWidth(currentLineSegment, fontMetrics, 0, tabExpander, 0);
} while (currentLineLengthInPixels <= LINE_LENGTH_IN_PIXELS);
currentPos--;
}
try {
doc.getText((currentLineStart+startingOffset), currentPos, currentLineSegment);
} catch (BadLocationException ble) {
System.err.println("BadLocationException in print (a): " + ble);
System.err.println("==> currentLineStart: " + currentLineStart + "; startingOffset: " + startingOffset + "; currentPos: " + currentPos);
System.err.println("==> Range: " + (currentLineStart+startingOffset) + " - " + (currentLineStart+startingOffset+currentPos));
return Printable.NO_SUCH_PAGE;
}
currentLineLengthInPixels = Utilities.getTabbedTextWidth(currentLineSegment, fontMetrics, 0, tabExpander, 0);
} // End of while (currentLineLengthInPixels > LINE_LENGTH_IN_PIXELS).
startingOffset += currentPos; // Where to start (offset from line's start), since this line wraps.
} // End of else.
numPrintedLines++;
if (numPrintedLines>STARTING_LINE_NUMBER) {
//g.drawString(currentLineSegment.toString(), xOffset,y);
Utilities.drawTabbedText(currentLineSegment, xOffset,y, g, tabExpander, 0);
y += fontHeight;
if (numPrintedLines==STARTING_LINE_NUMBER+MAX_LINES_PER_PAGE)
return Printable.PAGE_EXISTS;
}
}
// Now, the whole document has been "printed." Decide if this page had any text on it or not.
if (numPrintedLines > STARTING_LINE_NUMBER)
return Printable.PAGE_EXISTS;
return Printable.NO_SUCH_PAGE;
}
/*****************************************************************************/
/**
* Removes any spaces or tabs from the end of the segment.
*
* @param segment The segment from which to remove tailing whitespace.
* @return <code>segment</code> with trailing whitespace removed.
*/
private static Segment removeEndingWhitespace(Segment segment) {
int toTrim = 0;
char currentChar = segment.setIndex(segment.getEndIndex()-1);
while ((currentChar==' ' || currentChar=='\t') && currentChar!=Segment.DONE) {
toTrim++;
currentChar = segment.previous();
}
String stringVal = segment.toString();
String newStringVal = stringVal.substring(0,stringVal.length()-toTrim);
return new Segment(newStringVal.toCharArray(), 0, newStringVal.length());
}
/*****************************************************************************/
/******************* PRIVATE INNER CLASSES ***********************************/
/*****************************************************************************/
/**
* A tab expander for the document currently being printed with the
* font being used for the printing.
*/
private static class RPrintTabExpander implements TabExpander {
RPrintTabExpander() {
}
public float nextTabStop(float x, int tabOffset) {
if (tabSizeInSpaces == 0)
return x;
int tabSizeInPixels = tabSizeInSpaces * fontMetrics.charWidth(' ');
int ntabs = (((int) x) - xOffset) / tabSizeInPixels;
return xOffset + ((ntabs + 1) * tabSizeInPixels);
}
}
/*****************************************************************************/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -