Bug 574833: Fix not disposed GC in ShortedLabel
Change-Id: Ibdcff18944b5aa6223add0cff86e2d58a60ca1ff
diff --git a/ecommons/org.eclipse.statet.ecommons.uimisc/src/org/eclipse/statet/ecommons/ui/components/ShortedLabel.java b/ecommons/org.eclipse.statet.ecommons.uimisc/src/org/eclipse/statet/ecommons/ui/components/ShortedLabel.java
index 5d79876..e463072 100644
--- a/ecommons/org.eclipse.statet.ecommons.uimisc/src/org/eclipse/statet/ecommons/ui/components/ShortedLabel.java
+++ b/ecommons/org.eclipse.statet.ecommons.uimisc/src/org/eclipse/statet/ecommons/ui/components/ShortedLabel.java
@@ -14,6 +14,8 @@
package org.eclipse.statet.ecommons.ui.components;
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
+
import java.util.regex.Pattern;
import org.eclipse.swt.SWT;
@@ -24,6 +26,8 @@
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
/**
* Replacement for CLabel.
@@ -33,20 +37,22 @@
* - Better algorithm (faster and prettier).
* - Hover text.
*/
+@NonNullByDefault
public class ShortedLabel {
- private static final Pattern fLineBreakPattern = Pattern.compile("\\r[\\n]?|\\n"); //$NON-NLS-1$
+ private static final Pattern LINEBREAK_PATTERN= Pattern.compile("\\r[\\n]?|\\n"); //$NON-NLS-1$
- private String fText;
- private String fCheckedText;
- private final Label fLabel;
- private String fLineBreakReplacement = " "; //$NON-NLS-1$
+ private String text;
+ private String checkedText;
+
+ private final Label label;
+ private String lineBreakReplacement= " "; //$NON-NLS-1$
public ShortedLabel(final Composite parent, final int style) {
- fLabel = new Label(parent, style);
- fLabel.addListener(SWT.Resize, new Listener() {
+ this.label= new Label(parent, style);
+ this.label.addListener(SWT.Resize, new Listener() {
@Override
public void handleEvent(final Event event) {
updateShortening();
@@ -55,7 +61,7 @@
}
public Label getControl() {
- return fLabel;
+ return this.label;
}
public void setText(final String label) {
@@ -63,89 +69,102 @@
throw new NullPointerException();
}
- if (label.equals(fText)) {
+ if (label.equals(this.text)) {
return;
}
- fText = label;
+ this.text= label;
updateChecking();
updateShortening();
}
public void setLineBreakReplacement(final String s) {
- assert (s != null);
-
- fLineBreakReplacement = s;
- if (fText != null) {
+ this.lineBreakReplacement= nonNullAssert(s);
+ if (this.text != null) {
updateChecking();
}
}
private void updateChecking() {
- fCheckedText = fLineBreakPattern.matcher(fText).replaceAll(fLineBreakReplacement);
+ this.checkedText= LINEBREAK_PATTERN.matcher(this.text).replaceAll(this.lineBreakReplacement);
}
private void updateShortening() {
- final String text = new Shorter(fLabel).shorten(fCheckedText);
- fLabel.setText(text);
- fLabel.setToolTipText((text == fCheckedText) ? null : fText);
+ final Shorter shorter= new Shorter(this.label);
+ try {
+ final String text= shorter.shorten(this.checkedText);
+ this.label.setText(text);
+ this.label.setToolTipText((text == this.checkedText) ? null : this.text);
+ }
+ finally {
+ shorter.dispose();
+ }
}
private static class Shorter {
- private static final String ELLIPSIS = " ... "; //$NON-NLS-1$
- private static final int DRAW_FLAGS = SWT.DRAW_TAB;
+ private static final String ELLIPSIS= " ... "; //$NON-NLS-1$
+ private static final int DRAW_FLAGS= SWT.DRAW_TAB;
- Control fControl;
- GC fGC;
- int fMaxWidth;
+ private final Control control;
+ private GC gc;
+ private int maxWidth;
- String fText;
+ private String text;
public Shorter(final Control control) {
- fControl = control;
+ this.control= control;
}
+ public void dispose() {
+ final var gc= this.gc;
+ if (gc != null) {
+ this.gc= null;
+ gc.dispose();
+ }
+ }
+
+
public String shorten(final String text) {
if (text == null || text.isEmpty()) {
return text;
}
- if (fGC == null) {
- fGC = new GC(fControl);
- fMaxWidth = fControl.getBounds().width;
+ if (this.gc == null) {
+ this.gc= new GC(this.control);
+ this.maxWidth= this.control.getBounds().width;
}
- if (fGC.textExtent(text, DRAW_FLAGS).x <= fMaxWidth) {
+ if (this.gc.textExtent(text, DRAW_FLAGS).x <= this.maxWidth) {
return text;
}
- fText = text;
- final String shortedText = doShorten();
- fText = null;
+ this.text= text;
+ final String shortedText= doShorten();
+ this.text= null;
return shortedText;
}
private String doShorten() {
- final double avgCharWidth = fGC.getFontMetrics().getAverageCharacterWidth();
- final int textLength = fText.length();
+ final double avgCharWidth= this.gc.getFontMetrics().getAverageCharacterWidth();
+ final int textLength= this.text.length();
- final int ellipsisWidth = fGC.textExtent(ELLIPSIS, DRAW_FLAGS).x;
+ final int ellipsisWidth= this.gc.textExtent(ELLIPSIS, DRAW_FLAGS).x;
- int max2 = (fMaxWidth-ellipsisWidth) * 42 / 100;
+ int max2= (this.maxWidth-ellipsisWidth) * 42 / 100;
if (max2 < avgCharWidth * 3) {
- max2 = 0;
+ max2= 0;
}
- int e = Math.max(textLength - (int)(max2 / avgCharWidth), 0);
- int w2 = measurePart2(e);
+ int e= Math.max(textLength - (int)(max2 / avgCharWidth), 0);
+ int w2= measurePart2(e);
while (w2 > max2 && e < textLength) {
- w2 = measurePart2(e++);
+ w2= measurePart2(e++);
}
while (e > 0) {
- final int test = measurePart2(e-1);
+ final int test= measurePart2(e-1);
if (test <= max2) {
e--;
- w2 = test;
+ w2= test;
continue;
}
else {
@@ -153,17 +172,17 @@
}
}
- final int max1 = fMaxWidth-ellipsisWidth-w2;
- int s = Math.min((int)(max2 / avgCharWidth), textLength);
- int w1 = measurePart1(s);
+ final int max1= this.maxWidth-ellipsisWidth-w2;
+ int s= Math.min((int)(max2 / avgCharWidth), textLength);
+ int w1= measurePart1(s);
while (w1 > max1 && s > 3) {
- w1 = measurePart1(s--);
+ w1= measurePart1(s--);
}
while (s < textLength) {
- final int test = measurePart1(s+1);
+ final int test= measurePart1(s + 1);
if (test <= max1) {
s++;
- w1 = test;
+ w1= test;
continue;
}
else {
@@ -171,15 +190,15 @@
}
}
- return fText.substring(0, s)+ELLIPSIS+fText.substring(e, textLength);
+ return this.text.substring(0, s) + ELLIPSIS + this.text.substring(e, textLength);
}
private int measurePart1(final int end) {
- return fGC.textExtent(fText.substring(0, end), DRAW_FLAGS).x;
+ return this.gc.textExtent(this.text.substring(0, end), DRAW_FLAGS).x;
}
private int measurePart2(final int start) {
- return fGC.textExtent(fText.substring(start), DRAW_FLAGS).x;
+ return this.gc.textExtent(this.text.substring(start), DRAW_FLAGS).x;
}
}