*/
package com.vaadin.terminal.gwt.client.ui;
-import java.util.HashMap;
-import java.util.Map;
-
import com.google.gwt.dom.client.DivElement;
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.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.Widget;
import com.vaadin.terminal.gwt.client.VCaption;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.ValueMap;
+import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot;
public class VMeasuringOrderedLayout extends ComplexPanel {
- public static final String CLASSNAME = "v-orderedlayout";
-
final boolean isVertical;
- ValueMap expandRatios;
-
- ValueMap alignments;
-
- Map<VPaintableWidget, VCaption> captions = new HashMap<VPaintableWidget, VCaption>();
-
final DivElement spacingMeasureElement;
protected VMeasuringOrderedLayout(String className, boolean isVertical) {
this.isVertical = isVertical;
}
- static Element getWrapper(Widget widget) {
- return widget.getElement().getParentElement();
- }
+ public void addSlot(VLayoutSlot layoutSlot) {
+ Widget widget = layoutSlot.getWidget();
+ Element wrapperElement = layoutSlot.getWrapperElement();
- private void add(Widget widget, DivElement wrapper) {
- add(widget, (com.google.gwt.user.client.Element) wrapper.cast());
- }
+ getElement().appendChild(wrapperElement);
+ add(widget, wrapperElement);
- void addChildWidget(Widget widget) {
- DivElement wrapper = Document.get().createDivElement();
- 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) {
- Element wrapper = getWrapper(widget);
-
- // Logical attach.
- getChildren().add(caption);
-
- // Physical attach.
- DOM.insertBefore((com.google.gwt.user.client.Element) wrapper.cast(),
- caption.getElement(), widget.getElement());
-
- // Adopt.
- adopt(caption);
+ widget.setLayoutData(layoutSlot);
}
private void togglePrefixedStyleName(String name, boolean enabled) {
if (enabled) {
- addStyleName(CLASSNAME + name);
+ addStyleDependentName(name);
} else {
- removeStyleName(CLASSNAME + name);
+ removeStyleDependentName(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());
+ togglePrefixedStyleName("margin-top", marginInfo.hasTop());
+ togglePrefixedStyleName("margin-right", marginInfo.hasRight());
+ togglePrefixedStyleName("margin-bottom", marginInfo.hasBottom());
+ togglePrefixedStyleName("margin-left", marginInfo.hasLeft());
}
void updateSpacingStyleName(boolean spacingEnabled) {
+ String styleName = getStyleName();
if (spacingEnabled) {
- spacingMeasureElement.addClassName(CLASSNAME + "-spacing-on");
- spacingMeasureElement.removeClassName(CLASSNAME + "-spacing-off");
+ spacingMeasureElement.addClassName(styleName + "-spacing-on");
+ spacingMeasureElement.removeClassName(styleName + "-spacing-off");
} else {
- spacingMeasureElement.removeClassName(CLASSNAME + "-spacing-on");
- spacingMeasureElement.addClassName(CLASSNAME + "-spacing-off");
+ spacingMeasureElement.removeClassName(styleName + "-spacing-on");
+ spacingMeasureElement.addClassName(styleName + "-spacing-off");
+ }
+ }
+
+ public void removeSlot(VLayoutSlot slot) {
+ VCaption caption = slot.getCaption();
+ if (caption != null) {
+ remove(caption);
+ }
+
+ remove(slot.getWidget());
+ getElement().removeChild(slot.getWrapperElement());
+ }
+
+ public VLayoutSlot getSlotForChild(Widget widget) {
+ return (VLayoutSlot) widget.getLayoutData();
+ }
+
+ public void setCaption(Widget child, VCaption caption) {
+ VLayoutSlot slot = getSlotForChild(child);
+
+ if (caption != null) {
+ // Logical attach.
+ getChildren().add(caption);
+ }
+
+ // Physical attach if not null, also removes old caption
+ slot.setCaption(caption);
+
+ if (caption != null) {
+ // Adopt.
+ adopt(caption);
+ }
+ }
+
+ public int layoutPrimaryDirection(int spacingSize, int allocatedSize,
+ int startPadding) {
+ int actuallyAllocated = 0;
+ double totalExpand = 0;
+
+ int childCount = 0;
+ for (Widget child : this) {
+ if (child instanceof VCaption) {
+ continue;
+ }
+ childCount++;
+
+ VLayoutSlot slot = getSlotForChild(child);
+ totalExpand += slot.getExpandRatio();
+
+ if (!slot.isRelativeInDirection(isVertical)) {
+ actuallyAllocated += slot.getUsedSizeInDirection(isVertical);
+ }
+ }
+
+ actuallyAllocated += spacingSize * (childCount - 1);
+
+ if (allocatedSize == -1) {
+ allocatedSize = actuallyAllocated;
+ }
+
+ double unallocatedSpace = Math
+ .max(0, allocatedSize - actuallyAllocated);
+
+ double currentLocation = startPadding;
+
+ for (Widget child : this) {
+ if (child instanceof VCaption) {
+ continue;
+ }
+
+ VLayoutSlot slot = getSlotForChild(child);
+
+ double childExpandRatio;
+ if (totalExpand == 0) {
+ childExpandRatio = 1d / childCount;
+ } else {
+ childExpandRatio = slot.getExpandRatio() / totalExpand;
+ }
+
+ double extraPixels = unallocatedSpace * childExpandRatio;
+ double allocatedSpace = extraPixels;
+ if (!slot.isRelativeInDirection(isVertical)) {
+ allocatedSpace += slot.getUsedSizeInDirection(isVertical);
+ }
+
+ slot.positionInDirection(currentLocation, allocatedSpace,
+ isVertical);
+ currentLocation += allocatedSpace + spacingSize;
+ }
+
+ return allocatedSize;
+ }
+
+ public int layoutSecondaryDirection(int allocatedSize, int startPadding) {
+ int maxSize = 0;
+ for (Widget child : this) {
+ if (child instanceof VCaption) {
+ continue;
+ }
+
+ VLayoutSlot slot = getSlotForChild(child);
+ if (!slot.isRelativeInDirection(!isVertical)) {
+ maxSize = Math.max(maxSize,
+ slot.getUsedSizeInDirection(!isVertical));
+ }
}
+
+ if (allocatedSize == -1) {
+ allocatedSize = maxSize;
+ }
+
+ for (Widget child : this) {
+ if (child instanceof VCaption) {
+ continue;
+ }
+
+ VLayoutSlot slot = getSlotForChild(child);
+ slot.positionInDirection(startPadding, allocatedSize, !isVertical);
+ }
+
+ return allocatedSize;
}
}
package com.vaadin.terminal.gwt.client.ui;
-import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
-import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
-import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.CalculatingLayout;
import com.vaadin.terminal.gwt.client.VCaption;
import com.vaadin.terminal.gwt.client.VPaintableMap;
import com.vaadin.terminal.gwt.client.VPaintableWidget;
+import com.vaadin.terminal.gwt.client.ValueMap;
+import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot;
+import com.vaadin.terminal.gwt.client.ui.layout.VPaintableLayoutSlot;
public abstract class VMeasuringOrderedLayoutPaintable extends
VAbstractPaintableWidgetContainer implements CalculatingLayout {
}
public void updateCaption(VPaintableWidget component, UIDL uidl) {
+ VMeasuringOrderedLayout layout = getWidgetForPaintable();
if (VCaption.isNeeded(uidl)) {
- VCaption caption = getWidgetForPaintable().captions.get(component);
+ VLayoutSlot layoutSlot = layout.getSlotForChild(component
+ .getWidgetForPaintable());
+ VCaption caption = layoutSlot.getCaption();
if (caption == null) {
caption = new VCaption(component, getConnection());
Widget widget = component.getWidgetForPaintable();
- getWidgetForPaintable().addCaption(caption, widget);
- getWidgetForPaintable().captions.put(component, caption);
-
- getMeasuredSize().registerDependency(caption.getElement());
+ layout.setCaption(widget, caption);
}
caption.updateCaption(uidl);
} else {
- VCaption removedCaption = getWidgetForPaintable().captions
- .remove(component);
- if (removedCaption != null) {
- getWidgetForPaintable().remove(removedCaption);
- getMeasuredSize().deRegisterDependency(
- removedCaption.getElement());
- }
+ layout.setCaption(component.getWidgetForPaintable(), null);
}
}
HashSet<VPaintableWidget> previousChildren = new HashSet<VPaintableWidget>(
getChildren());
+ VMeasuringOrderedLayout layout = getWidgetForPaintable();
+
+ ValueMap expandRatios = uidl.getMapAttribute("expandRatios");
+ ValueMap alignments = uidl.getMapAttribute("alignments");
+
// TODO Support reordering elements!
for (final Iterator<Object> it = uidl.getChildIterator(); it.hasNext();) {
final UIDL childUIDL = (UIDL) it.next();
final VPaintableWidget child = client.getPaintable(childUIDL);
Widget widget = child.getWidgetForPaintable();
- if (widget.getParent() != getWidgetForPaintable()) {
- getWidgetForPaintable().addChildWidget(widget);
+ VLayoutSlot slot = layout.getSlotForChild(widget);
+
+ if (widget.getParent() != layout) {
+ slot = new VPaintableLayoutSlot(child);
+ layout.addSlot(slot);
+ }
+
+ String pid = child.getId();
+
+ AlignmentInfo alignment;
+ if (alignments.containsKey(pid)) {
+ alignment = new AlignmentInfo(alignments.getInt(pid));
+ } else {
+ alignment = AlignmentInfo.TOP_LEFT;
}
+ slot.setAlignment(alignment);
+
+ double expandRatio;
+ if (expandRatios.containsKey(pid)) {
+ expandRatio = expandRatios.getRawNumber(pid);
+ } else {
+ expandRatio = 0;
+ }
+ slot.setExpandRatio(expandRatio);
if (!childUIDL.getBooleanAttribute("cached")) {
child.updateFromUIDL(childUIDL, client);
child.getMeasuredSize().setDirty(true);
}
- // TODO Update alignments and expand ratios
previousChildren.remove(child);
}
for (VPaintableWidget child : previousChildren) {
Widget widget = child.getWidgetForPaintable();
- Element wrapper = VMeasuringOrderedLayout.getWrapper(widget);
- VCaption caption = getWidgetForPaintable().captions.remove(widget);
- if (caption != null) {
- getWidgetForPaintable().remove(caption);
- }
- getWidgetForPaintable().remove(widget);
- // Remove the wrapper
- getWidgetForPaintable().getElement().removeChild(wrapper);
+ layout.removeSlot(layout.getSlotForChild(widget));
VPaintableMap vPaintableMap = VPaintableMap.get(client);
vPaintableMap.unregisterPaintable(child);
}
int bitMask = uidl.getIntAttribute("margins");
- getWidgetForPaintable()
- .updateMarginStyleNames(new VMarginInfo(bitMask));
+ layout.updateMarginStyleNames(new VMarginInfo(bitMask));
- getWidgetForPaintable().updateSpacingStyleName(
- uidl.getBooleanAttribute("spacing"));
+ layout.updateSpacingStyleName(uidl.getBooleanAttribute("spacing"));
- getWidgetForPaintable().expandRatios = uidl
- .getMapAttribute("expandRatios");
- getWidgetForPaintable().alignments = uidl.getMapAttribute("alignments");
getMeasuredSize().setDirty(true);
}
- private int getCaptionWidth(VPaintableWidget child) {
- VCaption caption = getWidgetForPaintable().captions.get(child);
- if (caption == null) {
- return 0;
- } else {
- return getMeasuredSize().getDependencyOuterWidth(
- caption.getElement());
- }
- }
-
- private int getCaptionHeight(VPaintableWidget child) {
- VCaption caption = getWidgetForPaintable().captions.get(child);
- if (caption != null) {
- int captionHeight = getMeasuredSize().getDependencyOuterHeight(
- caption.getElement());
-
- caption.getElement().getStyle()
- .setMarginTop(-captionHeight, Unit.PX);
- return captionHeight;
- } else {
- return 0;
- }
- }
-
- private static boolean isRelativeInDirection(VPaintableWidget paintable,
- boolean isVertical) {
- if (isVertical) {
- return paintable.isRelativeHeight();
- } else {
- return paintable.isRelativeWidth();
- }
- }
-
private int getSizeForInnerSize(int size, boolean isVertical) {
MeasuredSize measuredSize = getMeasuredSize();
if (isVertical) {
return isVertical ? "height" : "width";
}
- private static String getStartProperty(boolean isVertical) {
- return isVertical ? "top" : "left";
- }
-
- private static boolean isUndefinedInDirection(VPaintableWidget paintable,
- boolean isVertical) {
+ private boolean isUndefinedInDirection(boolean isVertical) {
if (isVertical) {
- return paintable.isUndefinedHeight();
+ return isUndefinedHeight();
} else {
- return paintable.isUndefinedWidth();
- }
- }
-
- private static int getOuterSizeInDirection(VPaintableWidget paintable,
- boolean isVertical) {
- MeasuredSize measuredSize = paintable.getMeasuredSize();
- if (isVertical) {
- return measuredSize.getOuterHeight();
- } else {
- return measuredSize.getOuterWidth();
+ return isUndefinedWidth();
}
}
}
}
- private static int getAlignmentInDirection(AlignmentInfo alignment,
- boolean isVertical) {
- if (alignment == null) {
- return -1;
- }
- if (isVertical) {
- if (alignment.isTop()) {
- return -1;
- } else if (alignment.isBottom()) {
- return 1;
- } else {
- return 0;
- }
- } else {
- if (alignment.isLeft()) {
- return -1;
- } else if (alignment.isRight()) {
- return 1;
- } else {
- return 0;
- }
- }
- }
-
private void layoutPrimaryDirection() {
- Collection<VPaintableWidget> children = getChildren();
-
- // First pass - get total expand ratio and allocated size
- int totalAllocated = 0;
- double totalExpand = 0;
- for (VPaintableWidget child : children) {
- Widget widget = child.getWidgetForPaintable();
+ VMeasuringOrderedLayout layout = getWidgetForPaintable();
+ boolean isVertical = layout.isVertical;
+ boolean isUndefined = isUndefinedInDirection(isVertical);
- totalExpand += getExpandRatio(child);
+ int startPadding = getStartPadding(isVertical);
+ int spacingSize = getSpacingInDirection(isVertical);
+ int allocatedSize;
- int captionAllocation;
- if (getWidgetForPaintable().isVertical) {
- captionAllocation = getCaptionHeight(child);
- getWidgetForPaintable();
- VMeasuringOrderedLayout.getWrapper(widget).getStyle()
- .setPaddingTop(captionAllocation, Unit.PX);
- } else {
- captionAllocation = 0;
- }
-
- if (!isRelativeInDirection(child,
- getWidgetForPaintable().isVertical)) {
- int childSize = getOuterSizeInDirection(child,
- getWidgetForPaintable().isVertical);
- if (getWidgetForPaintable().isVertical) {
- childSize += captionAllocation;
- } else {
- childSize = Math.max(childSize, getCaptionWidth(child));
- }
- totalAllocated += childSize;
- }
+ if (isUndefined) {
+ allocatedSize = -1;
+ } else {
+ allocatedSize = getInnerSizeInDirection(isVertical);
}
- totalAllocated += getSpacingInDirection(getWidgetForPaintable().isVertical)
- * (children.size() - 1);
+ allocatedSize = layout.layoutPrimaryDirection(spacingSize,
+ allocatedSize, startPadding);
Style ownStyle = getWidgetForPaintable().getElement().getStyle();
- double ownSize;
- if (isUndefinedInDirection(this, getWidgetForPaintable().isVertical)) {
- ownSize = totalAllocated;
- ownStyle.setPropertyPx(
- getSizeProperty(getWidgetForPaintable().isVertical),
- getSizeForInnerSize(totalAllocated,
- getWidgetForPaintable().isVertical));
+ if (isUndefined) {
+ ownStyle.setPropertyPx(getSizeProperty(isVertical),
+ getSizeForInnerSize(allocatedSize, isVertical));
} else {
- ownSize = getInnerSizeInDirection(getWidgetForPaintable().isVertical);
- ownStyle.setProperty(
- getSizeProperty(getWidgetForPaintable().isVertical),
- getDefinedSize(getWidgetForPaintable().isVertical));
- }
-
- double unallocatedSpace = Math.max(0, ownSize - totalAllocated);
-
- double currentLocation = getStartPadding(getWidgetForPaintable().isVertical);
- for (VPaintableWidget child : children) {
- Widget widget = child.getWidgetForPaintable();
- getWidgetForPaintable();
- Element wrapper = VMeasuringOrderedLayout.getWrapper(widget);
- Style wrapperStyle = wrapper.getStyle();
-
- double childExpandRatio;
- if (totalExpand == 0) {
- childExpandRatio = 1d / children.size();
- } else {
- childExpandRatio = getExpandRatio(child) / totalExpand;
- }
-
- double extraPixels = unallocatedSpace * childExpandRatio;
-
- boolean relative = isRelativeInDirection(child,
- getWidgetForPaintable().isVertical);
-
- double size = getOuterSizeInDirection(child,
- getWidgetForPaintable().isVertical);
- int captionHeight = getCaptionHeight(child);
-
- if (getWidgetForPaintable().isVertical) {
- size += captionHeight;
- } else if (!relative) {
- size = Math.max(size, getCaptionWidth(child));
- }
-
- double allocatedSpace = extraPixels;
- if (!relative) {
- allocatedSpace += size;
- }
-
- int alignment = getAlignmentInDirection(getAlignment(child),
- getWidgetForPaintable().isVertical);
-
- if (relative) {
- double captionReservation = getWidgetForPaintable().isVertical ? captionHeight
- : 0;
- wrapperStyle.setProperty(
- getSizeProperty(getWidgetForPaintable().isVertical),
- allocatedSpace - captionReservation, Unit.PX);
- } else {
- wrapperStyle
- .clearProperty(getSizeProperty(getWidgetForPaintable().isVertical));
- }
-
- double startPosition = currentLocation;
- if (alignment == 0) {
- // Centered
- startPosition += (allocatedSpace - size) / 2;
- } else if (alignment == 1) {
- // Right or bottom
- startPosition += allocatedSpace - size;
- }
-
- wrapperStyle.setProperty(
- getStartProperty(getWidgetForPaintable().isVertical),
- startPosition, Unit.PX);
-
- currentLocation += allocatedSpace
- + getSpacingInDirection(getWidgetForPaintable().isVertical);
+ ownStyle.setProperty(getSizeProperty(isVertical),
+ getDefinedSize(isVertical));
}
}
}
private void layoutSecondaryDirection() {
- Collection<VPaintableWidget> children = getChildren();
+ VMeasuringOrderedLayout layout = getWidgetForPaintable();
+ boolean isVertical = layout.isVertical;
+ boolean isUndefined = isUndefinedInDirection(!isVertical);
- int maxSize = 0;
- for (VPaintableWidget child : children) {
- Widget widget = child.getWidgetForPaintable();
-
- int captionAllocation;
- if (!getWidgetForPaintable().isVertical) {
- captionAllocation = getCaptionHeight(child);
- getWidgetForPaintable();
- VMeasuringOrderedLayout.getWrapper(widget).getStyle()
- .setPaddingTop(captionAllocation, Unit.PX);
- } else {
- captionAllocation = 0;
- }
+ int startPadding = getStartPadding(!isVertical);
- if (!isRelativeInDirection(child,
- !getWidgetForPaintable().isVertical)) {
- int childSize = getOuterSizeInDirection(child,
- !getWidgetForPaintable().isVertical)
- + captionAllocation;
- maxSize = Math.max(maxSize, childSize);
- }
+ int allocatedSize;
+ if (isUndefined) {
+ allocatedSize = -1;
+ } else {
+ allocatedSize = getInnerSizeInDirection(!isVertical);
}
- double availableSpace;
+ allocatedSize = layout.layoutSecondaryDirection(allocatedSize,
+ startPadding);
+
Style ownStyle = getWidgetForPaintable().getElement().getStyle();
- if (isUndefinedInDirection(this, !getWidgetForPaintable().isVertical)) {
+ if (isUndefined) {
ownStyle.setPropertyPx(
getSizeProperty(!getWidgetForPaintable().isVertical),
- getSizeForInnerSize(maxSize,
+ getSizeForInnerSize(allocatedSize,
!getWidgetForPaintable().isVertical));
-
- availableSpace = maxSize;
} else {
ownStyle.setProperty(
getSizeProperty(!getWidgetForPaintable().isVertical),
getDefinedSize(!getWidgetForPaintable().isVertical));
- availableSpace = getInnerSizeInDirection(!getWidgetForPaintable().isVertical);
- }
-
- for (VPaintableWidget child : children) {
- Widget widget = child.getWidgetForPaintable();
- getWidgetForPaintable();
- Element wrapper = VMeasuringOrderedLayout.getWrapper(widget);
- Style wrapperStyle = wrapper.getStyle();
-
- boolean relative = isRelativeInDirection(child,
- !getWidgetForPaintable().isVertical);
-
- int captionHeight = getCaptionHeight(child);
-
- double allocatedSize = getOuterSizeInDirection(child,
- !getWidgetForPaintable().isVertical);
- if (!getWidgetForPaintable().isVertical) {
- allocatedSize += captionHeight;
- } else if (!relative) {
- allocatedSize = Math.max(allocatedSize, getCaptionWidth(child));
- }
-
- int alignment = getAlignmentInDirection(getAlignment(child),
- !getWidgetForPaintable().isVertical);
-
- double startPosition = getStartPadding(getWidgetForPaintable().isVertical);
- if (alignment == 0) {
- startPosition += (availableSpace - allocatedSize) / 2;
- // Centered
- } else if (alignment == 1) {
- // Right or bottom
- startPosition += (availableSpace - allocatedSize);
- }
-
- wrapperStyle.setProperty(
- getStartProperty(!getWidgetForPaintable().isVertical),
- startPosition, Unit.PX);
-
- if (relative) {
- double captionReservation = !getWidgetForPaintable().isVertical ? captionHeight
- : 0;
- wrapperStyle.setProperty(
- getSizeProperty(!getWidgetForPaintable().isVertical),
- availableSpace - captionReservation, Unit.PX);
- } else {
- wrapperStyle
- .clearProperty(getSizeProperty(!getWidgetForPaintable().isVertical));
- }
}
}
}
}
- AlignmentInfo getAlignment(VPaintableWidget child) {
- String pid = child.getId();
- if (getWidgetForPaintable().alignments.containsKey(pid)) {
- return new AlignmentInfo(
- getWidgetForPaintable().alignments.getInt(pid));
- } else {
- return AlignmentInfo.TOP_LEFT;
- }
- }
-
- double getExpandRatio(VPaintableWidget child) {
- String pid = child.getId();
- if (getWidgetForPaintable().expandRatios.containsKey(pid)) {
- return getWidgetForPaintable().expandRatios.getRawNumber(pid);
- } else {
- return 0;
- }
- }
}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.layout;
+
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Position;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.VCaption;
+import com.vaadin.terminal.gwt.client.ui.AlignmentInfo;
+
+public abstract class VLayoutSlot {
+
+ private final Element wrapper = Document.get().createDivElement().cast();
+
+ private AlignmentInfo alignment;
+ private VCaption caption;
+ private final Widget widget;
+
+ private double expandRatio;
+
+ public VLayoutSlot(Widget widget) {
+ this.widget = widget;
+
+ wrapper.getStyle().setPosition(Position.ABSOLUTE);
+
+ // TODO set box sizing in CSS
+ Style widgetStyle = widget.getElement().getStyle();
+ widgetStyle.setProperty("MozBoxSizing", "border-box");
+ widgetStyle.setProperty("boxSizing", "border-box");
+ }
+
+ public VCaption getCaption() {
+ return caption;
+ }
+
+ public void setCaption(VCaption caption) {
+ if (this.caption != null) {
+ this.caption.removeFromParent();
+ }
+ this.caption = caption;
+ if (caption != null) {
+ // Physical attach.
+ DOM.insertBefore(wrapper, caption.getElement(), widget.getElement());
+ caption.getElement().getStyle().setPosition(Position.ABSOLUTE);
+ }
+ }
+
+ public AlignmentInfo getAlignment() {
+ return alignment;
+ }
+
+ public Widget getWidget() {
+ return widget;
+ }
+
+ public void setAlignment(AlignmentInfo alignment) {
+ this.alignment = alignment;
+ }
+
+ public void positionHorizontally(double currentLocation,
+ double allocatedSpace) {
+ Style style = wrapper.getStyle();
+
+ if (isRelativeWidth()) {
+ style.setWidth(allocatedSpace, Unit.PX);
+ } else {
+ style.setWidth(getUsedWidth(), Unit.PX);
+ }
+
+ VCaption caption = getCaption();
+ Style captionStyle = caption != null ? caption.getElement().getStyle()
+ : null;
+
+ AlignmentInfo alignment = getAlignment();
+ if (!alignment.isLeft()) {
+ double usedWidth = getWidgetWidth();
+ if (alignment.isHorizontalCenter()) {
+ currentLocation += (allocatedSpace - usedWidth) / 2d;
+ if (captionStyle != null) {
+ double captionWidth = getCaptionWidth();
+ captionStyle.setLeft(usedWidth / 2 - (captionWidth / 2),
+ Unit.PX);
+ captionStyle.clearRight();
+ }
+ } else {
+ currentLocation += (allocatedSpace - usedWidth);
+ if (captionStyle != null) {
+ captionStyle.clearLeft();
+ captionStyle.setRight(0, Unit.PX);
+ }
+ }
+ } else {
+ if (captionStyle != null) {
+ captionStyle.setLeft(0, Unit.PX);
+ captionStyle.clearRight();
+ }
+ }
+
+ style.setLeft(currentLocation, Unit.PX);
+ }
+
+ public void positionVertically(double currentLocation, double allocatedSpace) {
+ Style style = wrapper.getStyle();
+
+ VCaption caption = getCaption();
+ double captionHeight = caption != null ? getCaptionHeight() : 0;
+ double contentHeight = allocatedSpace - captionHeight;
+
+ if (isRelativeHeight()) {
+ style.setHeight(contentHeight, Unit.PX);
+ } else {
+ style.clearHeight();
+ }
+
+ if (caption != null) {
+ style.setPaddingTop(getCaptionHeight(), Unit.PX);
+ caption.getElement().getStyle().setTop(0, Unit.PX);
+ } else {
+ style.clearPaddingTop();
+ }
+
+ AlignmentInfo alignment = getAlignment();
+ if (!alignment.isTop()) {
+ double actualHeight = getWidgetHeight() + captionHeight;
+ if (alignment.isVerticalCenter()) {
+ currentLocation += (allocatedSpace - actualHeight) / 2d;
+ } else {
+ currentLocation += (allocatedSpace - actualHeight);
+ }
+ }
+
+ style.setTop(currentLocation, Unit.PX);
+ }
+
+ public void positionInDirection(double currentLocation,
+ double allocatedSpace, boolean isVertical) {
+ if (isVertical) {
+ positionVertically(currentLocation, allocatedSpace);
+ } else {
+ positionHorizontally(currentLocation, allocatedSpace);
+ }
+ }
+
+ public int getWidgetSizeInDirection(boolean isVertical) {
+ return isVertical ? getWidgetHeight() : getWidgetWidth();
+ }
+
+ public int getUsedWidth() {
+ int captionWidth = (caption != null ? getCaptionWidth() : 0);
+ return Math.max(captionWidth, getWidgetWidth());
+ }
+
+ public int getUsedHeight() {
+ int captionHeight = (caption != null ? getCaptionHeight() : 0);
+ return getWidgetHeight() + captionHeight;
+ }
+
+ public int getUsedSizeInDirection(boolean isVertical) {
+ return isVertical ? getUsedHeight() : getUsedWidth();
+ }
+
+ protected abstract int getCaptionHeight();
+
+ protected abstract int getCaptionWidth();
+
+ public abstract int getWidgetHeight();
+
+ public abstract int getWidgetWidth();
+
+ public abstract boolean isUndefinedHeight();
+
+ public abstract boolean isUndefinedWidth();
+
+ public boolean isUndefinedInDirection(boolean isVertical) {
+ return isVertical ? isUndefinedHeight() : isUndefinedWidth();
+ }
+
+ public abstract boolean isRelativeHeight();
+
+ public abstract boolean isRelativeWidth();
+
+ public boolean isRelativeInDirection(boolean isVertical) {
+ return isVertical ? isRelativeHeight() : isRelativeWidth();
+ }
+
+ public Element getWrapperElement() {
+ return wrapper;
+ }
+
+ public void setExpandRatio(double expandRatio) {
+ this.expandRatio = expandRatio;
+ }
+
+ public double getExpandRatio() {
+ return expandRatio;
+ }
+}
\ No newline at end of file