From: Alexandre Montplaisir Date: Thu, 30 Jun 2016 21:39:00 +0000 (-0400) Subject: tmf: Ellipse function names that don't fit in CallStackView X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;ds=sidebyside;h=2984a46655de9969a26868a7ba9ff68a1012f590;p=deliverable%2Ftracecompass.git tmf: Ellipse function names that don't fit in CallStackView Add "..." to function names that get cut due to short rectangles in the call stack view, and avoid printing anything if at least 1 character + the "..." won't fit. Also, instead of starting from the full string length and going down to find a fitting string, start from 1 and work our way up. This will better handle the worst case, which is lots of very small states in a view that all want to print very long strings. Bug: 497111 Change-Id: I94ccca31fb890923063f75359ff714721a8b6f68 Signed-off-by: Alexandre Montplaisir Reviewed-on: https://git.eclipse.org/r/76401 Reviewed-by: Hudson CI --- diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackPresentationProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackPresentationProvider.java index b6478f028a..2542fadbf3 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackPresentationProvider.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackPresentationProvider.java @@ -48,7 +48,12 @@ public class CallStackPresentationProvider extends TimeGraphPresentationProvider private CallStackView fView; - private Integer fAverageCharWidth; + /** + * Minimum width of a displayed state below which we will not print any text + * into it. It corresponds to the average width of 1 char, plus the width of + * the ellipsis characters. + */ + private Integer fMinimumBarWidth; private final LoadingCache> fTimeEventNames = CacheBuilder.newBuilder() .maximumSize(1000) @@ -141,16 +146,27 @@ public class CallStackPresentationProvider extends TimeGraphPresentationProvider @Override public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) { - if (fAverageCharWidth == null) { - fAverageCharWidth = gc.getFontMetrics().getAverageCharWidth(); + if (!(event instanceof CallStackEvent)) { + return; } - if (bounds.width <= fAverageCharWidth) { + + if (fMinimumBarWidth == null) { + fMinimumBarWidth = gc.getFontMetrics().getAverageCharWidth() + gc.stringExtent(Utils.ELLIPSIS).x; + } + if (bounds.width <= fMinimumBarWidth) { + /* + * Don't print anything if we cannot at least show one character and + * ellipses. + */ return; } - if (!(event instanceof CallStackEvent)) { + + String name = fTimeEventNames.getUnchecked((CallStackEvent) event).orElse(""); //$NON-NLS-1$ + if (name.isEmpty()) { + /* No text to print */ return; } - String name = fTimeEventNames.getUnchecked((CallStackEvent) event).orElse(null); + gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE)); Utils.drawText(gc, name, bounds.x, bounds.y, bounds.width, bounds.height, true, true); } diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/widgets/Utils.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/widgets/Utils.java index dbd565a0f6..0b0bf7c36d 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/widgets/Utils.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/widgets/Utils.java @@ -83,6 +83,14 @@ public class Utils { NANOSEC } + /** + * Ellipsis character, used to shorten strings that don't fit in their + * target area. + * + * @since 2.1 + */ + public static final String ELLIPSIS = "…"; //$NON-NLS-1$ + private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$ private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$ private static final long HOURS_PER_DAY = 24; @@ -305,7 +313,9 @@ public class Utils { * @param isTransparent * If true the background will be transparent, otherwise it will be opaque * @return The number of characters written + * @deprecated Use {@link #drawText(GC, String, int, int, int, int, boolean, boolean)} instead. */ + @Deprecated public static int drawText(GC gc, String text, int x, int y, int width, boolean isCentered, boolean isTransparent) { if (width < 1) { return 0; @@ -356,36 +366,64 @@ public class Utils { * @since 2.0 */ public static int drawText(GC gc, String text, int x, int y, int width, int height, boolean isCentered, boolean isTransparent) { - if (width < 1) { + if (width < 1 || text.isEmpty()) { return 0; } - int len = text.length(); - int textWidth = 0; + String stringToDisplay; + int len; + boolean isCenteredWidth = isCentered; int realX = x; int realY = y; - Point textExtent = null; - while (len > 0) { - textExtent = gc.textExtent(text.substring(0, len)); - textWidth = textExtent.x; - if (textWidth <= width) { - break; - } + /* First check if the whole string fits */ + Point textExtent = gc.textExtent(text); + if (textExtent.x <= width) { + len = text.length(); + stringToDisplay = text; + } else { + /* + * The full string doesn't fit, try to find the longest one with + * "..." at the end that does fit. + * + * Iterate on the string length sizes, starting from 1 going up, + * until we find a string that does not fit. Once we do, we keep the + * one just before that did fit. + */ isCenteredWidth = false; - len--; - textExtent = gc.textExtent(text.substring(0, len)); - } - if (len > 0) { - if (isCenteredWidth) { - realX += (width - textWidth) / 2; - } - if (isCentered && textExtent != null) { - realY += (height - textExtent.y) / 2 - 1; + int prevLen = 0; + len = 1; + while (len <= text.length()) { + textExtent = gc.textExtent(text.substring(0, len) + ELLIPSIS); + if (textExtent.x > width) { + /* + * Here is the first length that does not fit, the one from + * the previous iteration is the one we will use. + */ + len = prevLen; + break; + } + /* This string would fit, try the next one */ + prevLen = len; + len++; } - gc.drawText(text.substring(0, len), realX, realY, isTransparent); + stringToDisplay = text.substring(0, len) + ELLIPSIS; + } + + if (len <= 0) { + /* Nothing fits, we end up drawing nothing */ + return 0; + } + + if (isCenteredWidth) { + realX += (width - textExtent.x) / 2; + } + if (isCentered) { + realY += (height - textExtent.y) / 2 - 1; } + gc.drawText(stringToDisplay, realX, realY, isTransparent); + return len; }