package com.vaadin.terminal.gwt.client;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public static final class MeasuredSize {
private int width = -1;
private int height = -1;
+
+ private int[] paddings = new int[4];
+ private int[] borders = new int[4];
+ private int[] margins = new int[4];
+
+ private final VPaintableWidget paintable;
+
private boolean isDirty = true;
private final Map<Element, int[]> dependencySizes = new HashMap<Element, int[]>();
- public int getHeight() {
+ public MeasuredSize(VPaintableWidget paintable) {
+ this.paintable = paintable;
+ }
+
+ public int getOuterHeight() {
return height;
}
- public int getWidth() {
+ public int getOuterWidth() {
return width;
}
- public void setHeight(int height) {
+ private static int sumWidths(int[] sizes) {
+ return sizes[1] + sizes[3];
+ }
+
+ private static int sumHeights(int[] sizes) {
+ return sizes[0] + sizes[2];
+ }
+
+ public int getInnerHeight() {
+ return height - sumHeights(margins) - sumHeights(borders)
+ - sumHeights(paddings);
+ }
+
+ public int getInnerWidth() {
+ return width - sumWidths(margins) - sumWidths(borders)
+ - sumWidths(paddings);
+ }
+
+ public void setOuterHeight(int height) {
if (this.height != height) {
isDirty = true;
+ this.height = height;
}
- this.height = height;
}
- public void setWidth(int width) {
- if (width != this.width) {
+ public void setOuterWidth(int width) {
+ if (this.width != width) {
isDirty = true;
+ this.width = width;
}
- this.width = width;
}
public boolean isDirty() {
dependencySizes.remove(element);
}
- public int getDependencyWidth(Element e) {
+ public int getDependencyOuterWidth(Element e) {
return getDependencySize(e, 0);
}
- public int getDependencyHeight(Element e) {
+ public int getDependencyOuterHeight(Element e) {
return getDependencySize(e, 1);
}
return sizes[index];
}
}
+
+ public int getBorderHeight() {
+ return sumHeights(borders);
+ }
+
+ public int getBorderWidth() {
+ return sumWidths(borders);
+ }
+
+ public int getPaddingHeight() {
+ return sumHeights(paddings);
+ }
+
+ public int getPaddingWidth() {
+ return sumWidths(paddings);
+ }
+
+ public int getMarginHeight() {
+ return sumHeights(margins);
+ }
+
+ public int getMarginWidth() {
+ return sumWidths(margins);
+ }
+
+ public int getMarginTop() {
+ return margins[0];
+ }
+
+ public int getMarginRight() {
+ return margins[1];
+ }
+
+ public int getMarginBottom() {
+ return margins[2];
+ }
+
+ public int getMarginLeft() {
+ return margins[3];
+ }
+
+ public int getBorderTop() {
+ return margins[0];
+ }
+
+ public int getBorderRight() {
+ return margins[1];
+ }
+
+ public int getBorderBottom() {
+ return margins[2];
+ }
+
+ public int getBorderLeft() {
+ return margins[3];
+ }
+
+ public int getPaddingTop() {
+ return paddings[0];
+ }
+
+ public int getPaddingRight() {
+ return paddings[1];
+ }
+
+ public int getPaddingBottom() {
+ return paddings[2];
+ }
+
+ public int getPaddingLeft() {
+ return paddings[3];
+ }
+
+ private void measure() {
+ boolean changed = isDirty;
+
+ Widget widget = paintable.getWidgetForPaintable();
+ ComputedStyle computedStyle = new ComputedStyle(widget.getElement());
+
+ int[] paddings = computedStyle.getPadding();
+ if (!changed && !Arrays.equals(this.paddings, paddings)) {
+ changed = true;
+ this.paddings = paddings;
+ }
+
+ int[] margins = computedStyle.getMargin();
+ if (!changed && !Arrays.equals(this.margins, margins)) {
+ changed = true;
+ this.margins = margins;
+ }
+
+ int[] borders = computedStyle.getBorder();
+ if (!changed && !Arrays.equals(this.borders, borders)) {
+ changed = true;
+ this.borders = borders;
+ }
+
+ int offsetHeight = widget.getOffsetHeight();
+ int marginHeight = sumHeights(margins);
+ setOuterHeight(offsetHeight + marginHeight);
+
+ int offsetWidth = widget.getOffsetWidth();
+ int marginWidth = sumWidths(margins);
+ setOuterWidth(offsetWidth + marginWidth);
+
+ // int i = 0;
+ for (Entry<Element, int[]> entry : dependencySizes.entrySet()) {
+ Element element = entry.getKey();
+ // int[] elementMargin = new ComputedStyle(element).getMargin();
+ int[] sizes = entry.getValue();
+
+ int elementWidth = element.getOffsetWidth();
+ // elementWidth += elementMargin[1] + elementMargin[3];
+ if (elementWidth != sizes[0]) {
+ // System.out.println(paintable.getId() + " dependency " + i
+ // + " width changed from " + sizes[0] + " to "
+ // + elementWidth);
+ sizes[0] = elementWidth;
+ changed = true;
+ }
+
+ int elementHeight = element.getOffsetHeight();
+ // Causes infinite loops as a negative margin based on the
+ // measured height is currently used for captions
+ // elementHeight += elementMargin[0] + elementMargin[1];
+ if (elementHeight != sizes[1]) {
+ // System.out.println(paintable.getId() + " dependency " + i
+ // + " height changed from " + sizes[1] + " to "
+ // + elementHeight);
+ sizes[1] = elementHeight;
+ changed = true;
+ }
+ // i++;
+ }
+
+ if (changed) {
+ setDirty(true);
+ }
+ }
}
public void doLayout(ApplicationConnection client) {
FastStringSet changed = FastStringSet.create();
for (VPaintableWidget paintableWidget : paintableWidgets) {
- Widget widget = paintableWidget.getWidgetForPaintable();
-
MeasureManager.MeasuredSize measuredSize = paintableWidget
.getMeasuredSize();
-
- measuredSize.setWidth(widget.getOffsetWidth());
- measuredSize.setHeight(widget.getOffsetHeight());
-
- boolean dirtyDependency = false;
- for (Entry<Element, int[]> entry : measuredSize.dependencySizes
- .entrySet()) {
- Element element = entry.getKey();
- int[] sizes = entry.getValue();
-
- int offsetWidth = element.getOffsetWidth();
- if (offsetWidth != sizes[0]) {
- sizes[0] = offsetWidth;
- dirtyDependency = true;
- }
-
- int offsetHeight = element.getOffsetHeight();
- if (offsetHeight != sizes[1]) {
- sizes[1] = offsetHeight;
- dirtyDependency = true;
- }
-
- }
-
- if (dirtyDependency) {
- measuredSize.setDirty(true);
- }
+ measuredSize.measure();
if (measuredSize.isDirty()) {
changed.add(paintableMap.getPid(paintableWidget));
import com.google.gwt.user.client.ui.ComplexPanel;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.RenderSpace;
import com.vaadin.terminal.gwt.client.VCaption;
import com.vaadin.terminal.gwt.client.VPaintableMap;
import com.vaadin.terminal.gwt.client.VPaintableWidget;
public static final String CLASSNAME = "v-orderedlayout";
- private static final int MARGIN_SIZE = 20;
-
final boolean isVertical;
ApplicationConnection client;
String id;
- private RenderSpace space;
-
ValueMap expandRatios;
ValueMap alignments;
Map<VPaintableWidget, VCaption> captions = new HashMap<VPaintableWidget, VCaption>();
- boolean spacing;
-
- VMarginInfo activeMarginsInfo;
+ final DivElement spacingMeasureElement;
protected VMeasuringOrderedLayout(String className, boolean isVertical) {
DivElement element = Document.get().createDivElement();
style.setOverflow(Overflow.HIDDEN);
style.setPosition(Position.RELATIVE);
+ spacingMeasureElement = Document.get().createDivElement();
+ Style spacingStyle = spacingMeasureElement.getStyle();
+ spacingStyle.setPosition(Position.ABSOLUTE);
+ getElement().appendChild(spacingMeasureElement);
+
setStyleName(className);
this.isVertical = isVertical;
}
add(widget, (com.google.gwt.user.client.Element) wrapper.cast());
}
- int getEndMarginInDirection(boolean isVertical) {
- if (isVertical) {
- return activeMarginsInfo.hasBottom() ? MARGIN_SIZE : 0;
- } else {
- return activeMarginsInfo.hasRight() ? MARGIN_SIZE : 0;
- }
- }
-
- int getStartMarginInDirection(boolean isVertical) {
- if (isVertical) {
- return activeMarginsInfo.hasTop() ? MARGIN_SIZE : 0;
- } else {
- return activeMarginsInfo.hasLeft() ? MARGIN_SIZE : 0;
- }
- }
-
- int getSpacingInDirection(boolean isVertical) {
- if (spacing) {
- return 20;
- } else {
- return 0;
- }
- }
-
AlignmentInfo getAlignment(VPaintableWidget child) {
String pid = VPaintableMap.get(client).getPid(child);
if (alignments.containsKey(pid)) {
wrapper.getStyle().setPosition(Position.ABSOLUTE);
getElement().appendChild(wrapper);
add(widget, wrapper);
+ widget.getElement().getStyle()
+ .setProperty("MozBoxSizing", "border-box");
+ widget.getElement().getStyle().setProperty("boxSizing", "border-box");
}
void addCaption(VCaption caption, Widget widget) {
adopt(caption);
}
- void remove(VCaption caption) {
- remove(caption);
+ private void togglePrefixedStyleName(String name, boolean enabled) {
+ if (enabled) {
+ addStyleName(CLASSNAME + name);
+ } else {
+ removeStyleName(CLASSNAME + name);
+ }
+ }
+
+ void updateMarginStyleNames(VMarginInfo marginInfo) {
+ togglePrefixedStyleName("-margin-top", marginInfo.hasTop());
+ togglePrefixedStyleName("-margin-right", marginInfo.hasRight());
+ togglePrefixedStyleName("-margin-bottom", marginInfo.hasBottom());
+ togglePrefixedStyleName("-margin-left", marginInfo.hasLeft());
+ }
+
+ void updateSpacingStyleName(boolean spacingEnabled) {
+ if (spacingEnabled) {
+ spacingMeasureElement.addClassName(CLASSNAME + "-spacing-on");
+ spacingMeasureElement.removeClassName(CLASSNAME + "-spacing-off");
+ } else {
+ spacingMeasureElement.removeClassName(CLASSNAME + "-spacing-on");
+ spacingMeasureElement.addClassName(CLASSNAME + "-spacing-off");
+ }
}
}
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.CalculatingLayout;
import com.vaadin.terminal.gwt.client.MeasureManager;
+import com.vaadin.terminal.gwt.client.MeasureManager.MeasuredSize;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.VCaption;
import com.vaadin.terminal.gwt.client.VPaintableMap;
public abstract class VMeasuringOrderedLayoutPaintable extends
VAbstractPaintableWidgetContainer implements CalculatingLayout {
+ public VMeasuringOrderedLayoutPaintable() {
+ getMeasuredSize().registerDependency(
+ getWidgetForPaintable().spacingMeasureElement);
+ }
+
public void updateCaption(VPaintableWidget component, UIDL uidl) {
if (VCaption.isNeeded(uidl)) {
VCaption caption = getWidgetForPaintable().captions.get(component);
return;
}
- long start = System.currentTimeMillis();
- // long childTime = 0;
-
HashSet<Widget> previousChildren = new HashSet<Widget>();
for (Widget child : getWidgetForPaintable()) {
if (!(child instanceof VCaption)) {
}
int bitMask = uidl.getIntAttribute("margins");
- if (getWidgetForPaintable().activeMarginsInfo == null
- || getWidgetForPaintable().activeMarginsInfo.getBitMask() != bitMask) {
- getWidgetForPaintable().activeMarginsInfo = new VMarginInfo(bitMask);
- }
+ getWidgetForPaintable()
+ .updateMarginStyleNames(new VMarginInfo(bitMask));
+
+ getWidgetForPaintable().updateSpacingStyleName(
+ uidl.getBooleanAttribute("spacing"));
- getWidgetForPaintable().spacing = uidl.getBooleanAttribute("spacing");
getWidgetForPaintable().expandRatios = uidl
.getMapAttribute("expandRatios");
getWidgetForPaintable().alignments = uidl.getMapAttribute("alignments");
if (caption == null) {
return 0;
} else {
- return getMeasuredSize().getDependencyWidth(caption.getElement());
+ return getMeasuredSize().getDependencyOuterWidth(
+ caption.getElement());
}
}
private int getCaptionHeight(VPaintableWidget child) {
VCaption caption = getWidgetForPaintable().captions.get(child);
if (caption != null) {
- int captionHeight = getMeasuredSize().getDependencyHeight(
+ int captionHeight = getMeasuredSize().getDependencyOuterHeight(
caption.getElement());
caption.getElement().getStyle()
}
}
- private static boolean isRelativeInDirection(Widget widget,
+ private static boolean isRelativeInDirection(VPaintableWidget paintable,
boolean isVertical) {
- String dimension = getDimensionInDirection(widget, isVertical);
- return dimension != null && dimension.endsWith("%");
+ if (isVertical) {
+ return paintable.isRelativeHeight();
+ } else {
+ return paintable.isRelativeWidth();
+ }
}
- private static String getDimensionInDirection(Widget widget,
- boolean vertical) {
- com.google.gwt.user.client.Element element = widget.getElement();
- Style style = element.getStyle();
- if (vertical) {
- return style.getHeight();
+ private int getSizeForInnerSize(int size, boolean isVertical) {
+ MeasuredSize measuredSize = getMeasuredSize();
+ if (isVertical) {
+ return size + measuredSize.getBorderHeight()
+ + measuredSize.getPaddingHeight();
} else {
- return style.getWidth();
+ return size + measuredSize.getBorderWidth()
+ + measuredSize.getPaddingWidth();
}
}
return isVertical ? "top" : "left";
}
- private static String getMinPropertyName(boolean isVertical) {
- return isVertical ? "minHeight" : "minWidth";
- }
-
- private static boolean isUndefinedInDirection(Widget widget,
+ private static boolean isUndefinedInDirection(VPaintableWidget paintable,
boolean isVertical) {
- String dimension = getDimensionInDirection(widget, isVertical);
- return dimension == null || dimension.length() == 0;
+ if (isVertical) {
+ return paintable.isUndefinedHeight();
+ } else {
+ return paintable.isUndefinedWidth();
+ }
}
- private int getMeasuredInDirection(VPaintableWidget paintable,
+ private static int getOuterSizeInDirection(VPaintableWidget paintable,
boolean isVertical) {
MeasureManager.MeasuredSize measuredSize = paintable.getMeasuredSize();
if (isVertical) {
- return measuredSize.getHeight();
+ return measuredSize.getOuterHeight();
} else {
- return measuredSize.getWidth();
+ return measuredSize.getOuterWidth();
+ }
+ }
+
+ private int getInnerSizeInDirection(boolean isVertical) {
+ if (isVertical) {
+ return getMeasuredSize().getInnerHeight();
+ } else {
+ return getMeasuredSize().getInnerWidth();
}
}
captionAllocation = 0;
}
- if (!isRelativeInDirection(widget,
+ if (!isRelativeInDirection(child,
getWidgetForPaintable().isVertical)) {
- totalAllocated += getMeasuredInDirection(child,
- getWidgetForPaintable().isVertical) + captionAllocation;
+ int childSize = getOuterSizeInDirection(child,
+ getWidgetForPaintable().isVertical);
+ if (getWidgetForPaintable().isVertical) {
+ childSize += captionAllocation;
+ } else {
+ childSize = Math.max(childSize, getCaptionWidth(child));
+ }
+ totalAllocated += childSize;
}
}
- int startMargin = getWidgetForPaintable().getStartMarginInDirection(
- getWidgetForPaintable().isVertical);
- int totalMargins = startMargin
- + getWidgetForPaintable().getEndMarginInDirection(
- getWidgetForPaintable().isVertical);
- totalAllocated += totalMargins
- + (getWidgetForPaintable().getSpacingInDirection(
- getWidgetForPaintable().isVertical) * (children.size() - 1));
+ totalAllocated += getSpacingInDirection(getWidgetForPaintable().isVertical)
+ * (children.size() - 1);
Style ownStyle = getWidgetForPaintable().getElement().getStyle();
double ownSize;
- if (isUndefinedInDirection(getWidgetForPaintable(),
- getWidgetForPaintable().isVertical)) {
+ if (isUndefinedInDirection(this, getWidgetForPaintable().isVertical)) {
ownSize = totalAllocated;
- ownStyle.setProperty(
- getMinPropertyName(getWidgetForPaintable().isVertical),
- totalAllocated, Unit.PX);
+ ownStyle.setPropertyPx(
+ getSizeProperty(getWidgetForPaintable().isVertical),
+ getSizeForInnerSize(totalAllocated,
+ getWidgetForPaintable().isVertical));
} else {
- ownSize = getMeasuredInDirection(this,
- getWidgetForPaintable().isVertical);
- ownStyle.clearProperty(getMinPropertyName(getWidgetForPaintable().isVertical));
+ ownSize = getInnerSizeInDirection(getWidgetForPaintable().isVertical);
+ ownStyle.setProperty(
+ getSizeProperty(getWidgetForPaintable().isVertical),
+ getDefinedSize(getWidgetForPaintable().isVertical));
}
double unallocatedSpace = Math.max(0, ownSize - totalAllocated);
- double currentLocation = startMargin;
+ double currentLocation = getStartPadding(getWidgetForPaintable().isVertical);
for (VPaintableWidget child : children) {
Widget widget = child.getWidgetForPaintable();
Element wrapper = getWidgetForPaintable().getWrapper(widget);
double extraPixels = unallocatedSpace * childExpandRatio;
- boolean relative = isRelativeInDirection(widget,
+ boolean relative = isRelativeInDirection(child,
getWidgetForPaintable().isVertical);
- double size = getMeasuredInDirection(child,
+ double size = getOuterSizeInDirection(child,
getWidgetForPaintable().isVertical);
int captionHeight = getCaptionHeight(child);
startPosition, Unit.PX);
currentLocation += allocatedSpace
- + getWidgetForPaintable().getSpacingInDirection(
- getWidgetForPaintable().isVertical);
+ + getSpacingInDirection(getWidgetForPaintable().isVertical);
+ }
+ }
+
+ private int getSpacingInDirection(boolean isVertical) {
+ if (isVertical) {
+ return getMeasuredSize().getDependencyOuterHeight(
+ getWidgetForPaintable().spacingMeasureElement);
+ } else {
+ return getMeasuredSize().getDependencyOuterWidth(
+ getWidgetForPaintable().spacingMeasureElement);
}
}
captionAllocation = 0;
}
- if (!isRelativeInDirection(widget,
+ if (!isRelativeInDirection(child,
!getWidgetForPaintable().isVertical)) {
- int childSize = getMeasuredInDirection(child,
+ int childSize = getOuterSizeInDirection(child,
!getWidgetForPaintable().isVertical)
+ captionAllocation;
maxSize = Math.max(maxSize, childSize);
}
}
- int startMargin = getWidgetForPaintable().getStartMarginInDirection(
- !getWidgetForPaintable().isVertical);
- int totalMargins = startMargin
- + getWidgetForPaintable().getEndMarginInDirection(
- !getWidgetForPaintable().isVertical);
-
double availableSpace;
Style ownStyle = getWidgetForPaintable().getElement().getStyle();
- if (isUndefinedInDirection(getWidgetForPaintable(),
- !getWidgetForPaintable().isVertical)) {
- ownStyle.setProperty(
- getMinPropertyName(!getWidgetForPaintable().isVertical),
- maxSize + totalMargins, Unit.PX);
+ if (isUndefinedInDirection(this, !getWidgetForPaintable().isVertical)) {
+ ownStyle.setPropertyPx(
+ getSizeProperty(!getWidgetForPaintable().isVertical),
+ getSizeForInnerSize(maxSize,
+ !getWidgetForPaintable().isVertical));
+
availableSpace = maxSize;
} else {
- ownStyle.clearProperty(getMinPropertyName(!getWidgetForPaintable().isVertical));
- availableSpace = getMeasuredInDirection(this,
- !getWidgetForPaintable().isVertical) - totalMargins;
+ ownStyle.setProperty(
+ getSizeProperty(!getWidgetForPaintable().isVertical),
+ getDefinedSize(!getWidgetForPaintable().isVertical));
+ availableSpace = getInnerSizeInDirection(!getWidgetForPaintable().isVertical);
}
for (VPaintableWidget child : children) {
Element wrapper = getWidgetForPaintable().getWrapper(widget);
Style wrapperStyle = wrapper.getStyle();
- boolean relative = isRelativeInDirection(widget,
+ boolean relative = isRelativeInDirection(child,
!getWidgetForPaintable().isVertical);
int captionHeight = getCaptionHeight(child);
- double allocatedSize = getMeasuredInDirection(child,
+ double allocatedSize = getOuterSizeInDirection(child,
!getWidgetForPaintable().isVertical);
if (!getWidgetForPaintable().isVertical) {
allocatedSize += captionHeight;
int alignment = getAlignmentInDirection(getWidgetForPaintable()
.getAlignment(child), !getWidgetForPaintable().isVertical);
- double startPosition = startMargin;
+ double startPosition = getStartPadding(getWidgetForPaintable().isVertical);
if (alignment == 0) {
startPosition += (availableSpace - allocatedSize) / 2;
// Centered
}
}
+ private String getDefinedSize(boolean isVertical) {
+ if (isVertical) {
+ return getDefinedHeight();
+ } else {
+ return getDefinedWidth();
+ }
+ }
+
+ private int getStartPadding(boolean isVertical) {
+ if (isVertical) {
+ return getMeasuredSize().getPaddingTop();
+ } else {
+ return getMeasuredSize().getPaddingLeft();
+ }
+ }
+
public void updateHorizontalSizes() {
if (getWidgetForPaintable().isVertical) {
layoutSecondaryDirection();