Bug 578696 - adjusts Sleak to show non-disposed widgets in diffs.

Change-Id: I77ef5966fa2477ca3558d6248af51fc83e82d8a9
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.swt/+/191044
Tested-by: Andrey Loskutov <loskutov@gmx.de>
Reviewed-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/bundles/org.eclipse.swt.tools.spies/META-INF/MANIFEST.MF b/bundles/org.eclipse.swt.tools.spies/META-INF/MANIFEST.MF
index 123f520..08b3d9e 100644
--- a/bundles/org.eclipse.swt.tools.spies/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.swt.tools.spies/META-INF/MANIFEST.MF
@@ -12,7 +12,7 @@
 Require-Bundle: org.eclipse.core.runtime;bundle-version="3.4.0",
  org.eclipse.swt.tools.base;bundle-version="3.106.0",
  org.eclipse.e4.ui.model.workbench;bundle-version="2.1.400",
- org.eclipse.swt;bundle-version="3.110.100",
+ org.eclipse.swt;bundle-version="3.119.0",
  org.eclipse.ui;bundle-version="3.113.0",
  org.eclipse.e4.ui.di;bundle-version="1.2.600"
 Automatic-Module-Name: org.eclipse.swt.tools.spies
diff --git a/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java b/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java
index f64394f..8d9655d 100644
--- a/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java
+++ b/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java
@@ -21,6 +21,7 @@
 import org.eclipse.swt.*;
 import org.eclipse.swt.custom.*;
 import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.WidgetSpy.*;
 import org.eclipse.swt.layout.*;
 import org.eclipse.swt.widgets.*;
 import org.eclipse.swt.widgets.List;
@@ -38,7 +39,6 @@
 	Button enableTracking, diff, stackTrace, saveAs, save;
 	Combo diffType;
 	Text text;
-	Label label;
 
 	String filterPath = "";
 	String fileName = "sleakout";
@@ -50,6 +50,8 @@
 	java.util.List<ObjectWithError> oldObjects = new ArrayList<> ();
 	java.util.List<ObjectWithError> objects = new ArrayList<> ();
 
+	NonDisposedWidgetTracker nonDisposedWidgetTracker = new NonDisposedWidgetTracker();
+
 public static void main (String [] args) {
 	DeviceData data = new DeviceData();
 	data.tracking = true;
@@ -164,19 +166,17 @@
 
 	list = new List (left, SWT.BORDER | SWT.V_SCROLL);
 	list.addListener (SWT.Selection, event -> refreshObject ());
-	list.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, true));
-
-	label = new Label (left, SWT.WRAP);
-	label.setText ("0 object(s)");
-	label.setLayoutData(new GridData(SWT.FILL, SWT.NONE, false, false));
+	list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
 
 	stackTrace.setSelection (false);
+	filterNonDisposedWidgetTypes();
 }
 
 private void toggleEnableTracking() {
 	Display display = enableTracking.getDisplay();
 	boolean tracking = display.isTracking();
 	display.setTracking(!tracking);
+	setWidgetTrackingEnabled(tracking);
 }
 
 void refreshLabel (java.util.List<ObjectWithError> createdObjects, java.util.List<ObjectWithError> deletedObjects) {
@@ -193,8 +193,7 @@
 	deletedAndCreated.distinct().sorted().forEach(type -> addCounts(sb, type, deleted.get(type), created.get(type)));
 
 	String description = sb.length() > 0 ? sb.toString() :  "0 object(s)";
-	label.setText (description.strip());
-	label.getParent().layout();
+	list.setToolTipText(description);
 }
 
 static void addCounts (StringBuilder string, String type, Long deleted, Long created) {
@@ -222,23 +221,29 @@
 	java.util.List<ObjectWithError> disposed = new ArrayList<>();
 	java.util.List<ObjectWithError> created = new ArrayList<>();
 	java.util.List<ObjectWithError> same = collectNewObjects(info, old, disposed, created);
-
+	java.util.List<ObjectWithError> nonDisposedWidgets = getNonDisposedWidgets();
+	created.addAll(nonDisposedWidgets);
+	resetNonDisposedWidgets();
 
 	if (diffType.getSelectionIndex() > 0) {
-		Iterator<ObjectWithError> object = created.iterator ();
-		while (object.hasNext ()) {
-			StackTraceElement stack = object.next ().getCreator ();
-			Iterator<ObjectWithError> equal = same.iterator ();
-			while (equal.hasNext ()) {
-				if (creatorEquals(stack, equal.next().getCreator ())) {
-					equal.remove ();
-					object.remove ();
-					break;
+		old.removeAll(same);
+		if (!old.isEmpty()) {
+			Iterator<ObjectWithError> createdIter = created.iterator ();
+			while (createdIter.hasNext ()) {
+				ObjectWithError createdObj = createdIter.next ();
+				StackTraceElement stack = createdObj.getCreator ();
+				Iterator<ObjectWithError> oldIter = old.iterator ();
+				while (oldIter.hasNext ()) {
+					ObjectWithError oldObj = oldIter.next();
+					if (creatorEquals(stack, oldObj.getCreator ())) {
+						createdIter.remove ();
+						break;
+					}
 				}
 			}
 		}
 	}
-
+	
 	objects.clear();
 	objects.addAll(created);
 
@@ -483,6 +488,28 @@
 	((GridData)control.getLayoutData()).exclude = !visible;
 }
 
+private void filterNonDisposedWidgetTypes() {
+	java.util.List<Class<? extends Widget>> trackedTypes = Arrays.asList(
+//		Composite.class, 
+//		Menu.class
+	);
+	nonDisposedWidgetTracker.setTrackedTypes(trackedTypes);
+}
+
+private void setWidgetTrackingEnabled(boolean tracking) {
+	nonDisposedWidgetTracker.setTrackingEnabled(tracking);
+}
+
+private java.util.List<ObjectWithError> getNonDisposedWidgets() {
+	java.util.List<ObjectWithError> nonDisposedWidgets = new ArrayList<>();
+	nonDisposedWidgetTracker.getNonDisposedWidgets().forEach((w, e) -> nonDisposedWidgets.add(new ObjectWithError(w, e)));
+	return nonDisposedWidgets;
+}
+
+private void resetNonDisposedWidgets() {
+	nonDisposedWidgetTracker.startTracking();
+}
+
 private static final class ObjectWithError {
 	final Object object;
 	final Error error;