### Eclipse Workspace Patch 1.0 #P org.eclipse.ua.tests Index: forms/org/eclipse/ua/tests/forms/AllFormsTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ua.tests/forms/org/eclipse/ua/tests/forms/AllFormsTests.java,v retrieving revision 1.1 diff -u -r1.1 AllFormsTests.java --- forms/org/eclipse/ua/tests/forms/AllFormsTests.java 10 Jul 2007 18:52:43 -0000 1.1 +++ forms/org/eclipse/ua/tests/forms/AllFormsTests.java 7 Sep 2007 21:51:19 -0000 @@ -15,6 +15,7 @@ import junit.framework.TestSuite; import org.eclipse.ua.tests.forms.layout.AllLayoutTests; +import org.eclipse.ua.tests.forms.util.AllUtilityTests; /* * Tests all cheat sheet functionality (automated). @@ -33,5 +34,6 @@ */ public AllFormsTests() { addTest(AllLayoutTests.suite()); + addTest(AllUtilityTests.suite()); } } Index: forms/org/eclipse/ua/tests/forms/util/FormImagesTests.java =================================================================== RCS file: forms/org/eclipse/ua/tests/forms/util/FormImagesTests.java diff -N forms/org/eclipse/ua/tests/forms/util/FormImagesTests.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ forms/org/eclipse/ua/tests/forms/util/FormImagesTests.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,75 @@ +package org.eclipse.ua.tests.forms.util; + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.internal.forms.widgets.FormImages; + +import junit.framework.Assert; +import junit.framework.TestCase; + +public class FormImagesTests extends TestCase { + public void testSingleton() { + Display display = Display.getCurrent(); + FormImages instance = FormImages.getInstance(); + // ensure the singleton is returning the same instance + Assert.assertTrue("getInstance() returned a different FormImages instance", instance.equals(FormImages.getInstance())); + Image gradient = instance.getGradient(display, new Color(display, 1, 1, 1), new Color(display, 7, 7, 7), 21, 21, 0); + instance.markFinished(gradient); + // ensure the singleton is returning the same instance after creating and disposing one gradient + Assert.assertTrue("getInstance() returned a different FormImages instance after creation and disposal of one image", instance.equals(FormImages.getInstance())); + } + + public void testDisposeOne() { + Display display = Display.getCurrent(); + Image gradient = FormImages.getInstance().getGradient(display, new Color(display, 255, 255, 255), new Color(display, 0, 0, 0), 21, 21, 0); + FormImages.getInstance().markFinished(gradient); + // ensure that getting a single gradient and marking it as finished disposed it + Assert.assertTrue("markFinished(...) did not dispose an image after a single getGradient()", gradient.isDisposed()); + } + + public void testMultipleInstances() { + Display display = Display.getCurrent(); + Image gradient = FormImages.getInstance().getGradient(display, new Color(display, 200, 200, 200), new Color(display, 0, 0, 0), 30, 16, 3); + int count; + // ensure that the same image is returned for many calls with the same parameter + for (count = 1; count < 20; count ++) + Assert.assertEquals("getGradient(...) returned a different image for the same params on iteration "+count, + gradient, FormImages.getInstance().getGradient(display, new Color(display, 200, 200, 200), new Color(display, 0, 0, 0), 30, 16, 3)); + for ( ;count > 0; count--) { + FormImages.getInstance().markFinished(gradient); + if (count != 1) + // ensure that the gradient is not disposed early + Assert.assertFalse("markFinished(...) disposed a shared image early on iteration "+count,gradient.isDisposed()); + else + // ensure that the gradient is disposed on the last markFinished + Assert.assertTrue("markFinished(...) did not dispose a shared image on the last call",gradient.isDisposed()); + } + } + + public void testMultipleUniqueInstances() { + Display display = Display.getCurrent(); + Image[] images = new Image[10]; + images[0] = FormImages.getInstance().getGradient(display, new Color(display, 1, 0, 0), new Color(display, 100, 100, 100), 25, 23, 1); + images[1] = FormImages.getInstance().getGradient(display, new Color(display, 0, 1, 0), new Color(display, 100, 100, 100), 25, 23, 1); + images[2] = FormImages.getInstance().getGradient(display, new Color(display, 0, 0, 1), new Color(display, 100, 100, 100), 25, 23, 1); + images[3] = FormImages.getInstance().getGradient(display, new Color(display, 0, 0, 0), new Color(display, 101, 100, 100), 25, 23, 1); + images[4] = FormImages.getInstance().getGradient(display, new Color(display, 0, 0, 0), new Color(display, 100, 101, 100), 25, 23, 1); + images[5] = FormImages.getInstance().getGradient(display, new Color(display, 0, 0, 0), new Color(display, 100, 100, 101), 25, 23, 1); + images[6] = FormImages.getInstance().getGradient(display, new Color(display, 0, 0, 0), new Color(display, 100, 100, 100), 20, 23, 1); + images[7] = FormImages.getInstance().getGradient(display, new Color(display, 0, 0, 0), new Color(display, 100, 100, 100), 25, 10, 1); + images[8] = FormImages.getInstance().getGradient(display, new Color(display, 0, 0, 0), new Color(display, 100, 100, 100), 25, 23, 2); + images[9] = FormImages.getInstance().getGradient(display, new Color(display, 1, 1, 1), new Color(display, 101, 101, 101), 20, 10, 2); + // ensure none of the images are the same + for (int i = 0; i < images.length - 1; i++) { + for (int j = i+1; j < images.length; j++) { + Assert.assertNotSame("getGradient(...) returned the same image for different parameters: i = " + i + "; j = " + j, images[i], images[j]); + } + } + // ensure all of the images are disposed with one call to markFinished + for (int i = 0; i < images.length; i++) { + FormImages.getInstance().markFinished(images[i]); + Assert.assertTrue("markFinished(...) did not dispose an image that was only requested once: i = " + i, images[i].isDisposed()); + } + } +} Index: forms/org/eclipse/ua/tests/forms/util/AllUtilityTests.java =================================================================== RCS file: forms/org/eclipse/ua/tests/forms/util/AllUtilityTests.java diff -N forms/org/eclipse/ua/tests/forms/util/AllUtilityTests.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ forms/org/eclipse/ua/tests/forms/util/AllUtilityTests.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ua.tests.forms.util; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/* + * Tests forms performance (automated). + */ +public class AllUtilityTests extends TestSuite { + + /* + * Returns the entire test suite. + */ + public static Test suite() { + return new AllUtilityTests(); + } + + /* + * Constructs a new performance test suite. + */ + public AllUtilityTests() { + addTestSuite(FormImagesTests.class); + } +} #P org.eclipse.ui.forms Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.forms/META-INF/MANIFEST.MF,v retrieving revision 1.14 diff -u -r1.14 MANIFEST.MF --- META-INF/MANIFEST.MF 9 Jul 2007 21:11:17 -0000 1.14 +++ META-INF/MANIFEST.MF 7 Sep 2007 21:51:20 -0000 @@ -10,7 +10,7 @@ org.eclipse.ui.forms.events, org.eclipse.ui.forms.widgets, org.eclipse.ui.internal.forms;x-internal:=true, - org.eclipse.ui.internal.forms.widgets;x-internal:=true + org.eclipse.ui.internal.forms.widgets;x-friends:="org.eclipse.ua.tests" Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.1.0,4.0.0)", org.eclipse.jface;bundle-version="[3.2.0,4.0.0)", org.eclipse.ui;bundle-version="[3.2.0,4.0.0)";resolution:=optional Index: src/org/eclipse/ui/forms/widgets/Section.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/Section.java,v retrieving revision 1.43 diff -u -r1.43 Section.java --- src/org/eclipse/ui/forms/widgets/Section.java 16 Mar 2007 20:24:01 -0000 1.43 +++ src/org/eclipse/ui/forms/widgets/Section.java 7 Sep 2007 21:51:20 -0000 @@ -27,6 +27,7 @@ import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.internal.forms.widgets.FormImages; import org.eclipse.ui.internal.forms.widgets.FormUtil; /** @@ -89,8 +90,9 @@ Listener listener = new Listener() { public void handleEvent(Event e) { Image image = Section.super.getBackgroundImage(); - if (image != null) - image.dispose(); + if (image != null) { + FormImages.getInstance().markFinished(image); + } Section.super.setBackgroundImage(null); } }; @@ -457,15 +459,7 @@ private void updateHeaderImage(Color bg, Rectangle bounds, int theight, int realtheight) { - Image image = new Image(getDisplay(), 1, realtheight); - image.setBackground(getBackground()); - GC gc = new GC(image); - gc.setBackground(getBackground()); - gc.fillRectangle(0, 0, 1, realtheight); - gc.setForeground(bg); - gc.setBackground(getBackground()); - gc.fillGradientRectangle(0, marginHeight + 2, 1, theight - 2, true); - gc.dispose(); + Image image = FormImages.getInstance().getGradient(getDisplay(), getBackground(), bg, realtheight, theight, marginHeight); super.setBackgroundImage(image); } Index: src/org/eclipse/ui/internal/forms/widgets/FormImages.java =================================================================== RCS file: src/org/eclipse/ui/internal/forms/widgets/FormImages.java diff -N src/org/eclipse/ui/internal/forms/widgets/FormImages.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/forms/widgets/FormImages.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.forms.widgets; + +import java.util.HashMap; + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; + +public class FormImages { + private static FormImages instance; + + public static FormImages getInstance() { + if (instance == null) + instance = new FormImages(); + return instance; + } + + private HashMap images; + private HashMap ids; + + private FormImages() { + } + + private class ImageIdentifier { + private Display fDisplay; + private Color fColor1; + private Color fColor2; + private int fRealtheight; + private int fTheight; + private int fMarginHeight; + + ImageIdentifier (Display display, Color color1, Color color2, + int realtheight, int theight, int marginHeight) { + fDisplay = display; + fColor1 = color1; + fColor2 = color2; + fRealtheight = realtheight; + fTheight = theight; + fMarginHeight = marginHeight; + } + + public boolean equals(Object obj) { + if (obj instanceof ImageIdentifier) { + ImageIdentifier id = (ImageIdentifier) obj; + if (id.fDisplay.equals(fDisplay) && id.fColor1.equals(fColor1) && + id.fColor2.equals(fColor2) && id.fRealtheight == fRealtheight && + id.fTheight == fTheight && id.fMarginHeight == fMarginHeight) + return true; + } + return false; + } + + public int hashCode() { + int hash = fDisplay.hashCode(); + hash = hash * 7 + fColor1.hashCode(); + hash = hash * 7 + fColor2.hashCode(); + hash = hash * 7 + new Integer(fRealtheight).hashCode(); + hash = hash * 7 + new Integer(fTheight).hashCode(); + hash = hash * 7 + new Integer(fMarginHeight).hashCode(); + return hash; + } + } + + private class ImageReference { + private Image fImage; + private int fCount; + + public ImageReference(Image image) { + fImage = image; + fCount = 1; + } + + public Image getImage() { + return fImage; + } + // returns a boolean indicating if all clients of this image are finished + // a true result indicates the underlying image should be disposed + public boolean decCount() { + return --fCount == 0; + } + public void incCount() { + fCount++; + } + } + + public Image getGradient(Display display, Color color1, Color color2, + int realtheight, int theight, int marginHeight) { + checkHashMaps(); + ImageIdentifier id = new ImageIdentifier(display, color1, color2, realtheight, theight, marginHeight); + ImageReference result = (ImageReference) images.get(id); + if (result != null && !result.getImage().isDisposed()) { + result.incCount(); + return result.getImage(); + } + Image image = createGradient(display, color1, color2, realtheight, theight, marginHeight); + images.put(id, new ImageReference(image)); + ids.put(image, id); + return image; + } + + public boolean markFinished(Image image) { + checkHashMaps(); + ImageIdentifier id = (ImageIdentifier)ids.get(image); + if (id != null) { + ImageReference ref = (ImageReference) images.get(id); + if (ref != null) { + if (ref.decCount()) { + images.remove(id); + ids.remove(ref.getImage()); + ref.getImage().dispose(); + validateHashMaps(); + } + return true; + } + } + return false; + } + + private void checkHashMaps() { + if (images == null) + images = new HashMap(); + if (ids == null) + ids = new HashMap(); + } + + private void validateHashMaps() { + if (images.size() == 0) + images = null; + if (ids.size() == 0) + ids = null; + } + + private Image createGradient(Display display, Color color1, Color color2, + int realtheight, int theight, int marginHeight) { + Image image = new Image(display, 1, realtheight); + image.setBackground(color1); + GC gc = new GC(image); + gc.setBackground(color1); + gc.fillRectangle(0, 0, 1, realtheight); + gc.setForeground(color2); + gc.setBackground(color1); + gc.fillGradientRectangle(0, marginHeight + 2, 1, theight - 2, true); + gc.dispose(); + return image; + } +}