diff options
author | Stefan Xenos | 2016-11-11 05:02:34 +0000 |
---|---|---|
committer | Stefan Xenos | 2016-11-12 08:05:42 +0000 |
commit | 62b818369a1dfc551ef1ffdb102760b7087a8b6c (patch) | |
tree | 8f4ad771248fae01cc0cd2d9208ac01510776e1a | |
parent | d1cb5534ebd9cb864895b220785c598354ca11d4 (diff) | |
download | eclipse.platform.ui-62b818369a1dfc551ef1ffdb102760b7087a8b6c.tar.gz eclipse.platform.ui-62b818369a1dfc551ef1ffdb102760b7087a8b6c.tar.xz eclipse.platform.ui-62b818369a1dfc551ef1ffdb102760b7087a8b6c.zip |
Bug 111900 - Significant slow down when using a job with a long name.I20161112-0405
Change-Id: I8c6271842b119ec32a0d8760a5fcfc5143d1975c
Signed-off-by: Stefan Xenos <sxenos@gmail.com>
-rw-r--r-- | bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/progress/ProgressManagerUtil.java | 161 |
1 files changed, 141 insertions, 20 deletions
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/progress/ProgressManagerUtil.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/progress/ProgressManagerUtil.java index 48d120beda9..1683691eb1c 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/progress/ProgressManagerUtil.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/progress/ProgressManagerUtil.java @@ -179,39 +179,160 @@ public class ProgressManagerUtil { * @param control * @return String */ - static String shortenText(String textValue, Control control) { if (textValue == null) { return null; } - GC gc = new GC(control); int maxWidth = control.getBounds().width - 5; - int maxExtent = gc.textExtent(textValue).x; - if (maxExtent < maxWidth) { + String ellipsisString = ellipsis; + GC gc = new GC(control); + try { + return clipToSize(gc, textValue, ellipsisString, maxWidth); + } finally { gc.dispose(); - return textValue; } + } + + private static String clipToSize(GC gc, String textValue, String ellipsisString, int maxWidth) { + int averageCharWidth = gc.getFontMetrics().getAverageCharWidth(); int length = textValue.length(); - int charsToClip = Math.round(0.95f * length - * (1 - ((float) maxWidth / maxExtent))); + int secondWord = findSecondWhitespace(textValue, gc, maxWidth); int pivot = ((length - secondWord) / 2) + secondWord; - int start = pivot - (charsToClip / 2); - int end = pivot + (charsToClip / 2) + 1; - while (start >= 0 && end < length) { - String s1 = textValue.substring(0, start); - String s2 = textValue.substring(end, length); - String s = s1 + ellipsis + s2; + + int currentLength; + int upperBoundWidth; + int upperBoundLength = 0; + + // Now use newton's method to search for the correct string size + int lowerBoundLength = 0; + int lowerBoundWidth = 0; + + // Try to guess the size of the string based on the font's average + // character width + int estimatedCharactersThatWillFit = maxWidth / averageCharWidth; + + if (estimatedCharactersThatWillFit >= length) { + int maxExtent = gc.textExtent(textValue).x; + if (maxExtent <= maxWidth) { + return textValue; + } + currentLength = Math.max(0, + Math.round(length * ((float) maxWidth / maxExtent)) - ellipsisString.length()); + upperBoundWidth = maxExtent; + upperBoundLength = length; + } else { + currentLength = Math.min(length, Math.max(0, estimatedCharactersThatWillFit - ellipsisString.length())); + for (;;) { + String s = clipToLength(textValue, ellipsisString, pivot, currentLength); + int currentExtent = gc.textExtent(s).x; + if (currentExtent > maxWidth) { + upperBoundWidth = currentExtent; + upperBoundLength = currentLength; + break; + } + if (currentLength == length) { + // No need to clip the string if the whole thing fits. + return textValue; + } + lowerBoundWidth = currentExtent; + lowerBoundLength = currentLength; + currentLength = Math.min(length, currentLength * 2 + 1); + } + } + + String s; + for (;;) { + int oldLength = currentLength; + s = clipToLength(textValue, ellipsisString, pivot, currentLength); + int l = gc.textExtent(s).x; - if (l < maxWidth) { - gc.dispose(); - return s; + int tooBigBy = l - maxWidth; + if (tooBigBy == 0) { + // If this was exactly the right size, stop the binary + // search + break; + } else if (tooBigBy > 0) { + // The string is too big. Need to clip more. + upperBoundLength = currentLength; + upperBoundWidth = l; + if (currentLength <= lowerBoundLength + 1) { + // We're one character away from a value that is known + // to clip too much, so opt for clipping slightly too + // much + currentLength = lowerBoundLength; + break; + } + if (tooBigBy <= averageCharWidth * 2) { + currentLength--; + } else { + int spaceToRightOfLowerBound = maxWidth - lowerBoundWidth; + currentLength = lowerBoundLength + + (currentLength - lowerBoundLength) * spaceToRightOfLowerBound / (l - lowerBoundWidth); + if (currentLength >= oldLength) { + currentLength = oldLength - 1; + } else if (currentLength <= lowerBoundLength) { + currentLength = lowerBoundLength + 1; + } + } + } else { + // The string is too small. Need to clip less. + lowerBoundLength = currentLength; + lowerBoundWidth = l; + if (currentLength >= upperBoundLength - 1) { + // We're one character away from a value that is known + // to clip too little, so opt for clipping slightly + // too much + currentLength = upperBoundLength - 1; + break; + } + if (-tooBigBy <= averageCharWidth * 2) { + currentLength++; + } else { + currentLength = currentLength + + (upperBoundLength - currentLength) * (-tooBigBy) / (upperBoundWidth - l); + if (currentLength <= oldLength) { + currentLength = oldLength + 1; + } else if (currentLength >= upperBoundLength) { + currentLength = upperBoundLength - 1; + } + } } - start--; - end++; } - gc.dispose(); - return textValue; + + s = clipToLength(textValue, ellipsisString, pivot, currentLength); + return s; + } + + private static String clipToLength(String textValue, String ellipsisString, int pivot, int newLength) { + return getClippedString(textValue, ellipsisString, pivot, textValue.length() - newLength); + } + + private static String getClippedString(String textValue, String ellipsisString, int pivot, int charsToClip) { + int length = textValue.length(); + if (charsToClip <= 0) { + return textValue; + } + if (charsToClip >= length) { + return ""; //$NON-NLS-1$ + } + String s; + int start = pivot - charsToClip / 2; + int end = pivot + (charsToClip + 1) / 2; + + if (start < 0) { + end -= start; + start = 0; + } + if (end < 0) { + start -= end; + end = 0; + } + + String s1 = textValue.substring(0, start); + String s2 = textValue.substring(end, length); + s = s1 + ellipsisString + s2; + return s; } /** |