bug 419415 fix layout problems
diff --git a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/swt/ControlCreator.java b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/swt/ControlCreator.java
index b39c60f..16a40b1 100644
--- a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/swt/ControlCreator.java
+++ b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/swt/ControlCreator.java
@@ -21,8 +21,11 @@
Set<T> controls = new HashSet<T>();
- protected ControlCreator(UpdatingComposite parent) {
+ private Class<T> classOfControls;
+
+ protected ControlCreator(UpdatingComposite parent, Class<T> classOfControls) {
this.parent = parent;
+ this.classOfControls = classOfControls;
}
/**
@@ -75,6 +78,6 @@
return eachControl;
}
}
- throw new RuntimeException("Control not in managed list"); //$NON-NLS-1$
+ return classOfControls.cast(control);
}
}
diff --git a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/swt/UpdatingComposite.java b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/swt/UpdatingComposite.java
index 57a316d..d7fd0b9 100644
--- a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/swt/UpdatingComposite.java
+++ b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/swt/UpdatingComposite.java
@@ -22,7 +22,7 @@
* 419415 so it can be decided what to promote to general API.
* <P>
* A composite that automatically tracks and registers listeners on its
- * dsependencies as long as all of its dependencies are {@link IObservable}
+ * dependencies as long as all of its dependencies are {@link IObservable}
* objects. The tracking is done while the child controls for this composite are
* being created. So when any of the dependencies change, the child controls are
* re-created.
@@ -50,6 +50,15 @@
* ControlCreator companyNameControlCreator = new CompanyNameControlCreator(this);
* ControlCreator genderComboCreator = new GenderComboCreator(this);
*
+ * MyComposite(Composite parent, int style) {
+ * super(parent, style);
+ *
+ * // IMPORTANT: Constructors must always call this. The constructor in the super class
+ * // cannot do this for you because trackControls calls createControls which may use fields in this class
+ * // that will not have been initialized when the super constructor is called.
+ * trackControls();
+ * }
+ *
* @Override
* protected void createControls() {
* Label label1 = labelCreator.create();
@@ -128,7 +137,8 @@
private IObservable[] dependencies = null;
/**
- * Set to a non-null list only while controls are being re-built.
+ * Set to a non-null list only while controls are being re-built, this being
+ * the list of controls available for re-use and must be in order
*/
List<Control> remainder = null;
@@ -197,8 +207,6 @@
for (Control control : remainder) {
remove(control);
}
-
- layout(true);
}
}
@@ -210,15 +218,6 @@
public UpdatingComposite(Composite parent, int style) {
super(parent, style);
- /*
- * We must wait until after the derived class fields have been
- * initialized before attempting to create the child controls.
- */
- // Display.getCurrent().asyncExec(new Runnable() {
- // public void run() {
- trackControls();
- // }
- // });
addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
@@ -249,7 +248,21 @@
return;
}
- trackControls();
+ createAndTrackControls();
+
+ /*
+ * Having added and removed controls, this composite now
+ * needs to be laid out. The children are okay because they
+ * should be laid out when they are created or re-used, so
+ * passing <code>false</code> is fine.
+ */
+ layout(false);
+
+ /*
+ * Assume that the preferred size has changed. Parent
+ * composites may need to re-layout their controls whenever
+ * the size of this control changes.
+ */
computeSizeObservable.fireChange();
}
});
@@ -259,12 +272,12 @@
/**
* This line will do the following:
* <UL>
- * <LI>Run the calculate method</LI>
+ * <LI>Run the <code>createControls</code> method</LI>
* <LI>While doing so, add any observable that is touched to the
* dependencies list</LI>
* </UL>
*/
- protected void trackControls() {
+ protected void createAndTrackControls() {
IObservable[] newDependencies = ObservableTracker.runAndMonitor(
privateRunnableInterface, privateChangeInterface, null);
@@ -305,37 +318,51 @@
}
}
+ /**
+ * This method is called while getters are being tracked. However we want to
+ * track only getters on observables that were used to determine which
+ * controls are created and setting properties on those controls outside of
+ * the control creator. We really don't want to track getters that are used
+ * while creating the control. For example it may be that
+ *
+ * @param controlCreator
+ * @return the control, which may be either re-used or just created by the
+ * control creator
+ */
<T extends Control> T create(ControlCreator<T> controlCreator) {
-
- T matchingControl = null;
- for (Control control : remainder) {
- if (controlCreator.equals(control.getData(key))) {
- matchingControl = controlCreator.typeControl(control);
- break;
+ ObservableTracker.setIgnore(true);
+ try {
+ T matchingControl = null;
+ for (Control control : remainder) {
+ if (controlCreator.equals(control.getData(key))) {
+ matchingControl = controlCreator.typeControl(control);
+ break;
+ }
}
+
+ if (matchingControl != null) {
+ /*
+ * Move this control to be before any other remaining controls.
+ */
+ if (matchingControl != remainder.get(0)) {
+ matchingControl.moveAbove(remainder.get(0));
+ }
+ remainder.remove(matchingControl);
+ } else {
+ matchingControl = controlCreator.createControl();
+ matchingControl.setData(key, controlCreator);
+ controlCreator.controls.add(matchingControl);
+ /*
+ * Move this control to be before any other remaining controls.
+ */
+ if (!remainder.isEmpty()) {
+ matchingControl.moveAbove(remainder.get(0));
+ }
+ }
+ return matchingControl;
+ } finally {
+ ObservableTracker.setIgnore(false);
}
-
- if (matchingControl != null) {
- /*
- * Move this control to be before any other remaining controls.
- */
- if (matchingControl != remainder.get(0)) {
- matchingControl.moveBelow(remainder.get(0));
- }
- remainder.remove(matchingControl);
- } else {
- matchingControl = controlCreator.createControl();
- matchingControl.setData(key, controlCreator);
- controlCreator.controls.add(matchingControl);
- /*
- * Move this control to be before any other remaining controls.
- */
- if (!remainder.isEmpty()) {
- matchingControl.moveBelow(remainder.get(0));
- }
- }
-
- return matchingControl;
}
/**