cleaning up leaks in Pane and our custom widgets
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledButton.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledButton.java
index a1d6d29..260fe25 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledButton.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledButton.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2008 Oracle. All rights reserved. This
+ *  Copyright (c) 2008, 2012 Oracle. 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
@@ -9,6 +9,7 @@
 package org.eclipse.jpt.common.ui.internal.util;
 
 import org.eclipse.core.runtime.Assert;
+import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.widgets.Button;
 
@@ -16,7 +17,7 @@
  * A default implementation of <code>LabeledControl</code> that updates a
  * <code>Button</code> when required.
  *
- * @version 2.0
+ * @version 3.3
  * @since 2.0
  */
 @SuppressWarnings("nls")
@@ -42,6 +43,14 @@
 		this.button = button;
 	}
 
+	public void addDisposeListener(DisposeListener disposeListener) {
+		this.button.addDisposeListener(disposeListener);
+	}
+
+	public void removeDisposeListener(DisposeListener disposeListener) {
+		this.button.removeDisposeListener(disposeListener);
+	}
+
 	/*
 	 * (non-Javadoc)
 	 */
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledControl.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledControl.java
index 2cef0dc..07d6e76 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledControl.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledControl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2008 Oracle. All rights reserved. This
+ *  Copyright (c) 2008, 2012 Oracle. 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
@@ -8,6 +8,7 @@
  *******************************************************************************/
 package org.eclipse.jpt.common.ui.internal.util;
 
+import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.graphics.Image;
 
 /**
@@ -17,7 +18,7 @@
  * @see LabeledButton
  * @see LabeledLabel
  *
- * @version 2.0
+ * @version 3.3
  * @since 2.0
  */
 public interface LabeledControl {
@@ -34,4 +35,15 @@
 	 * @param text The new text
 	 */
 	void setText(String text);
+
+	/**
+	 * Convenience method: Adds a dispose listener to the check box.
+	 * The source of any events sent to the listener will be the wrapped control.
+	 */
+	void addDisposeListener(DisposeListener disposeListener);
+
+	/**
+	 * Convenience method: Removes a dispose listener from the wrapped control.
+	 */
+	void removeDisposeListener(DisposeListener disposeListener);
 }
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledControlUpdater.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledControlUpdater.java
index 8be9813..62bba80 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledControlUpdater.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledControlUpdater.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008 Oracle. All rights reserved.
+ * Copyright (c) 2008, 2012 Oracle. 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.
@@ -14,13 +14,15 @@
 import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent;
 import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener;
 import org.eclipse.jpt.common.utility.model.value.PropertyValueModel;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.graphics.Image;
 
 /**
  * This updater is responsible to update the <code>LabeledControl</code> when
  * the text and the icon need to change.
  *
- * @version 2.0
+ * @version 3.3
  * @since 2.0
  */
 @SuppressWarnings("nls")
