### 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 19 Sep 2007 15:03:44 -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,24 +15,30 @@
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
+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.TextUtilities;
/**
* Utility class for FlowFigures.
* @author hudsonr
* @since 2.1
*/
-class FlowUtilities
- extends FigureUtilities
+public class FlowUtilities
{
interface LookAhead {
int getWidth();
}
-private static int ELLIPSIS_SIZE;
+
+/**
+ * a singleton default instance
+ */
+public static FlowUtilities INSTANCE = new FlowUtilities();
+
private static final BreakIterator INTERNAL_LINE_BREAK = BreakIterator.getLineInstance();
private static TextLayout layout;
@@ -61,10 +67,21 @@
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) {
@@ -129,34 +146,28 @@
}
}
-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);
- }
+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 getTextUtilities().getStringExtents(string.substring(0, guess), font).width;
+}
+
+protected 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 = getTextUtilities().getStringExtents(s.substring(0, frag.length), f).width;
+ if (frag.isTruncated())
+ width += getEllipsisWidth(f);
+ frag.setWidth(width);
+ }
}
/**
@@ -172,7 +183,7 @@
* @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,
+protected int wrapFragmentInContext(TextFragmentBox frag, String string,
FlowContext context, LookAhead lookahead, Font font, int wrapping) {
frag.setTruncated(false);
int strLen = string.length();
@@ -245,61 +256,59 @@
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;
+ 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 :
+ int truncatedWidth = availableWidth - getEllipsisWidth(font);
if (truncatedWidth > 0) {
//$TODO this is very slow. It should be using avgCharWidth to go faster
while (min > 0) {
@@ -312,24 +321,56 @@
} 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;
}
+/**
+ * @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);
+}
+
+/**
+ * Returns an instance of a TextUtililities
class on which
+ * text calculations can be performed. Clients may override to customize.
+ *
+ * @return the TextUtililities
instance
+ * @since 3.4
+ */
+protected TextUtilities getTextUtilities() {
+ return TextUtilities.INSTANCE;
+}
+
+/**
+ * Gets the ellipsis width.
+ *
+ * @param font
+ * the font to be used in the calculation
+ * @return the width of the ellipsis
+ * @since 3.4
+ */
+private int getEllipsisWidth(Font font) {
+ return getTextUtilities().getStringExtents(TextFlow.ELLIPSIS, font).width;
+}
}
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 19 Sep 2007 15:03:44 -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,12 +12,11 @@
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.TextUtilities;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
@@ -95,7 +94,7 @@
text = text.substring(1, index + 1);
if (bidiInfo == null)
- width[0] += FlowUtilities.getStringExtents(text, getFont()).width;
+ width[0] += getTextUtilities().getStringExtents(text, getFont()).width;
else {
TextLayout textLayout = FlowUtilities.getTextLayout();
textLayout.setFont(getFont());
@@ -175,8 +174,7 @@
}
int getAscent() {
- FontMetrics fm = FigureUtilities.getFontMetrics(getFont());
- return fm.getHeight() - fm.getDescent();
+ return getTextUtilities().getAscent(getFont());
}
/**
@@ -267,7 +265,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 = getTextUtilities().getStringExtents(substring, getFont()).width;
} else {
TextLayout layout = FlowUtilities.getTextLayout();
layout.setFont(getFont());
@@ -283,7 +281,7 @@
}
int getDescent() {
- return FigureUtilities.getFontMetrics(getFont()).getDescent();
+ return getTextUtilities().getDescent(getFont());
}
/**
@@ -485,7 +483,7 @@
g.getClip(Rectangle.SINGLETON);
int yStart = Rectangle.SINGLETON.y;
int yEnd = Rectangle.SINGLETON.bottom();
-
+
for (int i = 0; i < fragments.size(); i++) {
frag = (TextFragmentBox)fragments.get(i);
// g.drawLine(frag.getX(), frag.getLineRoot().getVisibleTop(),
@@ -499,7 +497,7 @@
//Break loop at first non-visible fragment
if (yEnd < frag.getLineRoot().getVisibleTop())
break;
-
+
String draw = getBidiSubstring(frag, i);
if (frag.isTruncated())
@@ -629,4 +627,25 @@
return Math.max(0, y - (box.getBaseline() + box.getLineRoot().getDescent()));
}
+/**
+ * Gets the FlowUtilities
instance to be used in measurement
+ * calculations.
+ *
+ * @return a FlowUtilities
instance
+ * @since 3.2
+ */
+protected FlowUtilities getFlowUtilities() {
+ return FlowUtilities.INSTANCE;
+}
+
+/**
+ * Gets the TextUtilities
instance to be used in measurement
+ * calculations.
+ *
+ * @return a TextUtilities
instance
+ * @since 3.2
+ */
+protected TextUtilities getTextUtilities() {
+ return TextUtilities.INSTANCE;
+}
}
\ 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 19 Sep 2007 15:03:44 -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 19 Sep 2007 15:03:44 -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:
*
TextUtilities
instance to be used in measurement
+ * calculations.
+ *
+ * @return a TextUtilities
instance
+ * @since 3.2
+ */
+public TextUtilities getTextUtilities() {
+ return TextUtilities.INSTANCE;
+}
+
+/**
+ * Gets the string that will be appended to the text when the label is
+ * truncated. By default, this returns an ellipsis.
+ *
+ * @return the string to append to the text when truncated
+ * @since 3.4
+ */
+protected String getTruncationString() {
+ return ELLIPSIS;
+}
+
+/**
+ * Gets the icon size
+ *
+ * @return the icon size
+ * @since 3.4
+ */
+protected Dimension getIconSize() {
+ return iconSize;
+}
+
}
Index: src/org/eclipse/draw2d/FigureUtilities.java
===================================================================
RCS file: /cvsroot/tools/org.eclipse.gef/plugins/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureUtilities.java,v
retrieving revision 1.34
diff -u -r1.34 FigureUtilities.java
--- src/org/eclipse/draw2d/FigureUtilities.java 24 Apr 2006 18:15:12 -0000 1.34
+++ src/org/eclipse/draw2d/FigureUtilities.java 19 Sep 2007 15:03:44 -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
@@ -114,48 +114,6 @@
}
/**
- * Returns the largest substring of s in Font f that can be confined to the
- * number of pixels in availableWidth.
- *
- * @param s the original string
- * @param f the font
- * @param availableWidth the available width
- * @return the largest substring that fits in the given width
- * @since 2.0
- */
-static int getLargestSubstringConfinedTo(String s, Font f, int availableWidth) {
- FontMetrics metrics = getFontMetrics(f);
- int min, max;
- float avg = metrics.getAverageCharWidth();
- min = 0;
- max = s.length() + 1;
-
- //The size of the current guess
- int guess = 0,
- guessSize = 0;
- while ((max - min) > 1) {
- //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 = guess + (int)((availableWidth - guessSize) / avg);
-
- if (guess >= max) guess = max - 1;
- if (guess <= min) guess = min + 1;
-
- //Measure the current guess
- guessSize = getTextExtents(s.substring(0, guess), f).width;
-
- if (guessSize < availableWidth)
- //We did not use the available width
- min = guess;
- else
- //We exceeded the available width
- max = guess;
- }
- return min;
-}
-
-/**
* Returns the Dimensions of the given text, converting newlines and tabs appropriately.
*
* @param text the text
Index: src/org/eclipse/draw2d/TextUtilities.java
===================================================================
RCS file: src/org/eclipse/draw2d/TextUtilities.java
diff -N src/org/eclipse/draw2d/TextUtilities.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/draw2d/TextUtilities.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.draw2d;
+
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontMetrics;
+
+import org.eclipse.draw2d.geometry.Dimension;
+
+/**
+ * Provides miscellaneous text operations. Clients may subclass this class if
+ * necessary.
+ *
+ * @author crevells
+ * @since 3.4
+ */
+public class TextUtilities {
+
+ /**
+ * a singleton default instance
+ */
+ public static TextUtilities INSTANCE = new TextUtilities();
+
+ /**
+ * Returns the Dimensions of s in Font f.
+ *
+ * @param s
+ * the string
+ * @param f
+ * the font
+ * @return the dimensions of the given string
+ */
+ public Dimension getStringExtents(String s, Font f) {
+ return FigureUtilities.getStringExtents(s, f);
+ }
+
+ /**
+ * Returns the Dimensions of the given text, converting newlines and tabs
+ * appropriately.
+ *
+ * @param s
+ * the text
+ * @param f
+ * the font
+ * @return the dimensions of the given text
+ */
+ public Dimension getTextExtents(String s, Font f) {
+ return FigureUtilities.getTextExtents(s, f);
+ }
+
+ /**
+ * 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();
+ }
+
+ /**
+ * Returns the largest substring of s in Font f that can be
+ * confined to the number of pixels in availableWidth.
+ *
+ * @param s
+ * the original string
+ * @param f
+ * the font
+ * @param availableWidth
+ * the available width
+ * @return the largest substring that fits in the given width
+ */
+ public int getLargestSubstringConfinedTo(String s, Font f,
+ int availableWidth) {
+ FontMetrics metrics = FigureUtilities.getFontMetrics(f);
+ int min, max;
+ float avg = metrics.getAverageCharWidth();
+ min = 0;
+ max = s.length() + 1;
+
+ // The size of the current guess
+ int guess = 0, guessSize = 0;
+ while ((max - min) > 1) {
+ // 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 = guess + (int) ((availableWidth - guessSize) / avg);
+
+ if (guess >= max)
+ guess = max - 1;
+ if (guess <= min)
+ guess = min + 1;
+
+ // Measure the current guess
+ guessSize = getTextExtents(s.substring(0, guess), f).width;
+
+ if (guessSize < availableWidth)
+ // We did not use the available width
+ min = guess;
+ else
+ // We exceeded the available width
+ max = guess;
+ }
+ return min;
+ }
+}