/******************************************************************************* * Copyright (c) 2010 Yadu. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Yadu - initial API and implementation ******************************************************************************/ package code.google.restclient.ui; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.DeviceData; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Path; import org.eclipse.swt.graphics.Pattern; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.Region; import org.eclipse.swt.graphics.TextLayout; import org.eclipse.swt.graphics.Transform; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; /** * Instructions on how to use the Sleak tool with a standlaone SWT example: Modify the main method below to launch your application. Run Sleak. * * @author Yaduvendra.Singh */ public class LeakDetect { List list; Canvas canvas; Button start, stop, check; Text text; Label label; Object[] oldObjects = new Object[0]; Error[] oldErrors = new Error[0]; Object[] objects = new Object[0]; Error[] errors = new Error[0]; public static void main(String[] args) { DeviceData data = new DeviceData(); data.tracking = true; Display display = new Display(data); LeakDetect leakDetect = new LeakDetect(); Shell shell = new Shell(display); shell.setText("S-Leak"); Point size = shell.getSize(); shell.setSize(size.x / 2, size.y / 2); leakDetect.create(shell); shell.open(); new MainWindow().open(); // Launch your application here // e.g. // Shell shell = new Shell(display); // Button button1 = new Button(shell, SWT.PUSH); // button1.setBounds(10, 10, 100, 50); // button1.setText("Hello World"); // Image image = new Image(display, 20, 20); // Button button2 = new Button(shell, SWT.PUSH); // button2.setBounds(10, 70, 100, 50); // button2.setImage(image); // shell.open(); while ( !shell.isDisposed() ) { if ( !display.readAndDispatch() ) display.sleep(); } display.dispose(); } public void create(Composite parent) { list = new List(parent, SWT.BORDER | SWT.V_SCROLL); list.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { refreshObject(); } }); text = new Text(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); canvas = new Canvas(parent, SWT.BORDER); canvas.addListener(SWT.Paint, new Listener() { public void handleEvent(Event event) { paintCanvas(event); } }); check = new Button(parent, SWT.CHECK); check.setText("Stack"); check.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { toggleStackTrace(); } }); start = new Button(parent, SWT.PUSH); start.setText("Snap"); start.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { refreshAll(); } }); stop = new Button(parent, SWT.PUSH); stop.setText("Diff"); stop.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { refreshDifference(); } }); label = new Label(parent, SWT.BORDER); label.setText("0 object(s)"); parent.addListener(SWT.Resize, new Listener() { public void handleEvent(Event e) { layout(); } }); check.setSelection(false); text.setVisible(false); layout(); } void refreshLabel() { int colors = 0, cursors = 0, fonts = 0, gcs = 0, images = 0; int paths = 0, patterns = 0, regions = 0, textLayouts = 0, transforms = 0; for ( int i = 0; i < objects.length; i++ ) { Object object = objects[i]; if ( object instanceof Color ) colors++; if ( object instanceof Cursor ) cursors++; if ( object instanceof Font ) fonts++; if ( object instanceof GC ) gcs++; if ( object instanceof Image ) images++; if ( object instanceof Path ) paths++; if ( object instanceof Pattern ) patterns++; if ( object instanceof Region ) regions++; if ( object instanceof TextLayout ) textLayouts++; if ( object instanceof Transform ) transforms++; } String string = ""; if ( colors != 0 ) string += colors + " Color(s)\n"; if ( cursors != 0 ) string += cursors + " Cursor(s)\n"; if ( fonts != 0 ) string += fonts + " Font(s)\n"; if ( gcs != 0 ) string += gcs + " GC(s)\n"; if ( images != 0 ) string += images + " Image(s)\n"; if ( paths != 0 ) string += paths + " Paths(s)\n"; if ( patterns != 0 ) string += patterns + " Pattern(s)\n"; if ( regions != 0 ) string += regions + " Region(s)\n"; if ( textLayouts != 0 ) string += textLayouts + " TextLayout(s)\n"; if ( transforms != 0 ) string += transforms + " Transform(s)\n"; if ( string.length() != 0 ) { string = string.substring(0, string.length() - 1); } label.setText(string); } void refreshDifference() { Display display = canvas.getDisplay(); DeviceData info = display.getDeviceData(); if ( !info.tracking ) { Shell shell = canvas.getShell(); MessageBox dialog = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK); dialog.setText(shell.getText()); dialog.setMessage("Warning: Device is not tracking resource allocation"); dialog.open(); } Object[] newObjects = info.objects; Error[] newErrors = info.errors; Object[] diffObjects = new Object[newObjects.length]; Error[] diffErrors = new Error[newErrors.length]; int count = 0; for ( int i = 0; i < newObjects.length; i++ ) { int index = 0; while ( index < oldObjects.length ) { if ( newObjects[i] == oldObjects[index] ) break; index++; } if ( index == oldObjects.length ) { diffObjects[count] = newObjects[i]; diffErrors[count] = newErrors[i]; count++; } } objects = new Object[count]; errors = new Error[count]; System.arraycopy(diffObjects, 0, objects, 0, count); System.arraycopy(diffErrors, 0, errors, 0, count); list.removeAll(); text.setText(""); canvas.redraw(); for ( int i = 0; i < objects.length; i++ ) { list.add(objects[i].toString()); } refreshLabel(); layout(); } void toggleStackTrace() { refreshObject(); layout(); } void paintCanvas(Event event) { canvas.setCursor(null); int index = list.getSelectionIndex(); if ( index == -1 ) return; GC gc = event.gc; Object object = objects[index]; if ( object instanceof Color ) { if ( ((Color) object).isDisposed() ) return; gc.setBackground((Color) object); gc.fillRectangle(canvas.getClientArea()); return; } if ( object instanceof Cursor ) { if ( ((Cursor) object).isDisposed() ) return; canvas.setCursor((Cursor) object); return; } if ( object instanceof Font ) { if ( ((Font) object).isDisposed() ) return; gc.setFont((Font) object); FontData[] array = gc.getFont().getFontData(); String string = ""; String lf = text.getLineDelimiter(); for ( int i = 0; i < array.length; i++ ) { FontData data = array[i]; String style = "NORMAL"; int bits = data.getStyle(); if ( bits != 0 ) { if ( (bits & SWT.BOLD) != 0 ) style = "BOLD "; if ( (bits & SWT.ITALIC) != 0 ) style += "ITALIC"; } string += data.getName() + " " + data.getHeight() + " " + style + lf; } gc.drawString(string, 0, 0); return; } // NOTHING TO DRAW FOR GC // if (object instanceof GC) { // return; // } if ( object instanceof Image ) { if ( ((Image) object).isDisposed() ) return; gc.drawImage((Image) object, 0, 0); return; } if ( object instanceof Path ) { if ( ((Path) object).isDisposed() ) return; gc.drawPath((Path) object); return; } if ( object instanceof Pattern ) { if ( ((Pattern) object).isDisposed() ) return; gc.setBackgroundPattern((Pattern) object); gc.fillRectangle(canvas.getClientArea()); gc.setBackgroundPattern(null); return; } if ( object instanceof Region ) { if ( ((Region) object).isDisposed() ) return; String string = ((Region) object).getBounds().toString(); gc.drawString(string, 0, 0); return; } if ( object instanceof TextLayout ) { if ( ((TextLayout) object).isDisposed() ) return; ((TextLayout) object).draw(gc, 0, 0); return; } if ( object instanceof Transform ) { if ( ((Transform) object).isDisposed() ) return; String string = ((Transform) object).toString(); gc.drawString(string, 0, 0); return; } } void refreshObject() { int index = list.getSelectionIndex(); if ( index == -1 ) return; if ( check.getSelection() ) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); PrintStream s = new PrintStream(stream); errors[index].printStackTrace(s); text.setText(stream.toString()); text.setVisible(true); canvas.setVisible(false); } else { canvas.setVisible(true); text.setVisible(false); canvas.redraw(); } } void refreshAll() { oldObjects = new Object[0]; oldErrors = new Error[0]; refreshDifference(); oldObjects = objects; oldErrors = errors; } void layout() { Composite parent = canvas.getParent(); Rectangle rect = parent.getClientArea(); int width = 0; String[] items = list.getItems(); GC gc = new GC(list); for ( int i = 0; i < objects.length; i++ ) { width = Math.max(width, gc.stringExtent(items[i]).x); } gc.dispose(); Point size1 = start.computeSize(SWT.DEFAULT, SWT.DEFAULT); Point size2 = stop.computeSize(SWT.DEFAULT, SWT.DEFAULT); Point size3 = check.computeSize(SWT.DEFAULT, SWT.DEFAULT); Point size4 = label.computeSize(SWT.DEFAULT, SWT.DEFAULT); width = Math.max(size1.x, Math.max(size2.x, Math.max(size3.x, width))); width = Math.max(64, Math.max(size4.x, list.computeSize(width, SWT.DEFAULT).x)); start.setBounds(0, 0, width, size1.y); stop.setBounds(0, size1.y, width, size2.y); check.setBounds(0, size1.y + size2.y, width, size3.y); label.setBounds(0, rect.height - size4.y, width, size4.y); int height = size1.y + size2.y + size3.y; list.setBounds(0, height, width, rect.height - height - size4.y); text.setBounds(width, 0, rect.width - width, rect.height); canvas.setBounds(width, 0, rect.width - width, rect.height); } }