001: //The contents of this file are subject to the Mozilla Public License Version 1.1
002: //(the "License"); you may not use this file except in compliance with the
003: //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
004: //
005: //Software distributed under the License is distributed on an "AS IS" basis,
006: //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
007: //for the specific language governing rights and
008: //limitations under the License.
009: //
010: //The Original Code is "The Columba Project"
011: //
012: //The Initial Developers of the Original Code are Frederik Dietz and Timo Stich.
013: //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
014: //
015: //All Rights Reserved.
016: package org.columba.core.print;
017:
018: import java.awt.Color;
019: import java.awt.Font;
020: import java.awt.Graphics2D;
021: import java.awt.font.FontRenderContext;
022: import java.awt.font.LineBreakMeasurer;
023: import java.awt.font.TextAttribute;
024: import java.awt.font.TextLayout;
025: import java.awt.geom.Point2D;
026: import java.text.AttributedCharacterIterator;
027: import java.text.AttributedString;
028: import java.util.Iterator;
029: import java.util.List;
030: import java.util.Vector;
031:
032: public class cParagraph extends cPrintObject {
033: public static final int LEFT = 0;
034: public static final int CENTER = 1;
035: public static final int RIGHT = 2;
036: public static final int BLOCK = 3;
037: private String original;
038: private List paragraphs;
039: private int alignment;
040: private Font font;
041:
042: public cParagraph() {
043: super ();
044: paragraphs = new Vector();
045:
046: alignment = 0;
047:
048: font = new Font("Default", Font.PLAIN, 10);
049: }
050:
051: public void setFontStyle(int style) {
052: font = font.deriveFont(style);
053:
054: updateFont();
055: }
056:
057: public void setFontSize(float size) {
058: font = font.deriveFont(size);
059: updateFont();
060: }
061:
062: private void updateFont() {
063: for (Iterator it = paragraphs.iterator(); it.hasNext();) {
064: ((AttributedString) it.next()).addAttribute(
065: TextAttribute.FONT, font);
066:
067: // for( int i=0; i<paragraphs.size(); i++ ) {
068: // ((AttributedString)paragraphs.get(i)).addAttribute(TextAttribute.FONT, font);
069: }
070: }
071:
072: /**
073: * Inserts space between newlines if necessary to avoid
074: * empty lines. Also inserts a space at the beginning if
075: * the text starts with a newline.
076: * @param t Text to validate
077: * @return Validated text
078: */
079: private String validate(String t) {
080: if ((t.indexOf("\n\n") == -1) && (!t.startsWith("\n"))) {
081: return t;
082: }
083:
084: StringBuffer result = new StringBuffer();
085:
086: // ensure that the text does not start with a newline
087: if (t.startsWith("\n")) {
088: result.append(' ');
089: }
090:
091: // insert space btw. double newlines
092: char last = ' ';
093:
094: for (int i = 0; i < t.length(); i++) {
095: if ((t.charAt(i) == '\n') && (last == '\n')) {
096: result.append(" \n");
097: } else {
098: result.append(t.charAt(i));
099: }
100:
101: last = t.charAt(i);
102: }
103:
104: return result.toString();
105: }
106:
107: public void setText(String t) {
108: original = validate(t);
109:
110: paragraphs.clear();
111:
112: StringBuffer buffer = new StringBuffer();
113:
114: AttributedString act;
115:
116: for (int i = 0; i < original.length(); i++) {
117: if (original.charAt(i) == '\n') {
118: act = new AttributedString(buffer.toString());
119: act.addAttribute(TextAttribute.FONT, font);
120: paragraphs.add(act);
121: buffer = new StringBuffer();
122: } else {
123: buffer.append(original.charAt(i));
124: }
125: }
126:
127: if (buffer.length() != 0) {
128: act = new AttributedString(buffer.toString());
129: act.addAttribute(TextAttribute.FONT, font);
130: paragraphs.add(act);
131: }
132: }
133:
134: public void setTextAlignment(int v) {
135: alignment = v;
136: }
137:
138: public void print(Graphics2D g) {
139: computePositionAndSize();
140:
141: Color saveForeground = g.getColor();
142:
143: g.setColor(color);
144:
145: switch (alignment) {
146: case LEFT:
147: renderLeftAligned(g);
148:
149: break;
150:
151: case RIGHT:
152: renderRightAligned(g);
153:
154: break;
155:
156: case CENTER:
157: renderCenterAligned(g);
158:
159: break;
160: }
161:
162: g.setColor(saveForeground);
163: }
164:
165: private void renderLeftAligned(Graphics2D g) {
166: Point2D.Double pen = getDrawingOrigin().getPoint2D();
167:
168: double width = getDrawingSize().getWidth().getPoints();
169:
170: for (Iterator it = paragraphs.iterator(); it.hasNext();) {
171: LineBreakMeasurer lineBreaker = new LineBreakMeasurer(
172: ((AttributedString) it.next()).getIterator(),
173: new FontRenderContext(null, true, true));
174:
175: // for (int i = 0; i < paragraphs.size(); i++) {
176: // LineBreakMeasurer lineBreaker =
177: // new LineBreakMeasurer(
178: // ((AttributedString) paragraphs.get(i)).getIterator(),
179: // new FontRenderContext(null, true, true));
180: TextLayout layout;
181:
182: while ((layout = lineBreaker.nextLayout((float) width)) != null) {
183: pen.y += layout.getAscent();
184:
185: layout.draw(g, (float) pen.x, (float) pen.y);
186:
187: pen.y += (layout.getDescent() + layout.getLeading());
188: }
189: }
190: }
191:
192: private void renderRightAligned(Graphics2D g) {
193: Point2D.Double pen = getDrawingOrigin().getPoint2D();
194:
195: double width = getDrawingSize().getWidth().getPoints();
196:
197: for (Iterator it = paragraphs.iterator(); it.hasNext();) {
198: LineBreakMeasurer lineBreaker = new LineBreakMeasurer(
199: ((AttributedString) it.next()).getIterator(),
200: new FontRenderContext(null, true, true));
201:
202: // for (int i = 0; i < paragraphs.size(); i++) {
203: // LineBreakMeasurer lineBreaker =
204: // new LineBreakMeasurer(
205: // ((AttributedString) paragraphs.get(i)).getIterator(),
206: // new FontRenderContext(null, true, true));
207: TextLayout layout;
208: float layoutX;
209:
210: while ((layout = lineBreaker.nextLayout((float) width)) != null) {
211: pen.y += layout.getAscent();
212:
213: layoutX = ((float) (pen.x + width))
214: - layout.getAdvance();
215:
216: layout.draw(g, layoutX, (float) pen.y);
217:
218: pen.y += (layout.getDescent() + layout.getLeading());
219: }
220: }
221: }
222:
223: private void renderCenterAligned(Graphics2D g) {
224: Point2D.Double pen = getDrawingOrigin().getPoint2D();
225:
226: double width = getDrawingSize().getWidth().getPoints();
227:
228: for (Iterator it = paragraphs.iterator(); it.hasNext();) {
229: LineBreakMeasurer lineBreaker = new LineBreakMeasurer(
230: ((AttributedString) it.next()).getIterator(),
231: new FontRenderContext(null, true, true));
232:
233: // for (int i = 0; i < paragraphs.size(); i++) {
234: // LineBreakMeasurer lineBreaker =
235: // new LineBreakMeasurer(
236: // ((AttributedString) paragraphs.get(i)).getIterator(),
237: // new FontRenderContext(null, true, true));
238: TextLayout layout;
239:
240: float layoutX;
241:
242: while ((layout = lineBreaker.nextLayout((float) width)) != null) {
243: pen.y += layout.getAscent();
244:
245: layoutX = ((float) (pen.x + (width / 2)))
246: - (layout.getAdvance() / 2);
247:
248: layout.draw(g, layoutX, (float) pen.y);
249:
250: pen.y += (layout.getDescent() + layout.getLeading());
251: }
252: }
253: }
254:
255: public cSize getSize(cUnit w) {
256: cCmUnit textHeight = new cCmUnit();
257: float maxAdvance = -1;
258:
259: Point2D.Double pen = new Point2D.Double(0.0, 0.0);
260:
261: double width = w.sub(leftMargin).sub(rightMargin).getPoints();
262:
263: for (Iterator it = paragraphs.iterator(); it.hasNext();) {
264: LineBreakMeasurer lineBreaker = new LineBreakMeasurer(
265: ((AttributedString) it.next()).getIterator(),
266: new FontRenderContext(null, true, true));
267:
268: // for (int i = 0; i < paragraphs.size(); i++) {
269: // LineBreakMeasurer lineBreaker =
270: // new LineBreakMeasurer(
271: // ((AttributedString) paragraphs.get(i)).getIterator(),
272: // new FontRenderContext(null, true, true));
273: TextLayout layout;
274:
275: while ((layout = lineBreaker.nextLayout((float) width)) != null) {
276: pen.y += (layout.getAscent() + layout.getDescent() + layout
277: .getLeading());
278:
279: if (layout.getAdvance() > maxAdvance) {
280: maxAdvance = layout.getAdvance();
281: }
282: }
283: }
284:
285: textHeight.setPoints(pen.y);
286: textHeight.addI(topMargin);
287: textHeight.addI(bottomMargin);
288:
289: cCmUnit bwidth = new cCmUnit();
290: bwidth.setPoints(maxAdvance);
291: bwidth.addI(leftMargin);
292: bwidth.addI(rightMargin);
293:
294: return new cSize(bwidth, textHeight);
295: }
296:
297: public cPrintObject breakBlock(cUnit w, cUnit maxHeight) {
298: AttributedCharacterIterator it;
299: int lastPos;
300: int pos = 0;
301:
302: cParagraph remainParagraph = null;
303:
304: Point2D.Double pen = new Point2D.Double(0.0, topMargin
305: .getPoints());
306:
307: double width = w.sub(leftMargin).sub(rightMargin).getPoints();
308:
309: for (Iterator iter = paragraphs.iterator(); iter.hasNext();) {
310: it = ((AttributedString) iter.next()).getIterator();
311:
312: // for (int i = 0; i < paragraphs.size(); i++) {
313: // it = ((AttributedString) paragraphs.get(i)).getIterator();
314: LineBreakMeasurer lineBreaker = new LineBreakMeasurer(it,
315: new FontRenderContext(null, true, true));
316:
317: TextLayout layout;
318: lastPos = 0;
319:
320: while ((layout = lineBreaker.nextLayout((float) width)) != null) {
321: pen.y += (layout.getAscent() + layout.getDescent() + layout
322: .getLeading());
323:
324: if (pen.y > maxHeight.getPoints()) {
325: remainParagraph = new cParagraph();
326: remainParagraph.setTextAlignment(alignment);
327: remainParagraph.setTopMargin(topMargin);
328: remainParagraph.setLeftMargin(leftMargin);
329: remainParagraph.setRightMargin(rightMargin);
330:
331: topMargin = new cCmUnit();
332:
333: remainParagraph.setText(original.substring(0, pos
334: + lastPos));
335: this .setText(original.substring(pos + lastPos));
336:
337: return remainParagraph;
338: }
339:
340: lastPos += layout.getCharacterCount();
341: }
342:
343: pos += (it.getEndIndex() + 1);
344: }
345:
346: return remainParagraph;
347: }
348:
349: public Font getFont() {
350: return font;
351: }
352:
353: public void setFont(Font font) {
354: this.font = font;
355: updateFont();
356: }
357: }
|