123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- /*
- @ITMillApache2LicenseForJavaFiles@
- */
- package com.vaadin.terminal.gwt.client.ui;
-
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Set;
- import java.util.Map.Entry;
-
- import com.google.gwt.dom.client.DivElement;
- import com.google.gwt.dom.client.Document;
- import com.google.gwt.dom.client.Style;
- import com.google.gwt.event.dom.client.DomEvent.Type;
- import com.google.gwt.event.shared.EventHandler;
- import com.google.gwt.event.shared.HandlerRegistration;
- import com.google.gwt.user.client.DOM;
- import com.google.gwt.user.client.Element;
- import com.google.gwt.user.client.ui.ComplexPanel;
- import com.google.gwt.user.client.ui.SimplePanel;
- import com.google.gwt.user.client.ui.Widget;
- import com.vaadin.terminal.gwt.client.ApplicationConnection;
- import com.vaadin.terminal.gwt.client.BrowserInfo;
- import com.vaadin.terminal.gwt.client.Container;
- import com.vaadin.terminal.gwt.client.Paintable;
- import com.vaadin.terminal.gwt.client.RenderSpace;
- import com.vaadin.terminal.gwt.client.UIDL;
- import com.vaadin.terminal.gwt.client.Util;
- import com.vaadin.terminal.gwt.client.VCaption;
-
- public class VAbsoluteLayout extends ComplexPanel implements Container {
-
- /** Tag name for widget creation */
- public static final String TAGNAME = "absolutelayout";
-
- /** Class name, prefix in styling */
- public static final String CLASSNAME = "v-absolutelayout";
-
- public static final String CLICK_EVENT_IDENTIFIER = "click";
-
- private DivElement marginElement;
-
- protected final Element canvas = DOM.createDiv();
-
- private int excessPixelsHorizontal;
-
- private int excessPixelsVertical;
-
- private Object previousStyleName;
-
- private Map<String, AbsoluteWrapper> pidToComponentWrappper = new HashMap<String, AbsoluteWrapper>();
-
- protected ApplicationConnection client;
-
- private boolean rendering;
-
- private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler(
- this, CLICK_EVENT_IDENTIFIER) {
-
- @Override
- protected Paintable getChildComponent(Element element) {
- return getComponent(element);
- }
-
- @Override
- protected <H extends EventHandler> HandlerRegistration registerHandler(
- H handler, Type<H> type) {
- return addDomHandler(handler, type);
- }
- };
-
- public VAbsoluteLayout() {
- setElement(Document.get().createDivElement());
- setStyleName(CLASSNAME);
- marginElement = Document.get().createDivElement();
- canvas.getStyle().setProperty("position", "relative");
- canvas.getStyle().setProperty("overflow", "hidden");
- marginElement.appendChild(canvas);
- getElement().appendChild(marginElement);
- }
-
- public RenderSpace getAllocatedSpace(Widget child) {
- // TODO needs some special handling for components with only on edge
- // horizontally or vertically defined
- AbsoluteWrapper wrapper = (AbsoluteWrapper) child.getParent();
- int w;
- if (wrapper.left != null && wrapper.right != null) {
- w = wrapper.getOffsetWidth();
- } else if (wrapper.right != null) {
- // left == null
- // available width == right edge == offsetleft + width
- w = wrapper.getOffsetWidth() + wrapper.getElement().getOffsetLeft();
- } else {
- // left != null && right == null || left == null &&
- // right == null
- // available width == canvas width - offset left
- w = canvas.getOffsetWidth() - wrapper.getElement().getOffsetLeft();
- }
- int h;
- if (wrapper.top != null && wrapper.bottom != null) {
- h = wrapper.getOffsetHeight();
- } else if (wrapper.bottom != null) {
- // top not defined, available space 0... bottom of wrapper
- h = wrapper.getElement().getOffsetTop() + wrapper.getOffsetHeight();
- } else {
- // top defined or both undefined, available space == canvas - top
- h = canvas.getOffsetHeight() - wrapper.getElement().getOffsetTop();
- }
-
- return new RenderSpace(w, h);
- }
-
- public boolean hasChildComponent(Widget component) {
- for (Iterator<Entry<String, AbsoluteWrapper>> iterator = pidToComponentWrappper
- .entrySet().iterator(); iterator.hasNext();) {
- if (iterator.next().getValue().paintable == component) {
- return true;
- }
- }
- return false;
- }
-
- public void replaceChildComponent(Widget oldComponent, Widget newComponent) {
- for (Widget wrapper : getChildren()) {
- AbsoluteWrapper w = (AbsoluteWrapper) wrapper;
- if (w.getWidget() == oldComponent) {
- w.setWidget(newComponent);
- return;
- }
- }
- }
-
- public boolean requestLayout(Set<Paintable> children) {
- // component inside an absolute panel never affects parent nor the
- // layout
- return true;
- }
-
- public void updateCaption(Paintable component, UIDL uidl) {
- AbsoluteWrapper parent2 = (AbsoluteWrapper) ((Widget) component)
- .getParent();
- parent2.updateCaption(uidl);
- }
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- rendering = true;
- this.client = client;
- // TODO margin handling
- if (client.updateComponent(this, uidl, true)) {
- rendering = false;
- return;
- }
-
- clickEventHandler.handleEventHandlerRegistration(client);
-
- HashSet<String> unrenderedPids = new HashSet<String>(
- pidToComponentWrappper.keySet());
-
- for (Iterator<Object> childIterator = uidl.getChildIterator(); childIterator
- .hasNext();) {
- UIDL cc = (UIDL) childIterator.next();
- if (cc.getTag().equals("cc")) {
- UIDL componentUIDL = cc.getChildUIDL(0);
- unrenderedPids.remove(componentUIDL.getId());
- getWrapper(client, componentUIDL).updateFromUIDL(cc);
- }
- }
-
- for (String pid : unrenderedPids) {
- AbsoluteWrapper absoluteWrapper = pidToComponentWrappper.get(pid);
- pidToComponentWrappper.remove(pid);
- absoluteWrapper.destroy();
- }
- rendering = false;
- }
-
- private AbsoluteWrapper getWrapper(ApplicationConnection client,
- UIDL componentUIDL) {
- AbsoluteWrapper wrapper = pidToComponentWrappper.get(componentUIDL
- .getId());
- if (wrapper == null) {
- wrapper = new AbsoluteWrapper(client.getPaintable(componentUIDL));
- pidToComponentWrappper.put(componentUIDL.getId(), wrapper);
- add(wrapper);
- }
- return wrapper;
-
- }
-
- @Override
- public void add(Widget child) {
- super.add(child, canvas);
- }
-
- @Override
- public void setStyleName(String style) {
- super.setStyleName(style);
- if (previousStyleName == null || !previousStyleName.equals(style)) {
- excessPixelsHorizontal = -1;
- excessPixelsVertical = -1;
- }
- }
-
- @Override
- public void setWidth(String width) {
- super.setWidth(width);
- // TODO do this so that canvas gets the sized properly (the area
- // inside marginals)
- canvas.getStyle().setProperty("width", width);
-
- if (!rendering) {
- if (BrowserInfo.get().isIE6()) {
- relayoutWrappersForIe6();
- }
- relayoutRelativeChildren();
- }
- }
-
- private void relayoutRelativeChildren() {
- for (Widget widget : getChildren()) {
- if (widget instanceof AbsoluteWrapper) {
- AbsoluteWrapper w = (AbsoluteWrapper) widget;
- client.handleComponentRelativeSize(w.getWidget());
- w.updateCaptionPosition();
- }
- }
- }
-
- @Override
- public void setHeight(String height) {
- super.setHeight(height);
- // TODO do this so that canvas gets the sized properly (the area
- // inside marginals)
- canvas.getStyle().setProperty("height", height);
-
- if (!rendering) {
- if (BrowserInfo.get().isIE6()) {
- relayoutWrappersForIe6();
- }
- relayoutRelativeChildren();
- }
- }
-
- private void relayoutWrappersForIe6() {
- for (Widget wrapper : getChildren()) {
- if (wrapper instanceof AbsoluteWrapper) {
- ((AbsoluteWrapper) wrapper).ie6Layout();
- }
- }
- }
-
- public class AbsoluteWrapper extends SimplePanel {
- private String css;
- private String left;
- private String top;
- private String right;
- private String bottom;
- private String zIndex;
-
- private Paintable paintable;
- private VCaption caption;
-
- public AbsoluteWrapper(Paintable paintable) {
- this.paintable = paintable;
- setStyleName(CLASSNAME + "-wrapper");
- }
-
- public void updateCaption(UIDL uidl) {
-
- boolean captionIsNeeded = VCaption.isNeeded(uidl);
- if (captionIsNeeded) {
- if (caption == null) {
- caption = new VCaption(paintable, client);
- VAbsoluteLayout.this.add(caption);
- }
- caption.updateCaption(uidl);
- updateCaptionPosition();
- } else {
- if (caption != null) {
- caption.removeFromParent();
- caption = null;
- }
- }
- }
-
- public void destroy() {
- if (caption != null) {
- caption.removeFromParent();
- }
- client.unregisterPaintable(paintable);
- removeFromParent();
- }
-
- public void updateFromUIDL(UIDL componentUIDL) {
- setPosition(componentUIDL.getStringAttribute("css"));
- if (getWidget() != paintable) {
- setWidget((Widget) paintable);
- }
- UIDL childUIDL = componentUIDL.getChildUIDL(0);
- paintable.updateFromUIDL(childUIDL, client);
- if (childUIDL.hasAttribute("cached")) {
- // child may need relative size adjustment if wrapper details
- // have changed this could be optimized (check if wrapper size
- // has changed)
- client.handleComponentRelativeSize((Widget) paintable);
- }
- }
-
- public void setPosition(String stringAttribute) {
- if (css == null || !css.equals(stringAttribute)) {
- css = stringAttribute;
- top = right = bottom = left = zIndex = null;
- if (!css.equals("")) {
- String[] properties = css.split(";");
- for (int i = 0; i < properties.length; i++) {
- String[] keyValue = properties[i].split(":");
- if (keyValue[0].equals("left")) {
- left = keyValue[1];
- } else if (keyValue[0].equals("top")) {
- top = keyValue[1];
- } else if (keyValue[0].equals("right")) {
- right = keyValue[1];
- } else if (keyValue[0].equals("bottom")) {
- bottom = keyValue[1];
- } else if (keyValue[0].equals("z-index")) {
- zIndex = keyValue[1];
- }
- }
- }
- // ensure ne values
- Style style = getElement().getStyle();
- /*
- * IE8 dies when nulling zIndex, even in IE7 mode. All other css
- * properties (and even in older IE's) accept null values just
- * fine. Assign empty string instead of null.
- */
- if (zIndex != null) {
- style.setProperty("zIndex", zIndex);
- } else {
- style.setProperty("zIndex", "");
- }
- style.setProperty("top", top);
- style.setProperty("left", left);
- style.setProperty("right", right);
- style.setProperty("bottom", bottom);
-
- if (BrowserInfo.get().isIE6()) {
- ie6Layout();
- }
- }
- updateCaptionPosition();
- }
-
- private void updateCaptionPosition() {
- if (caption != null) {
- Style style = caption.getElement().getStyle();
- style.setProperty("position", "absolute");
- style.setPropertyPx("left", getElement().getOffsetLeft());
- style.setPropertyPx("top", getElement().getOffsetTop()
- - caption.getHeight());
- }
- }
-
- private void ie6Layout() {
- // special handling for IE6 is needed, it does not support
- // setting both left/right or top/bottom
- Style style = getElement().getStyle();
- if (bottom != null && top != null) {
- // define height for wrapper to simulate bottom property
- int bottompixels = measureForIE6(bottom, true);
- ApplicationConnection.getConsole().log("ALB" + bottompixels);
- int height = canvas.getOffsetHeight() - bottompixels
- - getElement().getOffsetTop();
- ApplicationConnection.getConsole().log("ALB" + height);
- if (height < 0) {
- height = 0;
- }
- style.setPropertyPx("height", height);
- } else {
- // reset possibly existing value
- style.setProperty("height", "");
- }
- if (left != null && right != null) {
- // define width for wrapper to simulate right property
- int rightPixels = measureForIE6(right, false);
- ApplicationConnection.getConsole().log("ALR" + rightPixels);
- int width = canvas.getOffsetWidth() - rightPixels
- - getElement().getOffsetLeft();
- ApplicationConnection.getConsole().log("ALR" + width);
- if (width < 0) {
- width = 0;
- }
- style.setPropertyPx("width", width);
- } else {
- // reset possibly existing value
- style.setProperty("width", "");
- }
- }
-
- }
-
- private Element measureElement;
-
- private int measureForIE6(String cssLength, boolean vertical) {
- if (measureElement == null) {
- measureElement = DOM.createDiv();
- measureElement.getStyle().setProperty("position", "absolute");
- canvas.appendChild(measureElement);
- }
- if (vertical) {
- measureElement.getStyle().setProperty("height", cssLength);
- return measureElement.getOffsetHeight();
- } else {
- measureElement.getStyle().setProperty("width", cssLength);
- return measureElement.getOffsetWidth();
- }
- }
-
- /**
- * Returns the child component which contains "element". The child component
- * is also returned if "element" is part of its caption.
- *
- * @param element
- * An element that is a sub element of the root element in this
- * layout
- * @return The Paintable which the element is a part of. Null if the element
- * belongs to the layout and not to a child.
- */
- private Paintable getComponent(Element element) {
- return Util.getChildPaintableForElement(client, this, element);
- }
-
- }
|