Mercurial > projects > dwt-addons
diff dwtx/jface/internal/text/link/contentassist/LineBreakingReader.d @ 129:eb30df5ca28b
Added JFace Text sources
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 23 Aug 2008 19:10:48 +0200 |
parents | |
children | c4fb132a086c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/internal/text/link/contentassist/LineBreakingReader.d Sat Aug 23 19:10:48 2008 +0200 @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module dwtx.jface.internal.text.link.contentassist.LineBreakingReader; + +import dwt.dwthelper.utils; + + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; + +import com.ibm.icu.text.BreakIterator; + +import dwt.graphics.GC; + +/* + * Not a real reader. Could change if requested + */ +public class LineBreakingReader { + + private BufferedReader fReader; + private GC fGC; + private int fMaxWidth; + + private String fLine; + private int fOffset; + + private BreakIterator fLineBreakIterator; + private bool fBreakWords; + + /** + * Creates a reader that breaks an input text to fit in a given width. + * + * @param reader Reader of the input text + * @param gc The graphic context that defines the currently used font sizes + * @param maxLineWidth The max width (pixels) where the text has to fit in + */ + public LineBreakingReader(Reader reader, GC gc, int maxLineWidth) { + fReader= new BufferedReader(reader); + fGC= gc; + fMaxWidth= maxLineWidth; + fOffset= 0; + fLine= null; + fLineBreakIterator= BreakIterator.getLineInstance(); + fBreakWords= true; + } + + public bool isFormattedLine() { + return fLine !is null; + } + + /** + * Reads the next line. The lengths of the line will not exceed the given maximum + * width. + * + * @return the next line + * @throws IOException + */ + public String readLine() throws IOException { + if (fLine is null) { + String line= fReader.readLine(); + if (line is null) + return null; + + int lineLen= fGC.textExtent(line).x; + if (lineLen < fMaxWidth) { + return line; + } + fLine= line; + fLineBreakIterator.setText(line); + fOffset= 0; + } + int breakOffset= findNextBreakOffset(fOffset); + String res; + if (breakOffset !is BreakIterator.DONE) { + res= fLine.substring(fOffset, breakOffset); + fOffset= findWordBegin(breakOffset); + if (fOffset is fLine.length()) { + fLine= null; + } + } else { + res= fLine.substring(fOffset); + fLine= null; + } + return res; + } + + private int findNextBreakOffset(int currOffset) { + int currWidth= 0; + int nextOffset= fLineBreakIterator.following(currOffset); + while (nextOffset !is BreakIterator.DONE) { + String word= fLine.substring(currOffset, nextOffset); + int wordWidth= fGC.textExtent(word).x; + int nextWidth= wordWidth + currWidth; + if (nextWidth > fMaxWidth) { + if (currWidth > 0) + return currOffset; + + if (!fBreakWords) + return nextOffset; + + // need to fit into fMaxWidth + int length= word.length(); + while (length >= 0) { + length--; + word= word.substring(0, length); + wordWidth= fGC.textExtent(word).x; + if (wordWidth + currWidth < fMaxWidth) + return currOffset + length; + } + return nextOffset; + } + currWidth= nextWidth; + currOffset= nextOffset; + nextOffset= fLineBreakIterator.next(); + } + return nextOffset; + } + + private int findWordBegin(int idx) { + while (idx < fLine.length() && Character.isWhitespace(fLine.charAt(idx))) { + idx++; + } + return idx; + } +}