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;
+    }
+}