package com.vaadin.incubator.dashlayout.client.ui; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.ui.Widget; import com.vaadin.incubator.dashlayout.client.util.css.CSSUtil; import com.vaadin.terminal.gwt.client.BrowserInfo; 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.RenderInformation.FloatSize; import com.vaadin.terminal.gwt.client.RenderInformation.Size; import com.vaadin.terminal.gwt.client.ui.AlignmentInfo; /** * ChildCell represents one slot in the layout. */ public class ChildCell { // Size is the allocated space for this widget private RenderSpace space = null; // Widget size is the natural minimum size of the widget (including margins) private final Size widgetSize = new Size(-1, -1); // Margins that are specified for the widget in CSS private int[] widgetMargin = { 0, 0, 0, 0 }; private final Widget widget; private final VDashLayout parent; private FloatSize relativeSize; private AlignmentInfo alignment = new AlignmentInfo(1); private int alignmentOffsetLeft = 0; private int alignmentOffsetTop = 0; private float expandRatio = -1; private int surplus = 0; public ChildCell(Widget child, VDashLayout parent) { widget = child; this.parent = parent; // Floats affect how computedStyle is calculated in browsers setFloat("left"); } public void reset(boolean resetSize) { if (resetSize) { widget.setWidth(""); widget.setHeight(""); } widget.getElement().getStyle().setPropertyPx("marginTop", widgetMargin[0]); widget.getElement().getStyle().setPropertyPx("marginRight", widgetMargin[1]); widget.getElement().getStyle().setPropertyPx("marginBottom", widgetMargin[2]); widget.getElement().getStyle().setPropertyPx("marginLeft", widgetMargin[3]); alignmentOffsetLeft = 0; alignmentOffsetTop = 0; surplus = 0; } public void reAlign() { int left = 0; int top = 0; if (alignment != null) { int horizSpace = space.getWidth() - widgetSize.getWidth(); if (horizSpace < 0) { horizSpace = 0; } if (alignment.isHorizontalCenter()) { left = horizSpace / 2; } else if (alignment.isRight()) { left = horizSpace; } int vertSpace = space.getHeight() - widgetSize.getHeight(); if (vertSpace < 0) { vertSpace = 0; } if (alignment.isVerticalCenter()) { top = vertSpace / 2; } else if (alignment.isBottom()) { top = vertSpace; } } if (parent.getChildren().indexOf(widget) > 0) { if (parent.isHorizontal()) { left += parent.getSpacing(); } else { top += parent.getSpacing(); } } alignmentOffsetLeft = left; alignmentOffsetTop = top; left += widgetMargin[3]; widget.getElement().getStyle().setPropertyPx("marginLeft", left); top += widgetMargin[0]; widget.getElement().getStyle().setPropertyPx("marginTop", top); // TODO odd fix, try to isolate why IE needs these, why the initial // settings aren't enough if (BrowserInfo.get().isIE6()) { widget.getElement().getStyle().setProperty("display", "inline"); } // Need to remove spacing, it isn't actually reserving space from this // layout slot if (parent.getChildren().indexOf(widget) > 0) { if (parent.isHorizontal()) { left -= parent.getSpacing(); } else { top -= parent.getSpacing(); } } // Accommodate whole layout cell if (parent.isHorizontal()) { final int widgetWidth = widgetSize.getWidth() - widgetMargin[1] - widgetMargin[3]; if (widgetWidth > -1) { final int accommodated = widgetWidth + left + widgetMargin[1]; if (space.getWidth() > accommodated) { surplus = space.getWidth() - accommodated; widget.getElement().getStyle().setPropertyPx("marginRight", surplus + widgetMargin[1]); } } } else { final int widgetHeight = widgetSize.getHeight() - widgetMargin[0] - widgetMargin[2]; if (widgetHeight > -1) { final int accommodated = widgetHeight + top + widgetMargin[2]; if (space.getHeight() > accommodated) { surplus = space.getHeight() - accommodated; widget.getElement().getStyle().setPropertyPx( "marginBottom", surplus + widgetMargin[2]); } } } // Needed to shake IE7 a bit, some components might get clipped // otherwise (e.g. Panel) if (BrowserInfo.get().isIE7()) { widget.getElement().getStyle().setProperty("zoom", ""); DeferredCommand.addCommand(new Command() { public void execute() { widget.getElement().getStyle().setProperty("zoom", "1"); } }); } } public void setExpandRatio(float i) { expandRatio = i; } public void setAlignment(int i) { alignment = new AlignmentInfo(i); } private void setFloat(String floatValue) { widget.getElement().getStyle().setProperty("float", floatValue); widget.getElement().getStyle().setProperty("styleFloat", floatValue); widget.getElement().getStyle().setProperty("cssFloat", floatValue); if (!parent.isHorizontal()) { widget.getElement().getStyle().setProperty("clear", floatValue); } if (BrowserInfo.get().isIE()) { widget.getElement().getStyle().setProperty("zoom", "1"); widget.getElement().getStyle().setProperty("display", "inline"); } } public void updateSizeInfo(UIDL uidl) { if (uidl.hasAttribute("cached")) { return; } float relativeWidth = -1; if (uidl.hasAttribute("width")) { final String w = uidl.getStringAttribute("width"); if (w.endsWith("%")) { relativeWidth = Float .parseFloat(w.substring(0, w.length() - 1)); } } float relativeHeight = -1; if (uidl.hasAttribute("height")) { final String h = uidl.getStringAttribute("height"); if (h.endsWith("%")) { relativeHeight = Float.parseFloat(h .substring(0, h.length() - 1)); } } relativeSize = new FloatSize(relativeWidth, relativeHeight); } public void updateSpace() { if (widget.isAttached()) { int width = -1; int height = -1; float ratio = 0; if ((parent.isHorizontal() && !parent.undefWidth) || !parent.undefHeight) { float compoundRatio = parent.getCompoundRatio(); if (compoundRatio > 0 && expandRatio > 0) { ratio = (expandRatio / compoundRatio); } else if (compoundRatio < 0) { // No expand ratios set to any component, set equal // ratios to every widget ratio = 1.0f / parent.getCells().size(); } } if (parent.isHorizontal()) { height = parent.height; if (ratio != 0) { width = parent.width; if (isRelativeWidth()) { width = (int) ((width - parent.getConsumedSpace()) * ratio); } else { width = (int) (widgetSize.getWidth() + (width - parent .getConsumedSpace()) * ratio); } } else if (isRelativeWidth()) { width = 0; } } else { width = parent.width; if (ratio != 0) { height = parent.height; if (isRelativeHeight()) { height = (int) ((height - parent.getConsumedSpace()) * ratio); } else { height = (int) (widgetSize.getHeight() + (height - parent .getConsumedSpace()) * ratio); } } else if (isRelativeHeight()) { height = 0; } } space = new RenderSpace(width, height); } } public boolean isRelativeWidth() { return relativeSize.getWidth() > -1; } public boolean isRelativeHeight() { return relativeSize.getHeight() > -1; } public boolean hasRelativeSize() { return isRelativeHeight() || isRelativeWidth(); } public boolean isRelativeSizeInParentOrientation() { return parent.isHorizontal() ? isRelativeWidth() : isRelativeHeight(); } public Widget getWidget() { return widget; } public void updateWidgetMarginAndSize() { if (widget.isAttached()) { updateWidgetMargin(); updateWidgetSize(); } } public void updateWidgetSize() { if (widget.isAttached()) { int width = Util.getRequiredWidth(widget.getElement()) + widgetMargin[1] + widgetMargin[3]; int height = Util.getRequiredHeight(widget.getElement()) + widgetMargin[0] + widgetMargin[2]; widgetSize.setWidth(width); widgetSize.setHeight(height); } } public void updateWidgetMargin() { if (widget.isAttached()) { widgetMargin = CSSUtil.collectMargin(widget.getElement()); widgetMargin[3] -= alignmentOffsetLeft; widgetMargin[0] -= alignmentOffsetTop; if (parent.isHorizontal()) { widgetMargin[1] -= surplus; } else { widgetMargin[2] -= surplus; } } } public RenderSpace getRenderSpace() { return space; } public Size getWidgetSize() { return widgetSize; } public int getMaxSizeInParentOrientation() { final int spaceSize = parent.isHorizontal() ? space.getWidth() : space .getHeight(); final int widgetS = parent.isHorizontal() ? widgetSize.getWidth() : widgetSize.getHeight(); return Math.max(spaceSize, widgetS); } public int getMaxSizeInNonParentOrientation() { final int spaceSize = parent.isHorizontal() ? space.getHeight() : space .getWidth(); final int widgetS = parent.isHorizontal() ? widgetSize.getHeight() : widgetSize.getWidth(); return Math.max(spaceSize, widgetS); } public RenderSpace getSpaceSansMargins() { return new RenderSpace(space.getWidth() - widgetMargin[1] - widgetMargin[3], space.getHeight() - widgetMargin[0] - widgetMargin[2]); } public boolean updateAfterOtherCells() { if (parent.isHorizontal()) { return isRelativeHeight() || (!parent.undefWidth && (isRelativeWidth() || expandRatio != -1)); } else { return isRelativeWidth() || (!parent.undefHeight && (isRelativeHeight() || expandRatio != -1)); } } public float getExpandRatio() { return expandRatio; } }