### Eclipse Workspace Patch 1.0 #P org.eclipse.draw2d Index: src/org/eclipse/draw2d/text/FlowUtilities.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/plugins/org.eclipse.draw2d/src/org/eclipse/draw2d/text/FlowUtilities.java,v retrieving revision 1.56 diff -u -r1.56 FlowUtilities.java --- src/org/eclipse/draw2d/text/FlowUtilities.java 4 Apr 2006 12:43:12 -0000 1.56 +++ src/org/eclipse/draw2d/text/FlowUtilities.java 2 Aug 2007 20:49:05 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. + * Copyright (c) 2000, 2007 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 @@ -15,22 +15,24 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.TextLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.draw2d.FigureUtilities; +import org.eclipse.draw2d.geometry.Dimension; /** * Utility class for FlowFigures. * @author hudsonr * @since 2.1 */ -class FlowUtilities - extends FigureUtilities +public class FlowUtilities { interface LookAhead { - int getWidth(); + int getWidth(); } private static int ELLIPSIS_SIZE; private static final BreakIterator INTERNAL_LINE_BREAK = BreakIterator.getLineInstance(); @@ -39,64 +41,75 @@ static final BreakIterator LINE_BREAK = BreakIterator.getLineInstance(); static boolean canBreakAfter(char c) { - boolean result = Character.isWhitespace(c) || c == '-'; - if (!result && (c < 'a' || c > 'z')) { - // chinese characters and such would be caught in here - // LINE_BREAK is used here because INTERNAL_LINE_BREAK might be in use - LINE_BREAK.setText(c + "a"); //$NON-NLS-1$ - result = LINE_BREAK.isBoundary(1); - } - return result; + boolean result = Character.isWhitespace(c) || c == '-'; + if (!result && (c < 'a' || c > 'z')) { + // chinese characters and such would be caught in here + // LINE_BREAK is used here because INTERNAL_LINE_BREAK might be in use + LINE_BREAK.setText(c + "a"); //$NON-NLS-1$ + result = LINE_BREAK.isBoundary(1); + } + return result; } private static int findFirstDelimeter(String string) { - int macNL = string.indexOf('\r'); - int unixNL = string.indexOf('\n'); - - if (macNL == -1) - macNL = Integer.MAX_VALUE; - if (unixNL == -1) - unixNL = Integer.MAX_VALUE; - - return Math.min(macNL, unixNL); + int macNL = string.indexOf('\r'); + int unixNL = string.indexOf('\n'); + + if (macNL == -1) + macNL = Integer.MAX_VALUE; + if (unixNL == -1) + unixNL = Integer.MAX_VALUE; + + return Math.min(macNL, unixNL); } -private static float getAverageCharWidth(TextFragmentBox fragment, Font font) { - if (fragment.getWidth() > 0 && fragment.length != 0) - return fragment.getWidth() / (float)fragment.length; - return getFontMetrics(font).getAverageCharWidth(); +/** + * Gets the average character width. + * + * @param fragment the supplied TextFragmentBox to use for calculation. + * if the length is 0 or if the width is or below 0, + * the average character width is taken from standard + * font metrics. + * @param font the font to use in case the TextFragmentBox conditions + * above are true. + * @return the average character width + */ +protected float getAverageCharWidth(TextFragmentBox fragment, Font font) { + if (fragment.getWidth() > 0 && fragment.length != 0) + return fragment.getWidth() / (float)fragment.length; + return FigureUtilities.getFontMetrics(font).getAverageCharWidth(); } static int getBorderAscent(InlineFlow owner) { - if (owner.getBorder() instanceof FlowBorder) { - FlowBorder border = (FlowBorder)owner.getBorder(); - return border.getInsets(owner).top; - } - return 0; + if (owner.getBorder() instanceof FlowBorder) { + FlowBorder border = (FlowBorder)owner.getBorder(); + return border.getInsets(owner).top; + } + return 0; } static int getBorderAscentWithMargin(InlineFlow owner) { - if (owner.getBorder() instanceof FlowBorder) { - FlowBorder border = (FlowBorder)owner.getBorder(); - return border.getTopMargin() + border.getInsets(owner).top; - } - return 0; + if (owner.getBorder() instanceof FlowBorder) { + FlowBorder border = (FlowBorder)owner.getBorder(); + return border.getTopMargin() + border.getInsets(owner).top; + } + return 0; } static int getBorderDescent(InlineFlow owner) { - if (owner.getBorder() instanceof FlowBorder) { - FlowBorder border = (FlowBorder)owner.getBorder(); - return border.getInsets(owner).bottom; - } - return 0; + if (owner.getBorder() instanceof FlowBorder) { + FlowBorder border = (FlowBorder)owner.getBorder(); + return border.getInsets(owner).bottom; + } + return 0; } static int getBorderDescentWithMargin(InlineFlow owner) { - if (owner.getBorder() instanceof FlowBorder) { - FlowBorder border = (FlowBorder)owner.getBorder(); - return border.getBottomMargin() + border.getInsets(owner).bottom; - } - return 0; + if (owner.getBorder() instanceof FlowBorder) { + FlowBorder border = (FlowBorder)owner.getBorder(); + return border.getBottomMargin() + border.getInsets(owner).bottom; + } + return 0; } /** @@ -108,10 +121,10 @@ * @since 3.1 */ static TextLayout getTextLayout() { - if (layout == null) - layout = new TextLayout(Display.getDefault()); - layout.setOrientation(SWT.LEFT_TO_RIGHT); - return layout; + if (layout == null) + layout = new TextLayout(Display.getDefault()); + layout.setOrientation(SWT.LEFT_TO_RIGHT); + return layout; } /** @@ -121,42 +134,36 @@ * @since 3.1 */ private static void initBidi(TextFragmentBox frag, String string, Font font) { - if (frag.requiresBidi()) { - TextLayout textLayout = getTextLayout(); - textLayout.setFont(font); - //$TODO need to insert overrides in front of string. - textLayout.setText(string); - } -} - -private static int measureString(TextFragmentBox frag, String string, int guess, Font font) { - if (frag.requiresBidi()) { - // The text and/or could have changed if the lookAhead was invoked. This will - // happen at most once. - TextLayout layout = getTextLayout(); - layout.setText(string); - layout.setFont(font); - return layout.getBounds(0, guess - 1).width; - } else - return getStringDimension(string.substring(0, guess), font).x; -} - -static void setupFragment(TextFragmentBox frag, Font f, String s) { - if (frag.getWidth() == -1 || frag.isTruncated()) { - int width; - if (s.length() == 0 || frag.length == 0) - width = 0; - else if (frag.requiresBidi()) { - TextLayout textLayout = getTextLayout(); - textLayout.setFont(f); - textLayout.setText(s); - width = textLayout.getBounds(0, frag.length - 1).width; - } else - width = getStringDimension(s.substring(0, frag.length), f).x; - if (frag.isTruncated()) - width += ELLIPSIS_SIZE; - frag.setWidth(width); - } + if (frag.requiresBidi()) { + TextLayout textLayout = getTextLayout(); + textLayout.setFont(font); + //$TODO need to insert overrides in front of string. + textLayout.setText(string); + } +} + +private int measureString(TextFragmentBox frag, String string, int guess, Font font) { + if (frag.requiresBidi()) { + // The text and/or could have changed if the lookAhead was invoked. This will + // happen at most once. + return getTextLayoutBounds(string, font, 0, guess - 1).width; + } else + return getStringExtents(string.substring(0, guess), font).width; +} + +void setupFragment(TextFragmentBox frag, Font f, String s) { + if (frag.getWidth() == -1 || frag.isTruncated()) { + int width; + if (s.length() == 0 || frag.length == 0) + width = 0; + else if (frag.requiresBidi()) { + width = getTextLayoutBounds(s, f, 0, frag.length - 1).width; + } else + width = getStringExtents(s.substring(0, frag.length), f).width; + if (frag.isTruncated()) + width += ELLIPSIS_SIZE; + frag.setWidth(width); + } } /** @@ -172,131 +179,131 @@ * @return the number of characters that will fit in the given space; can be 0 (eg., when * the first character of the given string is a newline) */ -public static int wrapFragmentInContext(TextFragmentBox frag, String string, - FlowContext context, LookAhead lookahead, Font font, int wrapping) { - frag.setTruncated(false); - int strLen = string.length(); - if (strLen == 0) { - frag.setWidth(-1); - frag.length = 0; - setupFragment(frag, font, string); - context.addToCurrentLine(frag); - return 0; - } - - INTERNAL_LINE_BREAK.setText(string); - - initBidi(frag, string, font); - float avgCharWidth = getAverageCharWidth(frag, font); - frag.setWidth(-1); - - /* - * Setup initial boundaries within the string. - */ - int absoluteMin = 0; - int max, min = 1; - if (wrapping == ParagraphTextLayout.WORD_WRAP_HARD) { - absoluteMin = INTERNAL_LINE_BREAK.next(); - while (absoluteMin > 0 && Character.isWhitespace(string.charAt(absoluteMin - 1))) - absoluteMin--; - min = Math.max(absoluteMin, 1); - } - int firstDelimiter = findFirstDelimeter(string); - if (firstDelimiter == 0) - min = max = 0; - else - max = Math.min(strLen, firstDelimiter) + 1; - - - int availableWidth = context.getRemainingLineWidth(); - int guess = 0, guessSize = 0; - - while (true) { - if ((max - min) <= 1) { - if (min == absoluteMin - && context.isCurrentLineOccupied() - && !context.getContinueOnSameLine() - && availableWidth < measureString(frag, string, min, font) - + ((min == strLen && lookahead != null) ? lookahead.getWidth() : 0) - ) { - context.endLine(); - availableWidth = context.getRemainingLineWidth(); - max = Math.min(strLen, firstDelimiter) + 1; - if ((max - min) <= 1) - break; - } else - break; - } - // Pick a new guess size - // New guess is the last guess plus the missing width in pixels - // divided by the average character size in pixels - guess += 0.5f + (availableWidth - guessSize) / avgCharWidth; - - if (guess >= max) guess = max - 1; - if (guess <= min) guess = min + 1; - - guessSize = measureString(frag, string, guess, font); - - if (guess == strLen - && lookahead != null - && !canBreakAfter(string.charAt(strLen - 1)) - && guessSize + lookahead.getWidth() > availableWidth) { - max = guess; - continue; - } - - if (guessSize <= availableWidth) { - min = guess; - frag.setWidth(guessSize); - if (guessSize == availableWidth) - max = guess + 1; - } else - max = guess; - } - - int result = min; - boolean continueOnLine = false; - if (min == strLen) { - //Everything fits - if (string.charAt(strLen - 1) == ' ') { - if (frag.getWidth() == -1) { - frag.length = result; - frag.setWidth(measureString(frag, string, result, font)); - } - if (lookahead.getWidth() > availableWidth - frag.getWidth()) { - frag.length = result - 1; - frag.setWidth(-1); - } else - frag.length = result; - } else { - continueOnLine = !canBreakAfter(string.charAt(strLen - 1)); - frag.length = result; - } - } else if (min == firstDelimiter) { - //move result past the delimiter - frag.length = result; - if (string.charAt(min) == '\r') { - result++; - if (++min < strLen && string.charAt(min) == '\n') - result++; - } else if (string.charAt(min) == '\n') - result++; - } else if (string.charAt(min) == ' ' - || canBreakAfter(string.charAt(min - 1)) - || INTERNAL_LINE_BREAK.isBoundary(min)) { - frag.length = min; - if (string.charAt(min) == ' ') - result++; - else if (string.charAt(min - 1) == ' ') { - frag.length--; - frag.setWidth(-1); - } - } else out: { - // In the middle of an unbreakable offset - result = INTERNAL_LINE_BREAK.preceding(min); - if (result == 0) { - switch (wrapping) { - case ParagraphTextLayout.WORD_WRAP_TRUNCATE : +public int wrapFragmentInContext(TextFragmentBox frag, String string, + FlowContext context, LookAhead lookahead, Font font, int wrapping) { + frag.setTruncated(false); + int strLen = string.length(); + if (strLen == 0) { + frag.setWidth(-1); + frag.length = 0; + setupFragment(frag, font, string); + context.addToCurrentLine(frag); + return 0; + } + + INTERNAL_LINE_BREAK.setText(string); + + initBidi(frag, string, font); + float avgCharWidth = getAverageCharWidth(frag, font); + frag.setWidth(-1); + + /* + * Setup initial boundaries within the string. + */ + int absoluteMin = 0; + int max, min = 1; + if (wrapping == ParagraphTextLayout.WORD_WRAP_HARD) { + absoluteMin = INTERNAL_LINE_BREAK.next(); + while (absoluteMin > 0 && Character.isWhitespace(string.charAt(absoluteMin - 1))) + absoluteMin--; + min = Math.max(absoluteMin, 1); + } + int firstDelimiter = findFirstDelimeter(string); + if (firstDelimiter == 0) + min = max = 0; + else + max = Math.min(strLen, firstDelimiter) + 1; + + + int availableWidth = context.getRemainingLineWidth(); + int guess = 0, guessSize = 0; + + while (true) { + if ((max - min) <= 1) { + if (min == absoluteMin + && context.isCurrentLineOccupied() + && !context.getContinueOnSameLine() + && availableWidth < measureString(frag, string, min, font) + + ((min == strLen && lookahead != null) ? lookahead.getWidth() : 0) + ) { + context.endLine(); + availableWidth = context.getRemainingLineWidth(); + max = Math.min(strLen, firstDelimiter) + 1; + if ((max - min) <= 1) + break; + } else + break; + } + // Pick a new guess size + // New guess is the last guess plus the missing width in pixels + // divided by the average character size in pixels + guess += 0.5f + (availableWidth - guessSize) / avgCharWidth; + + if (guess >= max) guess = max - 1; + if (guess <= min) guess = min + 1; + + guessSize = measureString(frag, string, guess, font); + + if (guess == strLen + && lookahead != null + && !canBreakAfter(string.charAt(strLen - 1)) + && guessSize + lookahead.getWidth() > availableWidth) { + max = guess; + continue; + } + + if (guessSize <= availableWidth) { + min = guess; + frag.setWidth(guessSize); + if (guessSize == availableWidth) + max = guess + 1; + } else + max = guess; + } + + int result = min; + boolean continueOnLine = false; + if (min == strLen) { + //Everything fits + if (string.charAt(strLen - 1) == ' ') { + if (frag.getWidth() == -1) { + frag.length = result; + frag.setWidth(measureString(frag, string, result, font)); + } + if (lookahead.getWidth() > availableWidth - frag.getWidth()) { + frag.length = result - 1; + frag.setWidth(-1); + } else + frag.length = result; + } else { + continueOnLine = !canBreakAfter(string.charAt(strLen - 1)); + frag.length = result; + } + } else if (min == firstDelimiter) { + //move result past the delimiter + frag.length = result; + if (string.charAt(min) == '\r') { + result++; + if (++min < strLen && string.charAt(min) == '\n') + result++; + } else if (string.charAt(min) == '\n') + result++; + } else if (string.charAt(min) == ' ' + || canBreakAfter(string.charAt(min - 1)) + || INTERNAL_LINE_BREAK.isBoundary(min)) { + frag.length = min; + if (string.charAt(min) == ' ') + result++; + else if (string.charAt(min - 1) == ' ') { + frag.length--; + frag.setWidth(-1); + } + } else out: { + // In the middle of an unbreakable offset + result = INTERNAL_LINE_BREAK.preceding(min); + if (result == 0) { + switch (wrapping) { + case ParagraphTextLayout.WORD_WRAP_TRUNCATE : ELLIPSIS_SIZE = FigureUtilities .getStringExtents(TextFlow.ELLIPSIS, font).width; int truncatedWidth = availableWidth - ELLIPSIS_SIZE; @@ -312,24 +319,65 @@ } else frag.length = 0; frag.setTruncated(true); - result = INTERNAL_LINE_BREAK.following(max - 1); - break out; + result = INTERNAL_LINE_BREAK.following(max - 1); + break out; + + default: + result = min; + break; + } + } + frag.length = result; + if (string.charAt(result - 1) == ' ') + frag.length--; + frag.setWidth(-1); + } + + setupFragment(frag, font, string); + context.addToCurrentLine(frag); + context.setContinueOnSameLine(continueOnLine); + return result; +} - default: - result = min; - break; - } - } - frag.length = result; - if (string.charAt(result - 1) == ' ') - frag.length--; - frag.setWidth(-1); - } - - setupFragment(frag, font, string); - context.addToCurrentLine(frag); - context.setContinueOnSameLine(continueOnLine); - return result; +/** + * Returns the Dimensions of s in Font f. + * + * @param s the string + * @param f the font + * @return the dimensions of the given string + * @since 2.0 + */ +public Dimension getStringExtents(String s, Font f) { + return FigureUtilities.getStringExtents(s, f); +} + +/** + * @see TextLayout#getBounds() + */ +protected Rectangle getTextLayoutBounds(String s, Font f, int start, int end) { + TextLayout textLayout = getTextLayout(); + textLayout.setFont(f); + textLayout.setText(s); + return textLayout.getBounds(start, end); +} + +/** + * Gets the font's ascent. + * @param font + * @return the font's ascent + */ +public int getAscent(Font font) { + FontMetrics fm = FigureUtilities.getFontMetrics(font); + return fm.getHeight() - fm.getDescent(); +} + +/** + * Gets the font's descent. + * @param font + * @return the font's descent + */ +public int getDescent(Font font) { + return FigureUtilities.getFontMetrics(font).getDescent(); } } Index: src/org/eclipse/draw2d/text/TextFlow.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/plugins/org.eclipse.draw2d/src/org/eclipse/draw2d/text/TextFlow.java,v retrieving revision 1.55 diff -u -r1.55 TextFlow.java --- src/org/eclipse/draw2d/text/TextFlow.java 14 Feb 2006 20:13:32 -0000 1.55 +++ src/org/eclipse/draw2d/text/TextFlow.java 2 Aug 2007 20:49:05 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. + * Copyright (c) 2000, 2007 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 @@ -12,11 +12,9 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.TextLayout; import org.eclipse.draw2d.ColorConstants; -import org.eclipse.draw2d.FigureUtilities; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; @@ -36,10 +34,12 @@ extends InlineFlow { -static final String ELLIPSIS = "..."; //$NON-NLS-1$ +public static final String ELLIPSIS = "..."; //$NON-NLS-1$ private BidiInfo bidiInfo; private int selectionEnd = -1; private String text; +private FlowUtilities flowUtilities = new FlowUtilities(); + /** * Constructs a new TextFlow with the empty String. @@ -95,7 +95,7 @@ text = text.substring(1, index + 1); if (bidiInfo == null) - width[0] += FlowUtilities.getStringExtents(text, getFont()).width; + width[0] += flowUtilities.getStringExtents(text, getFont()).width; else { TextLayout textLayout = FlowUtilities.getTextLayout(); textLayout.setFont(getFont()); @@ -174,9 +174,8 @@ return findOffset(p, trailing, closestBox, index); } -int getAscent() { - FontMetrics fm = FigureUtilities.getFontMetrics(getFont()); - return fm.getHeight() - fm.getDescent(); +protected int getAscent() { + return getFlowUtilities().getAscent(getFont()); } /** @@ -267,7 +266,7 @@ if (trailing && offset < box.length) offset++; String substring = getText().substring(box.offset, box.offset + offset); - result.x = FigureUtilities.getStringExtents(substring, getFont()).width; + result.x = getFlowUtilities().getStringExtents(substring, getFont()).width; } else { TextLayout layout = FlowUtilities.getTextLayout(); layout.setFont(getFont()); @@ -282,8 +281,8 @@ return result; } -int getDescent() { - return FigureUtilities.getFontMetrics(getFont()).getDescent(); +protected int getDescent() { + return getFlowUtilities().getDescent(getFont()); } /** @@ -629,4 +628,12 @@ return Math.max(0, y - (box.getBaseline() + box.getLineRoot().getDescent())); } +public FlowUtilities getFlowUtilities() { + return flowUtilities; +} + +public void setFlowUtilities(FlowUtilities flowUtilities) { + this.flowUtilities = flowUtilities; +} + } \ No newline at end of file Index: src/org/eclipse/draw2d/text/SimpleTextLayout.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/plugins/org.eclipse.draw2d/src/org/eclipse/draw2d/text/SimpleTextLayout.java,v retrieving revision 1.10 diff -u -r1.10 SimpleTextLayout.java --- src/org/eclipse/draw2d/text/SimpleTextLayout.java 7 Sep 2005 21:34:54 -0000 1.10 +++ src/org/eclipse/draw2d/text/SimpleTextLayout.java 2 Aug 2007 20:49:05 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. + * Copyright (c) 2000, 2007 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 @@ -21,9 +21,9 @@ public class SimpleTextLayout extends TextLayout { private static final String[] DELIMITERS = { - "\r\n", //$NON-NLS-1$ - "\n", //$NON-NLS-1$ - "\r"};//$NON-NLS-1$ + "\r\n", //$NON-NLS-1$ + "\n", //$NON-NLS-1$ + "\r"};//$NON-NLS-1$ private static int result; private static int delimeterLength; @@ -33,49 +33,50 @@ * @param flow the TextFlow */ public SimpleTextLayout(TextFlow flow) { - super (flow); + super (flow); } /** * @see org.eclipse.draw2d.text.FlowFigureLayout#layout() */ protected void layout() { - TextFlow textFlow = (TextFlow)getFlowFigure(); - String text = textFlow.getText(); - List fragments = textFlow.getFragments(); - Font font = textFlow.getFont(); - TextFragmentBox fragment; - int i = 0; - int offset = 0; - - do { - nextLineBreak(text, offset); - fragment = getFragment(i++, fragments); - fragment.length = result - offset; - fragment.offset = offset; - fragment.setWidth(-1); - FlowUtilities.setupFragment(fragment, font, text); - getContext().addToCurrentLine(fragment); - getContext().endLine(); - offset = result + delimeterLength; - } while (offset < text.length()); - //Remove the remaining unused fragments. - while (i < fragments.size()) - fragments.remove(i++); + TextFlow textFlow = (TextFlow)getFlowFigure(); + String text = textFlow.getText(); + List fragments = textFlow.getFragments(); + Font font = textFlow.getFont(); + TextFragmentBox fragment; + int i = 0; + int offset = 0; + FlowUtilities flowUtilities = textFlow.getFlowUtilities(); + + do { + nextLineBreak(text, offset); + fragment = getFragment(i++, fragments); + fragment.length = result - offset; + fragment.offset = offset; + fragment.setWidth(-1); + flowUtilities.setupFragment(fragment, font, text); + getContext().addToCurrentLine(fragment); + getContext().endLine(); + offset = result + delimeterLength; + } while (offset < text.length()); + //Remove the remaining unused fragments. + while (i < fragments.size()) + fragments.remove(i++); } private int nextLineBreak(String text, int offset) { - result = text.length(); - delimeterLength = 0; - int current; - for (int i = 0; i < DELIMITERS.length; i++) { - current = text.indexOf(DELIMITERS[i], offset); - if (current != -1 && current < result) { - result = current; - delimeterLength = DELIMITERS[i].length(); - } - } - return result; + result = text.length(); + delimeterLength = 0; + int current; + for (int i = 0; i < DELIMITERS.length; i++) { + current = text.indexOf(DELIMITERS[i], offset); + if (current != -1 && current < result) { + result = current; + delimeterLength = DELIMITERS[i].length(); + } + } + return result; } } Index: src/org/eclipse/draw2d/text/ParagraphTextLayout.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/plugins/org.eclipse.draw2d/src/org/eclipse/draw2d/text/ParagraphTextLayout.java,v retrieving revision 1.31 diff -u -r1.31 ParagraphTextLayout.java --- src/org/eclipse/draw2d/text/ParagraphTextLayout.java 1 Jun 2005 19:56:30 -0000 1.31 +++ src/org/eclipse/draw2d/text/ParagraphTextLayout.java 2 Aug 2007 20:49:05 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. + * Copyright (c) 2000, 2007 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 @@ -20,7 +20,7 @@ * @since 2.1 */ public class ParagraphTextLayout - extends TextLayout + extends TextLayout { /** @@ -48,23 +48,23 @@ * @param flow the TextFlow */ public ParagraphTextLayout(TextFlow flow) { - super(flow); + super(flow); } /** * Constructs the layout with the specified TextFlow and wrapping style. The wrapping * style must be one of: * * @param flow the textflow * @param style the style of wrapping */ public ParagraphTextLayout(TextFlow flow, int style) { - this(flow); - wrappingStyle = style; + this(flow); + wrappingStyle = style; } /** @@ -75,133 +75,134 @@ * @return the requested segment */ private String[] getSegments(String text, int levelInfo[]) { - if (levelInfo.length == 1) - return new String[] {text}; - - String result[] = new String[levelInfo.length / 2 + 1]; - - int i; - int endOffset; - int beginOffset = 0; - - for (i = 0; i < result.length - 1; i++) { - endOffset = levelInfo[i * 2 + 1]; - result[i] = text.substring(beginOffset, endOffset); - beginOffset = endOffset; - } - endOffset = text.length(); - result[i] = text.substring(beginOffset, endOffset); - return result; + if (levelInfo.length == 1) + return new String[] {text}; + + String result[] = new String[levelInfo.length / 2 + 1]; + + int i; + int endOffset; + int beginOffset = 0; + + for (i = 0; i < result.length - 1; i++) { + endOffset = levelInfo[i * 2 + 1]; + result[i] = text.substring(beginOffset, endOffset); + beginOffset = endOffset; + } + endOffset = text.length(); + result[i] = text.substring(beginOffset, endOffset); + return result; } class SegmentLookahead implements FlowUtilities.LookAhead { - private int seg = -1; - private String segs[]; - private int[] width; - private final int trailingBorderSize; - SegmentLookahead(String segs[], int trailingBorderSize) { - this.segs = segs; - this.trailingBorderSize = trailingBorderSize; - } - public int getWidth() { - if (width == null) { - width = new int[1]; - int startingIndex = seg + 1; - TextFlow textFlow = (TextFlow)getFlowFigure(); - - if (startingIndex == segs.length) { - width[0] += trailingBorderSize; - getContext().getWidthLookahead(textFlow, width); - } else { - String rest = segs[startingIndex]; - for (int k = startingIndex + 1; k < segs.length; k++) - rest += segs[k]; - if (!textFlow.addLeadingWordWidth(rest, width)) { - width[0] += trailingBorderSize; - getContext().getWidthLookahead(textFlow, width); - } - } - } - return width[0]; - } - public void setIndex(int value) { - this.seg = value; - width = null; - } + private int seg = -1; + private String segs[]; + private int[] width; + private final int trailingBorderSize; + SegmentLookahead(String segs[], int trailingBorderSize) { + this.segs = segs; + this.trailingBorderSize = trailingBorderSize; + } + public int getWidth() { + if (width == null) { + width = new int[1]; + int startingIndex = seg + 1; + TextFlow textFlow = (TextFlow)getFlowFigure(); + + if (startingIndex == segs.length) { + width[0] += trailingBorderSize; + getContext().getWidthLookahead(textFlow, width); + } else { + String rest = segs[startingIndex]; + for (int k = startingIndex + 1; k < segs.length; k++) + rest += segs[k]; + if (!textFlow.addLeadingWordWidth(rest, width)) { + width[0] += trailingBorderSize; + getContext().getWidthLookahead(textFlow, width); + } + } + } + return width[0]; + } + public void setIndex(int value) { + this.seg = value; + width = null; + } } /** * @see org.eclipse.draw2d.text.FlowFigureLayout#layout() */ protected void layout() { - TextFlow textFlow = (TextFlow)getFlowFigure(); - int offset = 0; - - FlowContext context = getContext(); - List fragments = textFlow.getFragments(); - Font font = textFlow.getFont(); - int fragIndex = 0; - int advance = 0; - - TextFragmentBox fragment; - int levelInfo[] = (textFlow.getBidiInfo() == null) - ? new int[] {-1} - : textFlow.getBidiInfo().levelInfo; - - String segment, segments[] = getSegments(textFlow.getText(), levelInfo); - FlowBorder border = null; - if (textFlow.getBorder() instanceof FlowBorder) - border = (FlowBorder)textFlow.getBorder(); - - SegmentLookahead lookahead = new SegmentLookahead(segments, border == null ? 0 : border.getRightMargin()); - int seg; - - if (border != null) { - fragment = getFragment(fragIndex++, fragments); - fragment.setBidiLevel(levelInfo[0]); - fragment.setTruncated(false); - fragment.offset = fragment.length = -1; - fragment.setWidth(border.getLeftMargin() + border.getInsets(textFlow).left); - if (context.getRemainingLineWidth() - < fragment.getWidth() + lookahead.getWidth()) - context.endLine(); - context.addToCurrentLine(fragment); - } - - for (seg = 0; seg < segments.length; seg++) { - segment = segments[seg]; - lookahead.setIndex(seg); - - do { - fragment = getFragment(fragIndex++, fragments); - - fragment.offset = offset; - fragment.setBidiLevel(levelInfo[seg * 2]); - - advance = FlowUtilities.wrapFragmentInContext(fragment, segment, - context, lookahead, font, wrappingStyle); - segment = segment.substring(advance); - offset += advance; - if ((segment.length() > 0 - || fragment.length < advance) - || fragment.isTruncated()) - context.endLine(); - } while (segment.length() > 0 - || (!fragment.isTruncated() && fragment.length < advance)); - } - - if (border != null) { - fragment = getFragment(fragIndex++, fragments); - fragment.setBidiLevel(levelInfo[0]); - fragment.setTruncated(false); - fragment.offset = fragment.length = -1; - fragment.setWidth(border.getRightMargin() + border.getInsets(textFlow).right); - context.addToCurrentLine(fragment); - } - - //Remove the remaining unused fragments. - while (fragIndex < fragments.size()) - fragments.remove(fragments.size() - 1); + TextFlow textFlow = (TextFlow)getFlowFigure(); + int offset = 0; + + FlowContext context = getContext(); + List fragments = textFlow.getFragments(); + Font font = textFlow.getFont(); + int fragIndex = 0; + int advance = 0; + + TextFragmentBox fragment; + int levelInfo[] = (textFlow.getBidiInfo() == null) + ? new int[] {-1} + : textFlow.getBidiInfo().levelInfo; + + String segment, segments[] = getSegments(textFlow.getText(), levelInfo); + FlowBorder border = null; + if (textFlow.getBorder() instanceof FlowBorder) + border = (FlowBorder)textFlow.getBorder(); + + SegmentLookahead lookahead = new SegmentLookahead(segments, border == null ? 0 : border.getRightMargin()); + int seg; + + if (border != null) { + fragment = getFragment(fragIndex++, fragments); + fragment.setBidiLevel(levelInfo[0]); + fragment.setTruncated(false); + fragment.offset = fragment.length = -1; + fragment.setWidth(border.getLeftMargin() + border.getInsets(textFlow).left); + if (context.getRemainingLineWidth() + < fragment.getWidth() + lookahead.getWidth()) + context.endLine(); + context.addToCurrentLine(fragment); + } + + FlowUtilities flowUtilities = textFlow.getFlowUtilities(); + for (seg = 0; seg < segments.length; seg++) { + segment = segments[seg]; + lookahead.setIndex(seg); + + do { + fragment = getFragment(fragIndex++, fragments); + + fragment.offset = offset; + fragment.setBidiLevel(levelInfo[seg * 2]); + + advance = flowUtilities.wrapFragmentInContext(fragment, segment, + context, lookahead, font, wrappingStyle); + segment = segment.substring(advance); + offset += advance; + if ((segment.length() > 0 + || fragment.length < advance) + || fragment.isTruncated()) + context.endLine(); + } while (segment.length() > 0 + || (!fragment.isTruncated() && fragment.length < advance)); + } + + if (border != null) { + fragment = getFragment(fragIndex++, fragments); + fragment.setBidiLevel(levelInfo[0]); + fragment.setTruncated(false); + fragment.offset = fragment.length = -1; + fragment.setWidth(border.getRightMargin() + border.getInsets(textFlow).right); + context.addToCurrentLine(fragment); + } + + //Remove the remaining unused fragments. + while (fragIndex < fragments.size()) + fragments.remove(fragments.size() - 1); } }