/* This class implements some utility functions for drawing text within * an arbitrary Rectangle, complete with word-wrap and a choice of * justification parameters. All of the constants and methods in this * class are static, so there is never any need to actually create an * instance of TextUtils -- you can just call the methods directly. * * Author: Jeremy Baer * Copyright (c) 2000 Jeremy Baer * Permission is hereby granted for use in non-commercial, educational * activities only. */ import java.awt.*; public class TextUtils { // the following constants may be used to specify justification styles public static final int TEXT_JUST_LEFT = 0; public static final int TEXT_JUST_RIGHT = 1; public static final int TEXT_JUST_CENTER = 2; ///////////////////////////////////////////////////////////////// // formatString ///////////////////////////////////////////////////////////////// /** * This method draws a String in the specified Rectangle, using * the specified Font, and justification. This method calls * formatText (see below) to do its work. However, this method * is the one you will normally want to use, since you will * usually be dealing with a String as opposed to an array of * characters. * * @param Graphics The graphics objec to draw on * @param Rectangle The rect to draw the text in * @param Font The font to use * @param int Justification code (see above) * @param String The string to draw * * @return None */////////////////////////////////////////////////////////////// public static void formatString(Graphics g, Rectangle rect, Font f, int just, String aStr) { char text[]; text = new char[aStr.length()]; aStr.getChars(0, aStr.length(), text, 0); formatText(g, rect, f, just, text, 0, aStr.length()); } ///////////////////////////////////////////////////////////////// // formatText ///////////////////////////////////////////////////////////////// /** * This method draws an array of characters in a formatted way, * using a specified rect, font, justification, etc. This is * sort of a lower-level method which actually does the work * for the formatString method. Typically you will not need to * call this method directly. * * @param Graphics The graphics objec to draw on * @param Rectangle The rect to draw the text in * @param Font The font to use * @param int Justification code (see above) * @param char[] The array of characters * @param int The index to start at * @param int The length of the character array * * @return None */////////////////////////////////////////////////////////////// public static void formatText(Graphics g, Rectangle rect, Font f, int just, char text[], int startInd, int length) { int start = startInd, count = startInd, oldcount = 0; int newline = 0; int lineCount = 0; // bail if we don't really have any space to draw in if(rect.width <= 1 || rect.height == 0) return; g.setFont(f); FontMetrics fm = g.getFontMetrics(); int fontHeight = fm.getHeight(); int fontAscent = fm.getAscent(); while(count <= length - 1) { /* remove white space (sometimes) */ if(lineCount != 0) { if((text[count] == ' ' || text[count] == '\t') && text[count - 1] != '\n' && text[count - 1] != '\r') { while(text[count] == ' ' || text[count] == '\t') count++; } } start = count; /* figure out the next line of text */ while(fm.charsWidth(text, start, count - start) <= rect.width && count < length - 1) { newline = 0; oldcount = count; if(text[count] == '\n' || text[count] == '\r' && count < length - 1) { newline = 1; count++; break; } /* go through white space */ while((text[count] == ' ' || text[count] == '\t') && count < length - 1) count++; // see if the white space is gonna be too wide if(fm.charsWidth(text, start, count - start) > rect.width) oldcount = count; /* get a word */ while(text[count] != ' ' && text[count] != '\t' && text[count] != '\n' && text[count] != '\r' && count < length - 1) { count++; /* if the only word on this line is wider than the rect, draw as much of it as we can */ if(fm.charsWidth(text, start, count - start) > rect.width && text[count] != '\n' && text[count] != '\r' && oldcount == start) { if(count != start + 1) count--; break; } } /* make the line break if we come to a CR or newline */ if(text[count] == '\n' || text[count] == '\r' && count < length - 1) { newline = 1; count++; break; } } if(fm.charsWidth(text, start, count - start) > rect.width && !((text[Math.max(count - 1,0)] == '\n' || text[Math.max(count - 1,0)] == '\r') && count == start + 1)) { count = oldcount; newline = 0; } if(count == length - 1 && text[Math.max(count - 1,0)] != '\n' && text[Math.max(count - 1,0)] != '\r') count += 1; if(count == start) count += 2; /* draw the text */ if(text[start] != '\n' && text[start] != '\r') { switch(just) { case TEXT_JUST_LEFT: g.drawChars(text, start, count - start - newline, rect.x, rect.y + fontAscent + (lineCount * fontHeight)); break; case TEXT_JUST_RIGHT: g.drawChars(text, start, count - start - newline, rect.x + rect.width - fm.charsWidth(text, start, count - start), rect.y + fontAscent + (lineCount * fontHeight)); break; case TEXT_JUST_CENTER: g.drawChars(text, start, count - start - newline, rect.x + ((rect.width - fm.charsWidth(text, start, count - start)) / 2), rect.y + fontAscent + (lineCount * fontHeight)); break; default: break; } } lineCount++; // bail out if we don't need to draw the rest if(lineCount * fontHeight >= rect.height) break; else if((lineCount + 1) * fontHeight >= rect.height && lineCount > 0) break; } } }