Bug 563477: Allow enable/disable SWT Resource Tracking at runtime

S-Leak can then take advantage of this with a new checkbox to
allow resource tracking to start

Change-Id: I28c47d4efaa57ba910372fbef590d79dd8f6a97f
Signed-off-by: Jonah Graham <jonah@kichwacoders.com>
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 6dc715a..27246a2 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
@@ -29,7 +29,7 @@
 public class Sleak {
 	List list;
 	Canvas canvas;
-	Button snapshot, diff, stackTrace, saveAs, save;
+	Button enableTracking, snapshot, diff, stackTrace, saveAs, save;
 	Text text;
 	Label label;
 	
@@ -81,6 +81,11 @@
 	text = new Text (parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
 	canvas = new Canvas (parent, SWT.BORDER);
 	canvas.addListener (SWT.Paint, event -> paintCanvas (event));
+	enableTracking = new Button (parent, SWT.CHECK);
+	enableTracking.setText ("Enable");
+	enableTracking.setToolTipText("Enable Device resource tracking. Only resources allocated once enabled will be tracked. To track devices created before view is created, turn on tracing options, see https://www.eclipse.org/swt/tools.php");
+	enableTracking.addListener (SWT.Selection, e -> toggleEnableTracking ());
+	enableTracking.setSelection(enableTracking.getDisplay().isTracking());
 	stackTrace = new Button (parent, SWT.CHECK);
 	stackTrace.setText ("Stack");
 	stackTrace.addListener (SWT.Selection, e -> toggleStackTrace ());
@@ -106,6 +111,12 @@
 	layout();
 }
 
+private void toggleEnableTracking() {
+	Display display = enableTracking.getDisplay();
+	boolean tracking = display.isTracking();
+	display.setTracking(!tracking);
+}
+
 void refreshLabel () {
 	int cursors = 0, fonts = 0, gcs = 0, images = 0;
 	int paths = 0, patterns = 0, regions = 0, textLayouts = 0, transforms= 0;
@@ -141,10 +152,13 @@
 	DeviceData info = display.getDeviceData ();
 	if (!info.tracking) {
 		Shell shell = canvas.getShell();
-		MessageBox dialog = new MessageBox (shell, SWT.ICON_WARNING | SWT.OK);
+		MessageBox dialog = new MessageBox (shell, SWT.ICON_WARNING | SWT.YES | SWT.NO);
 		dialog.setText (shell.getText ());
-		dialog.setMessage ("Warning: Device is not tracking resource allocation");
-		dialog.open ();
+		dialog.setMessage ("Warning: Device is not tracking resource allocation\nWould you like to enable tracking now for future created resources?");
+		if (SWT.YES == dialog.open ()) {
+			enableTracking.setSelection(true);
+			toggleEnableTracking();
+		}
 	}
 	int size = 0;
 	for (int i = 0; i < info.objects.length; i++) {
@@ -374,23 +388,26 @@
 		width = Math.max (width, gc.stringExtent (items [i]).x);
 	}
 	gc.dispose ();
+	Point enableTrackingSize = enableTracking.computeSize (SWT.DEFAULT, SWT.DEFAULT);
 	Point snapshotSize = snapshot.computeSize (SWT.DEFAULT, SWT.DEFAULT);
 	Point diffSize = diff.computeSize (SWT.DEFAULT, SWT.DEFAULT);
 	Point stackSize = stackTrace.computeSize (SWT.DEFAULT, SWT.DEFAULT);
 	Point labelSize = label.computeSize (SWT.DEFAULT, SWT.DEFAULT);
 	Point saveAsSize = saveAs.computeSize (SWT.DEFAULT, SWT.DEFAULT);
 	Point saveSize = save.computeSize (SWT.DEFAULT, SWT.DEFAULT);
+	width = Math.max (enableTrackingSize.x, width);
 	width = Math.max (snapshotSize.x, Math.max (diffSize.x, Math.max (stackSize.x, width)));
 	width = Math.max (saveAsSize.x, Math.max (saveSize.x, width));
 	width = Math.max (labelSize.x, list.computeSize (width, SWT.DEFAULT).x);
 	width = Math.max (64, width);
-	snapshot.setBounds (0, 0, width, snapshotSize.y);
-	diff.setBounds (0, snapshotSize.y, width, diffSize.y);
-	stackTrace.setBounds (0, snapshotSize.y + diffSize.y, width, stackSize.y);
+	enableTracking.setBounds (0, 0, width, enableTrackingSize.y);
+	snapshot.setBounds (0, enableTrackingSize.y, width, snapshotSize.y);
+	diff.setBounds (0, enableTrackingSize.y + snapshotSize.y, width, diffSize.y);
+	stackTrace.setBounds (0, enableTrackingSize.y + snapshotSize.y + diffSize.y, width, stackSize.y);
 	label.setBounds (0, rect.height - saveSize.y - saveAsSize.y - labelSize.y, width, labelSize.y);
 	saveAs.setBounds (0, rect.height - saveSize.y - saveAsSize.y, width, saveAsSize.y);
 	save.setBounds (0, rect.height - saveSize.y, width, saveSize.y);
-	int height = snapshotSize.y + diffSize.y + stackSize.y;
+	int height = enableTrackingSize.y + snapshotSize.y + diffSize.y + stackSize.y;
 	list.setBounds (0, height, width, rect.height - height - labelSize.y - saveAsSize.y -saveSize.y);
 	text.setBounds (width, 0, rect.width - width, rect.height);
 	canvas.setBounds (width, 0, rect.width - width, rect.height);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Device.java
index 5ca39ae..92b6ed8 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Device.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Device.java
@@ -111,9 +111,7 @@
 			tracking = data.tracking;
 		}
 		if (tracking) {
-			errors = new Error [128];
-			objects = new Object [128];
-			trackingLock = new Object ();
+			startTracking();
 		}
 		if (NSThread.isMainThread()) {
 			NSAutoreleasePool pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
@@ -135,6 +133,52 @@
 }
 
 /**
+*
+* @exception SWTException <ul>
+*    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+* </ul>
+* @since 3.115
+*/
+public boolean isTracking() {
+	checkDevice();
+	return tracking;
+}
+
+/**
+* @exception SWTException <ul>
+*    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+* </ul>
+* @since 3.115
+*/
+public void setTracking(boolean tracking) {
+	checkDevice();
+	if (tracking == this.tracking) {
+		return;
+	}
+	this.tracking = tracking;
+	if (tracking) {
+		startTracking();
+	} else {
+		stopTracking();
+	}
+}
+
+private void startTracking() {
+	errors = new Error [128];
+	objects = new Object [128];
+	trackingLock = new Object ();
+}
+
+private void stopTracking() {
+	synchronized (trackingLock) {
+		objects = null;
+		errors = null;
+		trackingLock = null;
+	}
+}
+
+
+/**
  * Throws an <code>SWTException</code> if the receiver can not
  * be accessed by the caller. This may include both checks on
  * the state of the receiver and more generally on the entire
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java
index c042c8f..a102f27 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java
@@ -161,9 +161,7 @@
 			tracking = data.tracking;
 		}
 		if (tracking) {
-			errors = new Error [128];
-			objects = new Object [128];
-			trackingLock = new Object ();
+			startTracking();
 		}
 		create (data);
 		init ();
@@ -172,6 +170,51 @@
 }
 
 /**
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @since 3.115
+ */
+public boolean isTracking() {
+	checkDevice();
+	return tracking;
+}
+
+/**
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @since 3.115
+ */
+public void setTracking(boolean tracking) {
+	checkDevice();
+	if (tracking == this.tracking) {
+		return;
+	}
+	this.tracking = tracking;
+	if (tracking) {
+		startTracking();
+	} else {
+		stopTracking();
+	}
+}
+
+private void startTracking() {
+	errors = new Error [128];
+	objects = new Object [128];
+	trackingLock = new Object ();
+}
+
+private void stopTracking() {
+	synchronized (trackingLock) {
+		objects = null;
+		errors = null;
+		trackingLock = null;
+	}
+}
+
+/**
  * Throws an <code>SWTException</code> if the receiver can not
  * be accessed by the caller. This may include both checks on
  * the state of the receiver and more generally on the entire
@@ -232,11 +275,8 @@
 		xDisplay = 0;
 		disposed = true;
 		if (tracking) {
-			synchronized (trackingLock) {
-				objects = null;
-				errors = null;
-				trackingLock = null;
-			}
+			tracking = false;
+			stopTracking();
 		}
 	}
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Device.java
index d803b0a..067d23e 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Device.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Device.java
@@ -121,15 +121,60 @@
 			tracking = data.tracking;
 		}
 		if (tracking) {
-			errors = new Error [128];
-			objects = new Object [128];
-			trackingLock = new Object ();
+			startTracking();
 		}
 		create (data);
 		init ();
 	}
 }
 
+/**
+*
+* @exception SWTException <ul>
+*    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+* </ul>
+* @since 3.115
+*/
+public boolean isTracking() {
+	checkDevice();
+	return tracking;
+}
+
+/**
+* @exception SWTException <ul>
+*    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+* </ul>
+* @since 3.115
+*/
+public void setTracking(boolean tracking) {
+	checkDevice();
+	if (tracking == this.tracking) {
+		return;
+	}
+	this.tracking = tracking;
+	if (tracking) {
+		startTracking();
+	} else {
+		stopTracking();
+	}
+}
+
+private void startTracking() {
+	errors = new Error [128];
+	objects = new Object [128];
+	trackingLock = new Object ();
+}
+
+private void stopTracking() {
+	synchronized (trackingLock) {
+		objects = null;
+		errors = null;
+		trackingLock = null;
+	}
+}
+
+
+
 void addFont (String font) {
 	if (loadedFonts == null) loadedFonts = new String [4];
 	int length = loadedFonts.length;