001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.user.client.ui;
017:
018: import com.google.gwt.user.client.DOM;
019: import com.google.gwt.user.client.Element;
020:
021: /**
022: * An absolute panel positions all of its children absolutely, allowing them to
023: * overlap.
024: *
025: * <p>
026: * Note that this panel will not automatically resize itself to allow enough
027: * room for its absolutely-positioned children. It must be explicitly sized in
028: * order to make room for them.
029: * </p>
030: *
031: * <p>
032: * Once a widget has been added to an absolute panel, the panel effectively
033: * "owns" the positioning of the widget. Any existing positioning attributes on
034: * the widget may be modified by the panel.
035: * </p>
036: */
037: public class AbsolutePanel extends ComplexPanel {
038:
039: /**
040: * Changes a DOM element's positioning to static.
041: *
042: * @param elem the DOM element
043: */
044: private static void changeToStaticPositioning(Element elem) {
045: DOM.setStyleAttribute(elem, "left", "");
046: DOM.setStyleAttribute(elem, "top", "");
047: DOM.setStyleAttribute(elem, "position", "");
048: }
049:
050: /**
051: * Creates an empty absolute panel.
052: */
053: public AbsolutePanel() {
054: setElement(DOM.createDiv());
055:
056: // Setting the panel's position style to 'relative' causes it to be treated
057: // as a new positioning context for its children.
058: DOM.setStyleAttribute(getElement(), "position", "relative");
059: DOM.setStyleAttribute(getElement(), "overflow", "hidden");
060: }
061:
062: /**
063: * Adds a child widget to this panel.
064: *
065: * @param w the child widget to be added
066: */
067: @Override
068: public void add(Widget w) {
069: super .add(w, getElement());
070: }
071:
072: /**
073: * Adds a widget to the panel at the specified position. Setting a position of
074: * <code>(-1, -1)</code> will cause the child widget to be positioned
075: * statically.
076: *
077: * @param w the widget to be added
078: * @param left the widget's left position
079: * @param top the widget's top position
080: */
081: public void add(Widget w, int left, int top) {
082: // In order to avoid the potential for a flicker effect, it is necessary
083: // to set the position of the widget before adding it to the AbsolutePanel.
084: // The Widget should be removed from its parent before any positional
085: // changes are made to prevent flickering.
086: w.removeFromParent();
087: setWidgetPositionImpl(w, left, top);
088: add(w);
089: }
090:
091: /**
092: * Gets the position of the left outer border edge of the widget relative to
093: * the left outer border edge of the panel.
094: *
095: * @param w the widget whose position is to be retrieved
096: * @return the widget's left position
097: */
098: public int getWidgetLeft(Widget w) {
099: checkWidgetParent(w);
100: return DOM.getAbsoluteLeft(w.getElement())
101: - DOM.getAbsoluteLeft(getElement());
102: }
103:
104: /**
105: * Gets the position of the top outer border edge of the widget relative to
106: * the top outer border edge of the panel.
107: *
108: * @param w the widget whose position is to be retrieved
109: * @return the widget's top position
110: */
111: public int getWidgetTop(Widget w) {
112: checkWidgetParent(w);
113: return DOM.getAbsoluteTop(w.getElement())
114: - DOM.getAbsoluteTop(getElement());
115: }
116:
117: /**
118: * Overrides {@link ComplexPanel#remove(Widget)} to change the removed
119: * Widget's element back to static positioning.This is done so that any
120: * positioning changes to the widget that were done by the panel are undone
121: * when the widget is disowned from the panel.
122: */
123: @Override
124: public boolean remove(Widget w) {
125: boolean removed = super .remove(w);
126: if (removed) {
127: changeToStaticPositioning(w.getElement());
128: }
129: return removed;
130: }
131:
132: /**
133: * Sets the position of the specified child widget. Setting a position of
134: * <code>(-1, -1)</code> will cause the child widget to be positioned
135: * statically.
136: *
137: * @param w the child widget to be positioned
138: * @param left the widget's left position
139: * @param top the widget's top position
140: */
141: public void setWidgetPosition(Widget w, int left, int top) {
142: checkWidgetParent(w);
143: setWidgetPositionImpl(w, left, top);
144: }
145:
146: private void checkWidgetParent(Widget w) {
147: if (w.getParent() != this ) {
148: throw new IllegalArgumentException(
149: "Widget must be a child of this panel.");
150: }
151: }
152:
153: private void setWidgetPositionImpl(Widget w, int left, int top) {
154: Element h = w.getElement();
155: if ((left == -1) && (top == -1)) {
156: changeToStaticPositioning(h);
157: } else {
158: DOM.setStyleAttribute(h, "position", "absolute");
159: DOM.setStyleAttribute(h, "left", left + "px");
160: DOM.setStyleAttribute(h, "top", top + "px");
161: }
162: }
163: }
|