@@ -32,16 +34,32 @@
 	private LabeledControl labeledControl;
 
 	/**
+	 * A listener that allows us to stop listening to stuff when the control
+	 * is disposed. (Critical for preventing memory leaks.)
+	 */
+	protected DisposeListener disposeListener;
+
+	/** A value model on the underlying model text. */
+	protected final PropertyValueModel<String> textModel;
+
+	protected PropertyChangeListener textListener;
+
+	/** A value model on the underlying model image. */
+	protected final PropertyValueModel<Image> imageModel;
+
+	protected PropertyChangeListener imageListener;
+
+	/**
 	 * Creates a new <code>LabeledControlUpdater</code>.
 	 *
 	 * @param labeledControl The wrapper around the control that needs to
 	 * have its text updated
-	 * @param textHolder The holder this class will listen for changes
+	 * @param textModel The holder this class will listen for changes
 	 */
 	public LabeledControlUpdater(LabeledControl labeledControl,
-	                             PropertyValueModel<String> textHolder)
+	                             PropertyValueModel<String> textModel)
 	{
-		this(labeledControl, textHolder, null);
+		this(labeledControl, textModel, null);
 	}
 
 	/**
@@ -49,24 +67,42 @@
 	 *
 	 * @param labeledControl The wrapper around the control that needs to
 	 * have its image and text updated
-	 * @param imageHolder The holder this class will listen for changes or
+	 * @param imageModel The holder this class will listen for changes or
 	 * <code>null</code> if the text never changes
-	 * @param textHolder The holder this class will listen for changes or
+	 * @param textModel The holder this class will listen for changes or
 	 * <code>null</code> if the image never changes
 	 */
 	public LabeledControlUpdater(LabeledControl labeledControl,
-	                             PropertyValueModel<String> textHolder,
-	                             PropertyValueModel<Image> imageHolder)
+	                             PropertyValueModel<String> textModel,
+	                             PropertyValueModel<Image> imageModel)
 	{
 		super();
-		initialize(labeledControl, textHolder, imageHolder);
+		Assert.isNotNull(labeledControl, "The LabeledControl cannot be null");
+		this.labeledControl = labeledControl;
+		this.textModel = textModel;
+		this.imageModel = imageModel;
+
+		if (this.textModel != null) {
+			this.textListener = this.buildTextListener();
+			this.textModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.textListener);
+			this.setText(this.textModel.getValue());
+		}
+
+		if (this.imageModel != null) {
+			this.imageListener = this.buildImageListener();
+			this.imageModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.imageListener);
+			this.setImage(this.imageModel.getValue());
+		}
+
+		this.disposeListener = this.buildDisposeListener();
+		this.labeledControl.addDisposeListener(this.disposeListener);
 	}
 
-	private PropertyChangeListener buildIconListener() {
-		return new SWTPropertyChangeListenerWrapper(buildIconListener_());
+	private PropertyChangeListener buildImageListener() {
+		return new SWTPropertyChangeListenerWrapper(this.buildImageListener_());
 	}
 
-	private PropertyChangeListener buildIconListener_() {
+	private PropertyChangeListener buildImageListener_() {
 		return new PropertyChangeListener() {
 			public void propertyChanged(PropertyChangeEvent e) {
 				LabeledControlUpdater.this.setImage((Image) e.getNewValue());
@@ -96,35 +132,43 @@
 		};
 	}
 
-	private void initialize(LabeledControl labeledControl,
-	                        PropertyValueModel<String> textHolder,
-	                        PropertyValueModel<Image> imageHolder)
-	{
-		Assert.isNotNull(labeledControl, "The LabeledControl cannot be null");
-
-		this.labeledControl = labeledControl;
-
-		if (textHolder != null) {
-			textHolder.addPropertyChangeListener(PropertyValueModel.VALUE, buildTextListener());
-			setText(textHolder.getValue());
-		}
-
-		if (imageHolder != null) {
-			imageHolder.addPropertyChangeListener(PropertyValueModel.VALUE, buildIconListener());
-			setImage(imageHolder.getValue());
-		}
-	}
-
-	private void setImage(Image icon) {
-		labeledControl.setImage(icon);
+	private void setImage(Image image) {
+		this.labeledControl.setImage(image);
 	}
 
 	private void setText(String text) {
-
 		if (text == null) {
 			text = "";
 		}
 
-		labeledControl.setText(text);
+		this.labeledControl.setText(text);
+	}
+
+	// ********** dispose **********
+
+	private void controlDisposed(@SuppressWarnings("unused") DisposeEvent event) {
+		// the control is not yet "disposed" when we receive this event
+		// so we can still remove our listeners
+		this.labeledControl.removeDisposeListener(this.disposeListener);
+
+		if (this.imageModel != null) {
+			this.imageModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.imageListener);
+		}
+
+		if (this.textModel != null) {
+			this.textModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.textListener);
+		}
+	}
+
+	private DisposeListener buildDisposeListener() {
+		return new DisposeListener() {
+			public void widgetDisposed(DisposeEvent event) {
+				LabeledControlUpdater.this.controlDisposed(event);
+			}
+		    @Override
+			public String toString() {
+				return "LabeledControlUpdater.disposeListener";
+			}
+		};
 	}
 }
\ No newline at end of file
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledLabel.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledLabel.java
index c74ef06..32a7d01 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledLabel.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledLabel.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2008 Oracle. All rights reserved. This
+ *  Copyright (c) 2008, 2012 Oracle. 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
@@ -9,6 +9,7 @@
 package org.eclipse.jpt.common.ui.internal.util;
 
 import org.eclipse.core.runtime.Assert;
+import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.widgets.Label;
 
@@ -16,7 +17,7 @@
  * A default implementation of <code>LabeledControl</code> that updates an
  * <code>Label</code> when required.
  *
- * @version 2.0
+ * @version 3.3
  * @since 2.0
  */
 @SuppressWarnings("nls")
@@ -42,6 +43,14 @@
 		this.label = label;
 	}
 
