001: package net.xoetrope.xui;
002:
003: import java.awt.Component;
004: import java.awt.Graphics;
005: import java.awt.Color;
006: import java.awt.Font;
007: import java.awt.FontMetrics;
008: import java.awt.Image;
009: import java.awt.Dimension;
010:
011: /**
012: * A mixin class for rendering multiline text.
013: * <p>Copyright: Copyright (c) Xoetrope Ltd., 1998-2003<br>
014: * License: see license.txt
015: * $Revision: 1.25 $
016: */
017: public class XTextRenderer {
018: /**
019: * Left align the text
020: */
021: public static final int LEFT = 0;
022:
023: /**
024: * Right align the text
025: */
026: public static final int RIGHT = 1;
027:
028: /**
029: * Center the text
030: */
031: public static final int CENTER = 2;
032:
033: private int alignment = LEFT;
034: private boolean transparent = false;
035: private XTextDecorator textDecorator;
036:
037: /**
038: * Add a text decorator
039: * @param the decorator
040: */
041: public void setTextDecorator(XTextDecorator decorator) {
042: textDecorator = decorator;
043: }
044:
045: /**
046: * Paints the text on behalf of a component
047: * @param comp the owner component
048: * @param g the graphics context
049: * @param text the text to render.
050: */
051: public void paintText(Component comp, Graphics g, String text) {
052: int width = comp.getSize().width;
053: int height = comp.getSize().height;
054:
055: // Erase the image
056: if (!transparent) {
057: g.setColor(comp.getBackground());
058: g.fillRect(0, 0, width + 1, height + 1);
059: }
060:
061: if (text == null)
062: return;
063:
064: Font f;
065: FontMetrics fm;
066: f = comp.getFont();
067: if (f.getSize() == 0)
068: f = new Font(null, 0, 12);
069: g.setFont(f);
070: fm = g.getFontMetrics(f);
071:
072: // Draw the question text over multiple lines
073: g.setColor(comp.getForeground());
074: int start = 0;
075: int end = 0;
076: String line;
077: int lineNum = 1;
078: do {
079: boolean drawLine = false;
080:
081: // Extend the string by a word (to the next space, if any)
082: int endNewLine = text.indexOf('\n', end + 1);
083: end = text.indexOf(' ', end + 1);
084: if ((endNewLine > 0) && (endNewLine < end)) {
085: drawLine = true;
086: end = endNewLine;
087: }
088: String ss;
089: if (end > 0)
090: ss = text.substring(start, end);
091: else {
092: ss = text.substring(start);
093: drawLine = true;
094: }
095:
096: // Does the next word fit in?
097: if (fm.stringWidth(ss) < width)
098: line = ss;
099: else {
100: int inc = ss.lastIndexOf(' ');
101: end = start + inc;
102: if (inc < 0) {
103: line = ss;
104: end += ss.length();
105: } else if (end >= 0)
106: line = ss = text.substring(start, end);
107: else
108: line = ss = text.substring(start);
109:
110: drawLine = true;
111: }
112:
113: if (drawLine) {
114: if (alignment == LEFT)
115: drawString(g, ss, 0, lineNum * fm.getHeight());
116: else if (alignment == RIGHT)
117: drawString(g, ss, width - fm.stringWidth(ss),
118: lineNum * fm.getHeight());
119: else
120: drawString(g, ss, (width - fm.stringWidth(ss)) / 2,
121: lineNum * fm.getHeight());
122: lineNum++;
123: start = end + 1;
124: }
125: } while (end >= 0);
126:
127: // If no text drawn, then do it now
128: if ((start == 0) && (lineNum == 1)) {
129: if (alignment == LEFT)
130: drawString(g, text, 0, fm.getAscent());
131: else if (alignment == RIGHT)
132: drawString(g, text, width - fm.stringWidth(text), fm
133: .getHeight());
134: else
135: drawString(g, text, (width - fm.stringWidth(text)) / 2,
136: fm.getHeight());
137: }
138: }
139:
140: public void drawString(Graphics g, String str, int x, int y) {
141: g.drawString(str, x, y);
142: if (textDecorator != null)
143: textDecorator.textPainted(g, str, x, y);
144: }
145:
146: /**
147: * Sets the alignment of the text.
148: * @param b RIGHT to right align the text, LEFT for left alignment or CENTERED for centered text
149: */
150: public void setAlignment(int b) {
151: alignment = b;
152: }
153:
154: /**
155: * Get the alignment value for this renderer
156: * @return the alignment value
157: */
158: public int getAlignment() {
159: return alignment;
160: }
161:
162: /**
163: * Sets the transparency of the text.
164: * @param b true to make text transparent
165: */
166: public void setTransparent(boolean b) {
167: transparent = b;
168: }
169:
170: /**
171: * Gets the preferred size of this component.
172: * @return a dimension object indicating this component's preferred size
173: * @see #getMinimumSize
174: * @see LayoutManager
175: */
176: public Dimension getPreferredSize(Component comp, String text) {
177: Font f = comp.getFont();
178: if ((f == null) || (f.getSize() == 0))
179: f = new Font(null, 0, 12);
180:
181: int size = f.getSize();
182: int length = text == null ? 1 : text.length();
183: return new Dimension((size * length / 2) + size, 2 * size);
184: }
185: }
|