- Changed Requires/ProvidesLayout => Requires/ProvidesResize; some small doc
additions.
- Added RequiresLayout; moved doc into it.
- Added LayoutPanelExample.
- Added DockLayoutPanel.
- A bit of cleanup here and there.
Review: http://gwt-code-reviews.appspot.com/63801
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@6080 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/javadoc/com/google/gwt/examples/DockLayoutPanelExample.java b/user/javadoc/com/google/gwt/examples/DockLayoutPanelExample.java
new file mode 100644
index 0000000..31fa1ad
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/DockLayoutPanelExample.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.examples;
+
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.user.client.ui.DockLayoutPanel;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.RootLayoutPanel;
+import com.google.gwt.user.client.ui.DockLayoutPanel.Direction;
+
+public class DockLayoutPanelExample implements EntryPoint {
+
+ public void onModuleLoad() {
+ // Attach five widgets to a DockLayoutPanel, one in each direction. Lay
+ // them out in 'em' units.
+ DockLayoutPanel p = new DockLayoutPanel(Unit.EM);
+ p.add(new HTML("north"), Direction.NORTH, 2);
+ p.add(new HTML("south"), Direction.SOUTH, 2);
+ p.add(new HTML("east"), Direction.EAST, 2);
+ p.add(new HTML("west"), Direction.WEST, 2);
+ p.add(new HTML("center"), Direction.CENTER, 2);
+
+ // Note the explicit call to layout(). This is required for the layout to
+ // take effect.
+ p.layout();
+
+ // Attach the LayoutPanel to the RootLayoutPanel. The latter will listen for
+ // resize events on the window to ensure that its children are informed of
+ // possible size changes.
+ RootLayoutPanel rp = RootLayoutPanel.get();
+ rp.add(p);
+
+ // The RootLayoutPanel also requires that its layout() method be explicitly
+ // called for the initial layout to take effect.
+ rp.layout();
+ }
+}
diff --git a/user/javadoc/com/google/gwt/examples/LayoutExample.java b/user/javadoc/com/google/gwt/examples/LayoutExample.java
new file mode 100644
index 0000000..6f5fa86
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/LayoutExample.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.examples;
+
+import static com.google.gwt.dom.client.Style.Unit.EM;
+import static com.google.gwt.dom.client.Style.Unit.PCT;
+import static com.google.gwt.dom.client.Style.Unit.PX;
+
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.layout.client.Layout;
+import com.google.gwt.layout.client.Layout.Layer;
+
+public class LayoutExample implements EntryPoint {
+
+ public void onModuleLoad() {
+ // The following is a very simple example, which constructs a layout around
+ // a parent element, and attaches two child elements that split their
+ // parent's space vertically. It then goes on to animate from the first
+ // state to a horizontal stacking that uses EM units rather than
+ // percentages.
+ Document doc = Document.get();
+ Element parent = doc.createDivElement();
+ doc.getBody().appendChild(parent);
+
+ Layout layout = new Layout(parent);
+ layout.onAttach();
+
+ Element topChild = doc.createDivElement(), bottomChild = doc
+ .createDivElement();
+ Layer topLayer = layout.attachChild(topChild);
+ Layer bottomLayer = layout.attachChild(bottomChild);
+
+ // Stack the two children vertically, meeting at 50%.
+ topLayer.setLeftRight(0, PX, 0, PX);
+ bottomLayer.setLeftRight(0, PX, 0, PX);
+ topLayer.setTopHeight(0, PCT, 50, PCT);
+ bottomLayer.setBottomHeight(0, PCT, 50, PCT);
+ layout.layout();
+
+ // Update the two children to stack horizontally, meeting at 10em.
+ // Also have them animate for 500ms.
+ topLayer.setTopBottom(0, PX, 0, PX);
+ bottomLayer.setTopBottom(0, PX, 0, PX);
+ topLayer.setLeftWidth(0, EM, 10, EM);
+ bottomLayer.setLeftRight(10, EM, 0, EM);
+ layout.layout(500);
+ }
+}
diff --git a/user/javadoc/com/google/gwt/examples/LayoutPanelExample.java b/user/javadoc/com/google/gwt/examples/LayoutPanelExample.java
index f1300f9..3fc43d1 100644
--- a/user/javadoc/com/google/gwt/examples/LayoutPanelExample.java
+++ b/user/javadoc/com/google/gwt/examples/LayoutPanelExample.java
@@ -52,4 +52,4 @@
// called for the initial layout to take effect.
rp.layout();
}
-}
\ No newline at end of file
+}
diff --git a/user/src/com/google/gwt/layout/client/Layout.java b/user/src/com/google/gwt/layout/client/Layout.java
index 032f571..a4efe5e 100644
--- a/user/src/com/google/gwt/layout/client/Layout.java
+++ b/user/src/com/google/gwt/layout/client/Layout.java
@@ -328,11 +328,46 @@
* </p>
*
* @param child the child to be attached
+ * @param before the child element before which to insert
+ * @return the {@link Layer} associated with the element
+ */
+ public Layer attachChild(Element child, Element before) {
+ return attachChild(child, before, null);
+ }
+
+ /**
+ * Attaches a child element to this layout.
+ *
+ * <p>
+ * This method will attach the child to the layout, removing it from its
+ * current parent element. Use the {@link Layer} it returns to manipulate the
+ * child.
+ * </p>
+ *
+ * @param child the child to be attached
* @param userObject an arbitrary object to be associated with this layer
* @return the {@link Layer} associated with the element
*/
public Layer attachChild(Element child, Object userObject) {
- Element container = impl.attachChild(parentElem, child);
+ return attachChild(child, null, userObject);
+ }
+
+ /**
+ * Attaches a child element to this layout.
+ *
+ * <p>
+ * This method will attach the child to the layout, removing it from its
+ * current parent element. Use the {@link Layer} it returns to manipulate the
+ * child.
+ * </p>
+ *
+ * @param child the child to be attached
+ * @param before the child element before which to insert
+ * @param userObject an arbitrary object to be associated with this layer
+ * @return the {@link Layer} associated with the element
+ */
+ public Layer attachChild(Element child, Element before, Object userObject) {
+ Element container = impl.attachChild(parentElem, child, before);
Layer layer = new Layer(container, child, userObject);
layers.add(layer);
return layer;
diff --git a/user/src/com/google/gwt/layout/client/LayoutImpl.java b/user/src/com/google/gwt/layout/client/LayoutImpl.java
index 9eccd0d..cf423fa 100644
--- a/user/src/com/google/gwt/layout/client/LayoutImpl.java
+++ b/user/src/com/google/gwt/layout/client/LayoutImpl.java
@@ -24,6 +24,7 @@
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.layout.client.Layout.Layer;
@@ -60,20 +61,21 @@
protected DivElement relativeRuler;
- public Element attachChild(Element parent, Element child) {
+ public Element attachChild(Element parent, Element child, Element before) {
DivElement container = Document.get().createDivElement();
container.appendChild(child);
- container.getStyle().setProperty("position", "absolute");
- container.getStyle().setProperty("overflow", "hidden");
+ container.getStyle().setPosition(Position.ABSOLUTE);
+ container.getStyle().setOverflow(Overflow.HIDDEN);
fillParent(child);
- Style style = child.getStyle();
- style.setWidth(100, Unit.PCT);
- style.setHeight(100, Unit.PCT);
-
- parent.appendChild(container);
+ Element beforeContainer = null;
+ if (before != null) {
+ beforeContainer = before.getParentElement();
+ assert beforeContainer.getParentElement() == parent : "Element to insert before must be a sibling";
+ }
+ parent.insertBefore(container, beforeContainer);
return container;
}
@@ -118,7 +120,7 @@
}
public void initParent(Element parent) {
- parent.getStyle().setProperty("position", "relative");
+ parent.getStyle().setPosition(Position.RELATIVE);
parent.appendChild(relativeRuler = createRuler(EM, EX));
}
diff --git a/user/src/com/google/gwt/layout/client/LayoutImplIE6.java b/user/src/com/google/gwt/layout/client/LayoutImplIE6.java
index d5e3c5d..4a9be19 100644
--- a/user/src/com/google/gwt/layout/client/LayoutImplIE6.java
+++ b/user/src/com/google/gwt/layout/client/LayoutImplIE6.java
@@ -38,6 +38,30 @@
*/
class LayoutImplIE6 extends LayoutImpl {
+ private static boolean isIE6 = isIE6();
+
+ // Stolen and modified from UserAgent.gwt.xml.
+ // TODO(jgw): Get rid of this method, and switch to using soft permutations
+ // once they land in trunk.
+ private static native boolean isIE6() /*-{
+ function makeVersion(result) {
+ return (parseInt(result[1]) * 1000) + parseInt(result[2]);
+ }
+
+ var ua = navigator.userAgent.toLowerCase();
+ if (ua.indexOf("msie") != -1) {
+ var result = /msie ([0-9]+)\.([0-9]+)/.exec(ua);
+ if (result && result.length == 3) {
+ var v = makeVersion(result);
+ if (v < 7000) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }-*/;
+
private static Element createStyleRuler(Element parent) {
DivElement styleRuler = Document.get().createDivElement();
DivElement styleInner = Document.get().createDivElement();
@@ -111,13 +135,14 @@
elem[name] = value;
}-*/;
- public Element attachChild(Element parent, Element child) {
- if (!UserAgent.isIE6()) {
- return super.attachChild(parent, child);
+ @Override
+ public Element attachChild(Element parent, Element child, Element before) {
+ if (!isIE6) {
+ return super.attachChild(parent, child, before);
}
DivElement container = Document.get().createDivElement();
- container.appendChild(child);
+ container.insertBefore(child, before);
container.getStyle().setPosition(Position.ABSOLUTE);
container.getStyle().setOverflow(Overflow.HIDDEN);
@@ -127,13 +152,18 @@
// the child element, so that measureDecoration(child) will work.
setPropertyElement(child, "__styleRuler", createStyleRuler(container));
- parent.appendChild(container);
+ Element beforeContainer = null;
+ if (before != null) {
+ beforeContainer = before.getParentElement();
+ assert beforeContainer.getParentElement() == parent : "Element to insert before must be a sibling";
+ }
+ parent.insertBefore(container, beforeContainer);
return container;
}
@Override
public void fillParent(Element elem) {
- if (!UserAgent.isIE6()) {
+ if (!isIE6) {
super.fillParent(elem);
return;
}
@@ -143,7 +173,7 @@
@Override
public void finalizeLayout(Element parent) {
- if (!UserAgent.isIE6()) {
+ if (!isIE6) {
super.finalizeLayout(parent);
return;
}
@@ -156,13 +186,13 @@
public void initParent(Element parent) {
super.initParent(parent);
- if (UserAgent.isIE6()) {
+ if (isIE6) {
setPropertyElement(parent, "__styleRuler", createStyleRuler(parent));
}
}
public void layout(Layer layer) {
- if (!UserAgent.isIE6()) {
+ if (!isIE6) {
super.layout(layer);
return;
}
@@ -173,7 +203,7 @@
@Override
public void onAttach(Element parent) {
- if (UserAgent.isIE6()) {
+ if (isIE6) {
// No need to re-connect layer refs. This will be taken care of
// automatically in layout().
initResizeHandler(parent);
@@ -183,7 +213,7 @@
@Override
public void onDetach(Element parent) {
- if (UserAgent.isIE6()) {
+ if (isIE6) {
removeLayerRefs(parent);
removeResizeHandler(parent);
removeUnitChangeHandler(relativeRuler);
diff --git a/user/src/com/google/gwt/layout/client/UserAgent.java b/user/src/com/google/gwt/layout/client/UserAgent.java
deleted file mode 100644
index 2127a59..0000000
--- a/user/src/com/google/gwt/layout/client/UserAgent.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2009 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.layout.client;
-
-/**
- * User-Agent utility methods used by {@link LayoutImplIE6}.
- *
- * TODO: Generalize this, move it into a common place, and make it available for
- * use by other classes.
- */
-class UserAgent {
-
- // Stolen and modified from UserAgent.gwt.xml.
- public static native boolean isIE6() /*-{
- function makeVersion(result) {
- return (parseInt(result[1]) * 1000) + parseInt(result[2]);
- }
-
- var ua = navigator.userAgent.toLowerCase();
- if (ua.indexOf("msie") != -1) {
- var result = /msie ([0-9]+)\.([0-9]+)/.exec(ua);
- if (result && result.length == 3) {
- var v = makeVersion(result);
- if (v < 7000) {
- return true;
- }
- }
- }
-
- return false;
- }-*/;
-}
diff --git a/user/src/com/google/gwt/user/client/ui/DockLayoutPanel.java b/user/src/com/google/gwt/user/client/ui/DockLayoutPanel.java
new file mode 100644
index 0000000..27b2400
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/ui/DockLayoutPanel.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.client.ui;
+
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.layout.client.Layout;
+import com.google.gwt.layout.client.Layout.Layer;
+
+/**
+ * A panel that lays its child widgets out "docked" at its outer edges, and
+ * allows its last widget to take up the remaining space in its center.
+ *
+ * <p>
+ * Whenever children are added to, or removed from, this panel, you must call
+ * one of {@link #layout()}, {@link #layout(int)}, or
+ * {@link #layout(int, com.google.gwt.layout.client.Layout.AnimationCallback)}
+ * to update the panel's layout.
+ * </p>
+ *
+ * <p>
+ * This widget will <em>only</em> work in standards mode, which requires
+ * that the HTML page in which it is run have an explicit <!DOCTYPE>
+ * declaration.
+ * </p>
+ *
+ * <p>
+ * NOTE: This class is still very new, and its interface may change without
+ * warning. Use at your own risk.
+ * </p>
+ *
+ * <p>
+ * <h3>Example</h3>
+ * {@example com.google.gwt.examples.DockLayoutPanelExample}
+ * </p>
+ *
+ * TODO(jgw): RTL support.
+ */
+public class DockLayoutPanel extends ComplexPanel implements RequiresLayout,
+ RequiresResize, ProvidesResize {
+
+ /**
+ * Used in {@link DockLayoutPanel#add(Widget, Direction, double)} to specify
+ * the direction in which a child widget will be added.
+ */
+ public enum Direction {
+ NORTH, EAST, SOUTH, WEST, CENTER, LINE_START, LINE_END
+ }
+
+ protected static class LayoutData {
+ public Direction direction;
+ public double oldSize, size;
+ public double originalSize;
+ public boolean hidden;
+ public Layer layer;
+
+ public LayoutData(Direction direction, double size, Layer layer) {
+ this.direction = direction;
+ this.size = size;
+ this.layer = layer;
+ }
+ }
+
+ private final Unit unit;
+ private Widget center;
+ private final Layout layout;
+
+ /**
+ * Creates an empty dock panel.
+ *
+ * @param unit the unit to be used for layout
+ */
+ public DockLayoutPanel(Unit unit) {
+ this.unit = unit;
+
+ setElement(Document.get().createDivElement());
+ layout = new Layout(getElement());
+ }
+
+ /**
+ * Adds a widget to the specified edge of the dock. If the widget is already a
+ * child of this panel, this method behaves as though {@link #remove(Widget)}
+ * had already been called.
+ *
+ * @param widget the widget to be added
+ * @param direction the widget's direction in the dock
+ *
+ * @throws IllegalArgumentException when adding to the {@link #CENTER} and
+ * there is already a different widget there
+ */
+ public void add(Widget widget, Direction direction, double size) {
+ insert(widget, direction, size, null);
+ }
+
+ /**
+ * Adds a widget to the specified edge of the dock. If the widget is already a
+ * child of this panel, this method behaves as though {@link #remove(Widget)}
+ * had already been called.
+ *
+ * @param widget the widget to be added
+ * @param direction the widget's direction in the dock
+ * @param before the widget before which to insert the new child, or
+ * <code>null</code> to append
+ *
+ * @throws IllegalArgumentException when adding to the {@link #CENTER} and
+ * there is already a different widget there
+ */
+ public void insert(Widget widget, Direction direction, double size,
+ Widget before) {
+ assertIsChild(before);
+
+ // Validation.
+ if (before == null) {
+ assert center == null : "No widget may be added after the CENTER widget";
+ } else {
+ assert direction != Direction.CENTER : "A CENTER widget must always be added last";
+ }
+
+ // Detach new child.
+ widget.removeFromParent();
+
+ // Logical attach.
+ getChildren().add(widget);
+ if (direction == Direction.CENTER) {
+ center = widget;
+ }
+
+ // Physical attach.
+ Layer layer = layout.attachChild(widget.getElement(),
+ (before != null) ? before.getElement() : null, widget);
+ LayoutData data = new LayoutData(direction, size, layer);
+ widget.setLayoutData(data);
+
+ // Adopt.
+ adopt(widget);
+ }
+
+ /**
+ * Gets the layout direction of the given child widget.
+ *
+ * @param w the widget to be queried
+ * @return the widget's layout direction, or <code>null</code> if it is not a
+ * child of this panel
+ */
+ public Direction getWidgetDirection(Widget w) {
+ if (w.getParent() != this) {
+ return null;
+ }
+ return ((LayoutData) w.getLayoutData()).direction;
+ }
+
+ public void onResize() {
+ for (Widget child : getChildren()) {
+ if (child instanceof RequiresResize) {
+ ((RequiresResize) child).onResize();
+ }
+ }
+ }
+
+ @Override
+ public boolean remove(Widget w) {
+ boolean removed = super.remove(w);
+ if (removed) {
+ // Clear the center widget.
+ if (w == center) {
+ center = null;
+ }
+
+ LayoutData data = (LayoutData) w.getLayoutData();
+ layout.removeChild(data.layer);
+ }
+
+ return removed;
+ }
+
+ protected Widget getCenter() {
+ return center;
+ }
+
+ protected Unit getUnit() {
+ return unit;
+ }
+
+ @Override
+ protected void onLoad() {
+ layout.onAttach();
+ }
+
+ @Override
+ protected void onUnload() {
+ layout.onDetach();
+ }
+
+ public void layout() {
+ layout(0);
+ }
+
+ public void layout(int duration) {
+ layout(0, null);
+ }
+
+ public void layout(int duration, final Layout.AnimationCallback callback) {
+ int left = 0, top = 0, right = 0, bottom = 0;
+
+ for (Widget child : getChildren()) {
+ LayoutData data = (LayoutData) child.getLayoutData();
+ Layer layer = data.layer;
+
+ switch (data.direction) {
+ case NORTH:
+ layer.setLeftRight(left, unit, right, unit);
+ layer.setTopHeight(top, unit, data.size, unit);
+ top += data.size;
+ break;
+
+ case SOUTH:
+ layer.setLeftRight(left, unit, right, unit);
+ layer.setBottomHeight(bottom, unit, data.size, unit);
+ bottom += data.size;
+ break;
+
+ case WEST:
+ layer.setTopBottom(top, unit, bottom, unit);
+ layer.setLeftWidth(left, unit, data.size, unit);
+ left += data.size;
+ break;
+
+ case EAST:
+ layer.setTopBottom(top, unit, bottom, unit);
+ layer.setRightWidth(right, unit, data.size, unit);
+ right += data.size;
+ break;
+
+ case CENTER:
+ layer.setLeftRight(left, unit, right, unit);
+ layer.setTopBottom(top, unit, bottom, unit);
+ break;
+ }
+ }
+
+ layout.layout(duration, new Layout.AnimationCallback() {
+ public void onAnimationComplete() {
+ for (Widget child : getChildren()) {
+ LayoutData data = (LayoutData) child.getLayoutData();
+ if (data.size != data.oldSize) {
+ data.oldSize = data.size;
+ if (child instanceof RequiresResize) {
+ ((RequiresResize) child).onResize();
+ }
+ }
+
+ if (callback != null) {
+ callback.onAnimationComplete();
+ }
+ }
+ }
+
+ public void onLayout(Layer layer, double progress) {
+ Widget child = (Widget) layer.getUserObject();
+ if (child instanceof RequiresResize) {
+ ((RequiresResize) child).onResize();
+ }
+
+ if (callback != null) {
+ callback.onLayout(layer, progress);
+ }
+ }
+ });
+ }
+
+ /**
+ * TODO(jgw): Is this really the best way to do this?
+ */
+ public Element getContainerElementFor(Widget widget) {
+ assertIsChild(widget);
+ return ((LayoutData)widget.getLayoutData()).layer.getContainerElement();
+ }
+
+ private void assertIsChild(Widget widget) {
+ assert (widget == null) || (widget.getParent() == this) : "TODO";
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/LayoutComposite.java b/user/src/com/google/gwt/user/client/ui/LayoutComposite.java
index f4f5067..f6c9af9 100644
--- a/user/src/com/google/gwt/user/client/ui/LayoutComposite.java
+++ b/user/src/com/google/gwt/user/client/ui/LayoutComposite.java
@@ -16,20 +16,20 @@
package com.google.gwt.user.client.ui;
/**
- * A {@link Composite} implementation that implements {@link RequiresLayout} and
+ * A {@link Composite} implementation that implements {@link RequiresResize} and
* automatically delegates that interface's methods to its wrapped widget, which
- * must itself implement {@link RequiresLayout}.
+ * must itself implement {@link RequiresResize}.
*/
-public abstract class LayoutComposite extends Composite implements RequiresLayout {
+public abstract class LayoutComposite extends Composite implements RequiresResize {
@Override
protected void initWidget(Widget widget) {
- assert widget instanceof RequiresLayout :
+ assert widget instanceof RequiresResize :
"LayoutComposite requires that its wrapped widget implement HasLayout";
super.initWidget(widget);
}
- public void onLayout() {
- ((RequiresLayout) getWidget()).onLayout();
+ public void onResize() {
+ ((RequiresResize) getWidget()).onResize();
}
}
diff --git a/user/src/com/google/gwt/user/client/ui/LayoutPanel.java b/user/src/com/google/gwt/user/client/ui/LayoutPanel.java
index ddfe76b..4adccbc 100644
--- a/user/src/com/google/gwt/user/client/ui/LayoutPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/LayoutPanel.java
@@ -24,8 +24,15 @@
* using the {@link Layout} class.
*
* <p>
- * NOTE: This widget will <em>only</em> work in standards mode, which requires
- * that the HTML page in which it is run have an explicit <!DOCTYPE>
+ * Whenever children are added to, or removed from, this panel, you must call
+ * one of {@link #layout()}, {@link #layout(int)}, or
+ * {@link #layout(int, com.google.gwt.layout.client.Layout.AnimationCallback)}
+ * to update the panel's layout.
+ * </p>
+ *
+ * <p>
+ * This widget will <em>only</em> work in standards mode, which requires that
+ * the HTML page in which it is run have an explicit <!DOCTYPE>
* declaration.
* </p>
*
@@ -40,7 +47,7 @@
* </p>
*/
public class LayoutPanel extends ComplexPanel implements RequiresLayout,
- ProvidesLayout {
+ RequiresResize, ProvidesResize {
private final Layout layout;
@@ -84,7 +91,7 @@
*
* <p>
* After you have made changes to any of the child widgets' constraints, you
- * must call one of the {@link HasAnimatedLayout} methods for those changes to
+ * must call one of the {@link RequiresLayout} methods for those changes to
* be reflected visually.
* </p>
*
@@ -96,52 +103,14 @@
return (Layout.Layer) child.getLayoutData();
}
- /**
- * This method, or one of its overloads, must be called whenever any of the
- * {@link Layout.Layer layers} associated with its children is modified.
- *
- * @see #layout(int)
- * @see #layout(int, com.google.gwt.layout.client.Layout.AnimationCallback)
- */
public void layout() {
layout.layout();
}
- /**
- * This method, or one of its overloads, must be called whenever any of the
- * {@link Layout.Layer layers} associated with its children is modified.
- *
- * <p>
- * This overload will cause the layout to be updated by animating over a
- * specified period of time.
- * </p>
- *
- * @param duration the animation duration, in milliseconds
- *
- * @see #layout()
- * @see #layout(int, com.google.gwt.layout.client.Layout.AnimationCallback)
- */
public void layout(int duration) {
layout.layout(duration);
}
- /**
- * This method, or one of its overloads, must be called whenever any of the
- * {@link Layout.Layer layers} associated with its children is modified.
- *
- * <p>
- * This overload will cause the layout to be updated by animating over a
- * specified period of time. In addition, it provides a callback that will be
- * informed of updates to the layers. This can be used to create more complex
- * animation effects.
- * </p>
- *
- * @param duration the animation duration, in milliseconds
- * @param callback the animation callback
- *
- * @see #layout()
- * @see #layout(int, com.google.gwt.layout.client.Layout.AnimationCallback)
- */
public void layout(int duration, final Layout.AnimationCallback callback) {
layout.layout(duration, new Layout.AnimationCallback() {
public void onAnimationComplete() {
@@ -155,8 +124,8 @@
// Inform the child associated with this layer that its size may have
// changed.
Widget child = (Widget) layer.getUserObject();
- if (child instanceof RequiresLayout) {
- ((RequiresLayout) child).onLayout();
+ if (child instanceof RequiresResize) {
+ ((RequiresResize) child).onResize();
}
// Chain to the passed callback.
@@ -167,10 +136,10 @@
});
}
- public void onLayout() {
+ public void onResize() {
for (Widget child : getChildren()) {
- if (child instanceof RequiresLayout) {
- ((RequiresLayout) child).onLayout();
+ if (child instanceof RequiresResize) {
+ ((RequiresResize) child).onResize();
}
}
}
diff --git a/user/src/com/google/gwt/user/client/ui/ProvidesLayout.java b/user/src/com/google/gwt/user/client/ui/ProvidesResize.java
similarity index 71%
rename from user/src/com/google/gwt/user/client/ui/ProvidesLayout.java
rename to user/src/com/google/gwt/user/client/ui/ProvidesResize.java
index f6e6d07..543eae3 100644
--- a/user/src/com/google/gwt/user/client/ui/ProvidesLayout.java
+++ b/user/src/com/google/gwt/user/client/ui/ProvidesResize.java
@@ -17,24 +17,24 @@
/**
* This tag interface specifies that the implementing widget will call
- * {@link RequiresLayout#onLayout()} on its children whenever their size may
+ * {@link RequiresResize#onResize()} on its children whenever their size may
* have changed.
*
* <p>
* With limited exceptions (such as {@link RootLayoutPanel}), widgets that
- * implement this interface will also implement {@link RequiresLayout}. A typical
- * widget will implement {@link RequiresLayout#onLayout()} like this:
+ * implement this interface will also implement {@link RequiresResize}. A typical
+ * widget will implement {@link RequiresResize#onResize()} like this:
*
* <code>
- * public void onLayout() {
+ * public void onResize() {
* for (Widget child : getChildren()) {
- * if (child instanceof RequiresLayout) {
- * ((RequiresLayout) child).onLayout();
+ * if (child instanceof RequiresResize) {
+ * ((RequiresResize) child).onResize();
* }
* }
* }
* </code>
* </p>
*/
-public interface ProvidesLayout {
+public interface ProvidesResize {
}
diff --git a/user/src/com/google/gwt/user/client/ui/RequiresLayout.java b/user/src/com/google/gwt/user/client/ui/RequiresLayout.java
index be81be6..680c9a6 100644
--- a/user/src/com/google/gwt/user/client/ui/RequiresLayout.java
+++ b/user/src/com/google/gwt/user/client/ui/RequiresLayout.java
@@ -15,20 +15,54 @@
*/
package com.google.gwt.user.client.ui;
+import com.google.gwt.layout.client.Layout;
+
/**
- * This interface designates that its implementor needs to be informed whenever
- * its size is modified.
+ * Designates that a widget requires a method to be explicitly called after its
+ * children are modified.
*
* <p>
- * Widgets that implement this interface should only be added to those that
- * implement {@link ProvidesLayout}. Failure to do so will usually result in
- * {@link #onLayout()} not being called.
+ * Widgets that implement this interface perform some layout work that will not
+ * be fully realized until {@link #layout()} or one of its overloads is called.
+ * This is required after adding or removing child widgets, and after any other
+ * operations that the implementor designates as requiring layout. Note that
+ * only <em>one</em> call to {@link #layout()} is required after any number of
+ * modifications.
* </p>
*/
public interface RequiresLayout {
/**
- * Update the layout immediately.
+ * Layout children immediately.
+ *
+ * @see #layout(int)
+ * @see #layout(int, com.google.gwt.layout.client.Layout.AnimationCallback)
*/
- void onLayout();
+ void layout();
+
+ /**
+ * Layout children, animating over the specified period of time.
+ *
+ * @param duration the animation duration, in milliseconds
+ *
+ * @see #layout()
+ * @see #layout(int, com.google.gwt.layout.client.Layout.AnimationCallback)
+ */
+ void layout(int duration);
+
+ /**
+ * Layout children, animating over the specified period of time.
+ *
+ * <p>
+ * This method provides a callback that will be informed of animation updates.
+ * This can be used to create more complex animation effects.
+ * </p>
+ *
+ * @param duration the animation duration, in milliseconds
+ * @param callback the animation callback
+ *
+ * @see #layout()
+ * @see #layout(int, com.google.gwt.layout.client.Layout.AnimationCallback)
+ */
+ void layout(int duration, final Layout.AnimationCallback callback);
}
diff --git a/user/src/com/google/gwt/user/client/ui/RequiresResize.java b/user/src/com/google/gwt/user/client/ui/RequiresResize.java
new file mode 100644
index 0000000..7193a2d
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/ui/RequiresResize.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.client.ui;
+
+/**
+ * This interface designates that its implementor needs to be informed whenever
+ * its size is modified.
+ *
+ * <p>
+ * Widgets that implement this interface should only be added to those that
+ * implement {@link ProvidesResize}. Failure to do so will usually result in
+ * {@link #onResize()} not being called.
+ * </p>
+ */
+public interface RequiresResize {
+
+ /**
+ * This method must be called whenever the implementor's size has been
+ * modified.
+ */
+ void onResize();
+}
diff --git a/user/src/com/google/gwt/user/client/ui/RootLayoutPanel.java b/user/src/com/google/gwt/user/client/ui/RootLayoutPanel.java
index 88969e0..9351ec1 100644
--- a/user/src/com/google/gwt/user/client/ui/RootLayoutPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/RootLayoutPanel.java
@@ -24,7 +24,7 @@
* to the document body (i.e. {@link RootPanel#get()}).
*
* <p>
- * This panel automatically calls {@link RequiresLayout#layout()} on itself when
+ * This panel automatically calls {@link RequiresResize#layout()} on itself when
* initially created, and whenever the window is resized.
* </p>
*
@@ -44,7 +44,7 @@
* {@example com.google.gwt.examples.LayoutPanelExample}
* </p>
*/
-public class RootLayoutPanel extends LayoutPanel implements ProvidesLayout {
+public class RootLayoutPanel extends LayoutPanel {
private static RootLayoutPanel singleton;
@@ -70,11 +70,11 @@
private RootLayoutPanel() {
Window.addResizeHandler(new ResizeHandler() {
public void onResize(ResizeEvent event) {
- onLayout();
+ RootLayoutPanel.this.onResize();
}
});
- // TODO: We need notification of font-size changes as well.
+ // TODO(jgw): We need notification of font-size changes as well.
// I believe there's a hidden iframe trick that we can use to get
// a font-size-change event (really an em-definition-change event).
}