+	public void addDisposeListener(DisposeListener disposeListener) {
+		this.label.addDisposeListener(disposeListener);
+	}
+
+	public void removeDisposeListener(DisposeListener disposeListener) {
+		this.label.removeDisposeListener(disposeListener);
+	}
+
 	/*
 	 * (non-Javadoc)
 	 */
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/AddRemovePane.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/AddRemovePane.java
index 36fcbc3..a46cf7e 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/AddRemovePane.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/AddRemovePane.java
@@ -48,10 +48,11 @@
 	private Adapter<E> adapter;
 	private Button addButton;
 	private IBaseLabelProvider labelProvider;
-	private ListValueModel<?> listHolder;
+	private ListValueModel<?> listModel;
 	private Button optionalButton;
 	private Button removeButton;
 	private ModifiableCollectionValueModel<E> selectedItemsModel;
+	private ListChangeListener listChangeListener;
 
 	/**
 	 * Creates a new <code>AddRemovePane</code>.
@@ -61,21 +62,21 @@
 	 * @param adapter This <code>Adapter</code> is used to dictate the behavior
 	 * of this <code>AddRemovePane</code> and by delegating to it some of the
 	 * behavior
-	 * @param listHolder The <code>ListValueModel</code> containing the items
+	 * @param listModel The <code>ListValueModel</code> containing the items
 	 * @param selectedItemsModel The holder of the selected items
 	 * @param labelProvider The renderer used to format the list holder's items
 	 */
 	protected AddRemovePane(Pane<? extends T> parentPane,
 	                        Composite parent,
 	                        Adapter<E> adapter,
-	                        ListValueModel<?> listHolder,
+	                        ListValueModel<?> listModel,
 	                        ModifiableCollectionValueModel<E> selectedItemsModel,
 	                        IBaseLabelProvider labelProvider) {
 
 		this(parentPane,
 		     parent,
 		     adapter,
-		     listHolder,
+		     listModel,
 		     selectedItemsModel,
 		     labelProvider,
 		     null);
@@ -86,10 +87,10 @@
 	 *
 	 * @param parentPane The parent container of this one
 	 * @param parent The parent container
-	 * @param adapter This <code>Adapter</code> is used to dictacte the behavior
+	 * @param adapter This <code>Adapter</code> is used to dictate the behavior
 	 * of this <code>AddRemovePane</code> and by delegating to it some of the
 	 * behavior
-	 * @param listHolder The <code>ListValueModel</code> containing the items
+	 * @param listModel The <code>ListValueModel</code> containing the items
 	 * @param selectedItemsModel The holder of the selected items
 	 * @param labelProvider The renderer used to format the list holder's items
 	 * @param helpId The topic help ID to be registered with this pane
@@ -99,7 +100,7 @@
 	protected AddRemovePane(Pane<? extends T> parentPane,
 	                        Composite parent,
 	                        Adapter<E> adapter,
-	                        ListValueModel<?> listHolder,
+	                        ListValueModel<?> listModel,
 	                        ModifiableCollectionValueModel<E> selectedItemsModel,
 	                        IBaseLabelProvider labelProvider,
 	                        String helpId) {
@@ -108,14 +109,14 @@
 
 		initialize(
 			adapter,
-			listHolder,
+			listModel,
 			selectedItemsModel,
 			labelProvider
 		);
 
 		initializeLayout(
 			adapter,
-			listHolder,
+			listModel,
 			selectedItemsModel,
 			labelProvider,
 			helpId
@@ -125,7 +126,7 @@
 	protected AddRemovePane(Pane<? extends T> parentPane,
         Composite parent,
         Adapter<E> adapter,
-        ListValueModel<?> listHolder,
+        ListValueModel<?> listModel,
         ModifiableCollectionValueModel<E> selectedItemsModel,
         IBaseLabelProvider labelProvider,
         PropertyValueModel<Boolean> enabledModel,
@@ -135,14 +136,14 @@
 
 		initialize(
 			adapter,
-			listHolder,
+			listModel,
 			selectedItemsModel,
 			labelProvider
 		);
 		
 		initializeLayout(
 			adapter,
-			listHolder,
+			listModel,
 			selectedItemsModel,
 			labelProvider,
 			helpId
@@ -158,7 +159,7 @@
 	 * of this <code>AddRemovePane</code> and by delegating to it some of the
 	 * behavior
 	 * @param parent The parent container
-	 * @param listHolder The <code>ListValueModel</code> containing the items
+	 * @param listModel The <code>ListValueModel</code> containing the items
 	 * @param selectedItemsModel The holder of the selected item
 	 * @param labelProvider The renderer used to format the list holder's items
 	 */
@@ -166,7 +167,7 @@
 	                        PropertyValueModel<? extends T> subjectHolder,
 	                        Composite parent,
 	                        Adapter<E> adapter,
-	                        ListValueModel<?> listHolder,
+	                        ListValueModel<?> listModel,
 	                        ModifiableCollectionValueModel<E> selectedItemsModel,
 	                        IBaseLabelProvider labelProvider) {
 
@@ -174,7 +175,7 @@
 		     subjectHolder,
 		     parent,
 		     adapter,
-		     listHolder,
+		     listModel,
 		     selectedItemsModel,
 		     labelProvider,
 		     null);
@@ -189,7 +190,7 @@
 	 * of this <code>AddRemovePane</code> and by delegating to it some of the
 	 * behavior
 	 * @param parent The parent container
-	 * @param listHolder The <code>ListValueModel</code> containing the items
+	 * @param listModel The <code>ListValueModel</code> containing the items
 	 * @param selectedItemsModel The holder of the selected item
 	 * @param labelProvider The renderer used to format the list holder's items
 	 * @param helpId The topic help ID to be registered with this pane
@@ -198,7 +199,7 @@
 	                        PropertyValueModel<? extends T> subjectHolder,
 	                        Composite parent,
 	                        Adapter<E> adapter,
-	                        ListValueModel<?> listHolder,
+	                        ListValueModel<?> listModel,
 	                        ModifiableCollectionValueModel<E> selectedItemsModel,
 	                        IBaseLabelProvider labelProvider,
 	                        String helpId) {
@@ -207,14 +208,14 @@
 
 		initialize(
 			adapter,
-			listHolder,
+			listModel,
 			selectedItemsModel,
 			labelProvider
 		);
 
 		initializeLayout(
 			adapter,
-			listHolder,
+			listModel,
 			selectedItemsModel,
 			labelProvider,
 			helpId
@@ -412,8 +413,8 @@
 		return this.labelProvider;
 	}
 
-	protected final ListValueModel<?> getListHolder() {
-		return this.listHolder;
+	protected final ListValueModel<?> getListModel() {
+		return this.listModel;
 	}
 
 	/**
@@ -441,18 +442,19 @@
 	 * @category Initialization
 	 */
 	protected void initialize(Adapter<E> adapter,
-	                          ListValueModel<?> listHolder,
+	                          ListValueModel<?> listModel,
 	                          ModifiableCollectionValueModel<E> selectedItemsModel,
 	                          IBaseLabelProvider labelProvider)
 	{
-		this.listHolder         = listHolder;
+		this.listModel          = listModel;
 		this.labelProvider      = labelProvider;
 		this.adapter            = (adapter == null) ? buildAdapter() : adapter;
 		this.selectedItemsModel = selectedItemsModel;
 
-		this.listHolder.addListChangeListener(
+		this.listChangeListener = this.buildListChangeListener();
+		this.listModel.addListChangeListener(
 			ListValueModel.LIST_VALUES,
-			buildListChangeListener()
+			this.listChangeListener
 		);
 	}
 
@@ -516,7 +518,7 @@
 	 * @category Layout
 	 */
 	protected void initializeLayout(Adapter<E> adapter,
-    	                             ListValueModel<?> listHolder,
+    	                             ListValueModel<?> listModel,
    	                             ModifiableCollectionValueModel<E> selectedItemsModel,
    	                             IBaseLabelProvider labelProvider,
    	                             String helpId) {
@@ -524,7 +526,7 @@
 		initializeMainComposite(
 			(Composite) getControl(),
 			adapter,
-			listHolder,
+			listModel,
 			selectedItemsModel,
 			labelProvider,
 			helpId);
@@ -585,6 +587,14 @@
 	}
 
 
+	@Override
+	protected void controlDisposed() {
+		this.listModel.removeListChangeListener(
+			ListValueModel.LIST_VALUES,
+			this.listChangeListener
+		);
+		super.controlDisposed();
+	}
 	/**
 	 * This adapter is used to perform the actual action when adding a new item
 	 * or removing the selected items. It is possible to add an optional button.
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/ClassChooserPane.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/ClassChooserPane.java
index f4e257e..0dd976c 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/ClassChooserPane.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/ClassChooserPane.java
@@ -432,8 +432,8 @@
 	}
 
 	@Override
-	public void dispose() {
+	public void controlDisposed() {
 		this.getSubjectHolder().removePropertyChangeListener(PropertyValueModel.VALUE, this.subjectChangeListener);
-		super.dispose();
+		super.controlDisposed();
 	}
 }
\ No newline at end of file
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Dialog.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Dialog.java
index f346bef..cef31c6 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Dialog.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Dialog.java
@@ -34,7 +34,7 @@
  * @see Node
  * @see DialogPane
  *
- * @version 2.0
+ * @version 3.3
  * @since 2.0
  */
 @SuppressWarnings("nls")
@@ -108,22 +108,6 @@
 		return Node.NULL_VALIDATOR;
 	}
 
-	/*
-	 * (non-Javadoc)
-	 */
-	@Override
-	public boolean close() {
-
-		// Dispose the pane in order to remove any listeners that could
-		// have been installed outside the scrope of the state object
-		if (pane != null) {
-			pane.dispose();
-			pane = null;
-		}
-
-		return super.close();
-	}
-
 	/**
 	 * {@inheritDoc}
 	 */
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/PackageChooserPane.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/PackageChooserPane.java
index 42d2433..63d0807 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/PackageChooserPane.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/PackageChooserPane.java
@@ -232,8 +232,8 @@
 	}
 
 	@Override
-	public void dispose() {
+	public void controlDisposed() {
 		this.getSubjectHolder().removePropertyChangeListener(PropertyValueModel.VALUE, this.subjectChangeListener);
-		super.dispose();
+		super.controlDisposed();
 	}
 }
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Pane.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Pane.java
index fcd3e56..8f2dc5b 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Pane.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Pane.java
@@ -14,7 +14,6 @@
 import org.eclipse.core.runtime.Assert;
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
-import org.eclipse.jface.resource.StringConverter;
 import org.eclipse.jface.viewers.ComboViewer;
 import org.eclipse.jface.viewers.IBaseLabelProvider;
 import org.eclipse.jpt.common.ui.WidgetFactory;
@@ -40,6 +39,8 @@
 import org.eclipse.jpt.common.utility.model.value.PropertyValueModel;
 import org.eclipse.jpt.common.utility.transformer.Transformer;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.events.MouseAdapter;
 import org.eclipse.swt.events.MouseEvent;
 import org.eclipse.swt.events.SelectionAdapter;
@@ -135,6 +136,12 @@
 	private PropertyValueModel<Boolean> enabledModel;
 
 	/**
+	 * A listener that allows us to stop listening to stuff when the control
+	 * is disposed. (Critical for preventing memory leaks.)
+	 */
+	private final DisposeListener controlDisposeListener;
+
+	/**
 	 * Creates a new <code>Pane</code>.
 	 *
 	 * @param parentPane The parent container of this one
@@ -209,6 +216,8 @@
 			this.container = null;
 			this.initializeLayout(parent);
 		}
+		this.controlDisposeListener = this.buildControlDisposeListener();
+		this.getControl().addDisposeListener(this.controlDisposeListener);
 		this.engageSubjectHolder();
 		this.engageListeners(getSubject());
 		this.populate();
@@ -247,6 +256,8 @@
 			this.container = null;
 			this.initializeLayout(parent);
 		}
+		this.controlDisposeListener = this.buildControlDisposeListener();
+		this.getControl().addDisposeListener(this.controlDisposeListener);
 		this.engageSubjectHolder();
 		this.engageListeners(getSubject());
 		this.populate();
@@ -276,6 +287,8 @@
 			this.container = null;
 			this.initializeLayout(parent);
 		}
+		this.controlDisposeListener = this.buildControlDisposeListener();
+		this.getControl().addDisposeListener(this.controlDisposeListener);
 		this.engageSubjectHolder();
 		this.engageListeners(getSubject());
 		this.populate();
@@ -297,6 +310,8 @@
 			this.container = null;
 			this.initializeLayout(parent);
 		}
+		this.controlDisposeListener = this.buildControlDisposeListener();
+		this.getControl().addDisposeListener(this.controlDisposeListener);
 		this.engageSubjectHolder();
 		this.engageListeners(getSubject());
 		this.populate();
@@ -364,6 +379,19 @@
 	 */
 	protected abstract void initializeLayout(Composite container);
 
+	private DisposeListener buildControlDisposeListener() {
+		return new DisposeListener() {
+			public void widgetDisposed(DisposeEvent event) {
+				Pane.this.controlDisposed();
+			}
+		    @Override
+			public String toString() {
+				return "control dispose listener";
+			}
+		};
+	}
+
+
 	/**
 	 * Adds any property names to the given collection in order to be notified
 	 * when the actual property changes in the subject.
@@ -1532,7 +1560,6 @@
 	 * Creates a new <code>Text</code> widget.
 	 *
 	 * @param container The parent container
-	 * @param textHolder The holder of the text field's input
 	 * @return The newly created <code>Text</code> widget
 	 *
 	 * @category Layout
@@ -2664,17 +2691,16 @@
 		}
 	}
 
-	public void dispose() {
+	protected void controlDisposed() {
+		// the control is not yet "disposed" when we receive this event
+		// so we can still remove our listeners
 		JptCommonUiPlugin.instance().trace(TRACE_OPTION, "dispose");
 
 		// Dispose this pane
 		this.disengageListeners(getSubject());
 		this.disengageSubjectHolder();
 
-		// Ask the sub-panes to dispose themselves
-		for (Pane<?> subPane : this.subPanes) {
-			subPane.dispose();
-		}
+		this.getControl().removeDisposeListener(this.controlDisposeListener);
 	}
 
 	private static final String TRACE_OPTION = Pane.class.getSimpleName();
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/TriStateCheckBox.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/TriStateCheckBox.java
index 7253570..1f9a80b 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/TriStateCheckBox.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/TriStateCheckBox.java
@@ -112,13 +112,6 @@
 	}
 
 	/**
-	 * Disposes the check box widget.
-	 */
-	public void dispose() {
-		this.button.dispose();
-	}
-
-	/**
 	 * Returns the <code>Button</code> used to show a tri-state check box.
 	 *
 	 * @return The <code>Button</code> used to show a tri-state check box
diff --git a/common/tests/org.eclipse.jpt.common.ui.tests/src/org/eclipse/jpt/common/ui/tests/internal/util/PaneVisibilityEnablerTest.java b/common/tests/org.eclipse.jpt.common.ui.tests/src/org/eclipse/jpt/common/ui/tests/internal/util/PaneVisibilityEnablerTest.java
index c72ddbf..8c98491 100644
--- a/common/tests/org.eclipse.jpt.common.ui.tests/src/org/eclipse/jpt/common/ui/tests/internal/util/PaneVisibilityEnablerTest.java
+++ b/common/tests/org.eclipse.jpt.common.ui.tests/src/org/eclipse/jpt/common/ui/tests/internal/util/PaneVisibilityEnablerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2009 Oracle. All rights reserved.
+ * Copyright (c) 2008, 2012 Oracle. 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.
@@ -87,7 +87,6 @@
 		);
 
 		// Dispose
-		pane.dispose();
 		booleanHolder.setValue(true);
 	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/details/JpaComposite.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/details/JpaComposite.java
index d0da397..b060ce9 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/details/JpaComposite.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/details/JpaComposite.java
@@ -29,9 +29,4 @@
 	 * @return This composite's actual widget
 	 */
 	Control getControl();
-
-	/**
-	 * Notifies this composite it should dispose any resources.
-	 */
-	void dispose();
 }
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/details/JpaDetailsPageManager.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/details/JpaDetailsPageManager.java
index 131c54f..e0537e4 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/details/JpaDetailsPageManager.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/details/JpaDetailsPageManager.java
@@ -26,7 +26,7 @@
  * 
  * @param <T> the type of the details page manager's model
  * 
- * @version 2.0
+ * @version 3.3
  * @since 2.0
  * @see JpaDetailsProvider
  */
@@ -47,11 +47,6 @@
 	 */
 	void setSubject(Object subject);
 
-	/**
-	 * Dispose the details page manager and any resources it holds.
-	 */
-	void dispose();
-
 	interface Factory {
 		<T extends JpaStructureNode> JpaDetailsPageManager<T> buildPageManager(Composite parent, WidgetFactory widgetFactory);
 	}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/MapAsComposite.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/MapAsComposite.java
index 6d70d29..2ef26cf 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/MapAsComposite.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/MapAsComposite.java
@@ -403,10 +403,9 @@
 	}
 
 	@Override
-	public void dispose() {
-		this.styledText.dispose();
+	protected void controlDisposed() {
 		this.getEnabledModel().removePropertyChangeListener(PropertyValueModel.VALUE, this.enabledModelListener);
-		super.dispose();
+		super.controlDisposed();
 	}
 
 	/**
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentAttributeDetailsPage.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentAttributeDetailsPage.java
index 16cde21..b5e1340 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentAttributeDetailsPage.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentAttributeDetailsPage.java
@@ -147,14 +147,11 @@
 	}
 
 	@Override
-	public void dispose() {
+	public void controlDisposed() {
 		JptJpaUiPlugin.instance().trace(TRACE_OPTION, "dispose"); //$NON-NLS-1$
 
-		for (JpaComposite mappingComposite : this.mappingComposites.values()) {
-			mappingComposite.dispose();
-		}
 		this.mappingComposites.clear();
-		super.dispose();
+		super.controlDisposed();
 	}
 
 	private static final String TRACE_OPTION = PersistentAttributeDetailsPage.class.getSimpleName();
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentTypeDetailsPage.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentTypeDetailsPage.java
index c7c44bb..088c69d 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentTypeDetailsPage.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentTypeDetailsPage.java
@@ -37,7 +37,6 @@
  * @version 2.2
  * @since 1.0
  */
-@SuppressWarnings("nls")
 public class PersistentTypeDetailsPage extends AbstractJpaDetailsPage<PersistentType>
 {
 	private Map<String, JpaComposite> mappingComposites;
@@ -151,14 +150,11 @@
 	}
 
 	@Override
-	public void dispose() {
+	public void controlDisposed() {
 		JptJpaUiPlugin.instance().trace(TRACE_OPTION, "dispose"); //$NON-NLS-1$
 
-		for (JpaComposite mappingComposite : this.mappingComposites.values()) {
-			mappingComposite.dispose();
-		}
 		this.mappingComposites.clear();
-		super.dispose();
+		super.controlDisposed();
 	}
 
 	private static final String TRACE_OPTION = PersistentTypeDetailsPage.class.getSimpleName();
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/editors/PersistenceEditor.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/editors/PersistenceEditor.java
index 30bc885..4081c09 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/editors/PersistenceEditor.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/editors/PersistenceEditor.java
@@ -347,7 +347,6 @@
 
 		@Override
 		public void dispose() {
-			this.page.dispose();
 			if (this.imageDescriptor != null) {
 				PersistenceEditor.this.resourceManager.destroyImage(this.imageDescriptor);
 			}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/views/JpaDetailsView.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/views/JpaDetailsView.java
index cf9414d..fc375f9 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/views/JpaDetailsView.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/views/JpaDetailsView.java
@@ -259,9 +259,6 @@
 			this.currentPageManager.setSubject(null);
 			this.currentPageManager = null;
 		}
-		for (JpaDetailsPageManager<? extends JpaStructureNode> detailsPage : this.pageManagers.values()) {
-			detailsPage.dispose();
-		}
 		this.pageManagers.clear();
 	}