001: /*******************************************************************************
002: * Copyright (c) 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.util;
011:
012: import java.io.BufferedReader;
013: import java.io.IOException;
014: import java.io.Reader;
015:
016: import com.ibm.icu.text.BreakIterator;
017: import org.eclipse.swt.graphics.GC;
018:
019: /**
020: * LineBreakingReader
021: * Derived from org.eclipse.jdt.internal.ui.text.LineBreakingReader
022: */
023: public class LineBreakingReader {
024:
025: private BufferedReader fReader;
026:
027: private GC fGC;
028:
029: private int fMaxWidth;
030:
031: private String fLine;
032:
033: private int fOffset;
034:
035: private BreakIterator fLineBreakIterator;
036:
037: private boolean fBreakWords;
038:
039: /**
040: * Creates a reader that breaks an input text to fit in a given width.
041: *
042: * @param reader
043: * Reader of the input text
044: * @param gc
045: * The graphic context that defines the currently used font sizes
046: * @param maxLineWidth
047: * The max width (pixels) where the text has to fit in
048: */
049: public LineBreakingReader(Reader reader, GC gc, int maxLineWidth) {
050: fReader = new BufferedReader(reader);
051: fGC = gc;
052: fMaxWidth = maxLineWidth;
053: fOffset = 0;
054: fLine = null;
055: fLineBreakIterator = BreakIterator.getLineInstance();
056: fBreakWords = true;
057: }
058:
059: public boolean isFormattedLine() {
060: return fLine != null;
061: }
062:
063: /**
064: * Reads the next line. The lengths of the line will not exceed the given
065: * maximum width.
066: *
067: * @return the next line
068: * @throws IOException
069: */
070: public String readLine() throws IOException {
071: if (fLine == null) {
072: String line = fReader.readLine();
073: if (line == null)
074: return null;
075:
076: int lineLen = fGC.textExtent(line).x;
077: if (lineLen < fMaxWidth) {
078: return line;
079: }
080: fLine = line;
081: fLineBreakIterator.setText(line);
082: fOffset = 0;
083: }
084: int breakOffset = findNextBreakOffset(fOffset);
085: String res;
086: if (breakOffset != BreakIterator.DONE) {
087: res = fLine.substring(fOffset, breakOffset);
088: fOffset = findWordBegin(breakOffset);
089: if (fOffset == fLine.length()) {
090: fLine = null;
091: }
092: } else {
093: res = fLine.substring(fOffset);
094: fLine = null;
095: }
096: return res;
097: }
098:
099: private int findNextBreakOffset(int currOffset) {
100: int currWidth = 0;
101: int nextOffset = fLineBreakIterator.following(currOffset);
102: while (nextOffset != BreakIterator.DONE) {
103: String word = fLine.substring(currOffset, nextOffset);
104: int wordWidth = fGC.textExtent(word).x;
105: int nextWidth = wordWidth + currWidth;
106: if (nextWidth > fMaxWidth) {
107: if (currWidth > 0)
108: return currOffset;
109:
110: if (!fBreakWords)
111: return nextOffset;
112:
113: // need to fit into fMaxWidth
114: int length = word.length();
115: while (length >= 0) {
116: length--;
117: word = word.substring(0, length);
118: wordWidth = fGC.textExtent(word).x;
119: if (wordWidth + currWidth < fMaxWidth)
120: return currOffset + length;
121: }
122: return nextOffset;
123: }
124: currWidth = nextWidth;
125: currOffset = nextOffset;
126: nextOffset = fLineBreakIterator.next();
127: }
128: return nextOffset;
129: }
130:
131: private int findWordBegin(int idx) {
132: while (idx < fLine.length()
133: && Character.isWhitespace(fLine.charAt(idx))) {
134: idx++;
135: }
136: return idx;
137: }
138: }
|