import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ui.SubPartAware;
import com.vaadin.client.ui.gridlayout.VGridLayout;
-import com.vaadin.client.ui.orderedlayout.VBoxLayout;
-import com.vaadin.client.ui.orderedlayout.VMeasuringOrderedLayout;
+import com.vaadin.client.ui.orderedlayout.VOrderedLayout;
import com.vaadin.client.ui.tabsheet.VTabsheetPanel;
import com.vaadin.client.ui.ui.VUI;
import com.vaadin.client.ui.window.VWindow;
String childIndexString = part.substring("domChild[".length(),
part.length() - 1);
- if (Util.findWidget(baseElement, null) instanceof VBoxLayout) {
+ if (Util.findWidget(baseElement, null) instanceof VOrderedLayout) {
if (element.hasChildNodes()) {
Element e = element.getFirstChildElement().cast();
String cn = e.getClassName();
continue;
}
- if ("VVerticalLayout".equals(widgetClassName)
- || "VHorizontalLayout".equals(widgetClassName)) {
- widgetClassName = "VBoxLayout";
- }
-
- if (w instanceof VBoxLayout
+ if (w instanceof VOrderedLayout
&& "ChildComponentContainer".equals(widgetClassName)) {
- widgetClassName = "VBoxLayout$Slot";
+ widgetClassName = "VOrderedLayout$Slot";
}
if (w instanceof VTabsheetPanel && widgetPosition != 0) {
* (which would originally have found the widget inside the
* ChildComponentContainer)
*/
- if ((w instanceof VMeasuringOrderedLayout || w instanceof VGridLayout)
+ if ((w instanceof VGridLayout)
&& "ChildComponentContainer".equals(widgetClassName)
&& i + 1 < parts.length) {
String[] nextSplit = nextPart.split("\\[", 2);
String nextWidgetClassName = nextSplit[0];
- if ("VVerticalLayout".equals(nextWidgetClassName)
- || "VHorizontalLayout".equals(nextWidgetClassName)) {
- nextWidgetClassName = "VBoxLayout";
- }
-
// Find the n:th child and count the number of children with
// the same type before it
int nextIndex = 0;
}
widgetPosition--;
- } else if (w instanceof VBoxLayout
- && "VBoxLayout$Slot".equals(simpleName2)) {
+ } else if (w instanceof VOrderedLayout
+ && "VOrderedLayout$Slot".equals(simpleName2)) {
child = ((SimplePanel) child).getWidget();
simpleName2 = Util.getSimpleName(child);
if (widgetClassName.equals(simpleName2)) {
+++ /dev/null
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.client.ui.orderedlayout;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.user.client.Element;
-import com.vaadin.client.ComponentConnector;
-import com.vaadin.client.ConnectorHierarchyChangeEvent;
-import com.vaadin.client.Util;
-import com.vaadin.client.communication.RpcProxy;
-import com.vaadin.client.communication.StateChangeEvent;
-import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler;
-import com.vaadin.client.ui.AbstractFieldConnector;
-import com.vaadin.client.ui.AbstractLayoutConnector;
-import com.vaadin.client.ui.LayoutClickEventHandler;
-import com.vaadin.client.ui.layout.ElementResizeEvent;
-import com.vaadin.client.ui.layout.ElementResizeListener;
-import com.vaadin.client.ui.orderedlayout.VBoxLayout.CaptionPosition;
-import com.vaadin.client.ui.orderedlayout.VBoxLayout.Slot;
-import com.vaadin.shared.AbstractFieldState;
-import com.vaadin.shared.ComponentConstants;
-import com.vaadin.shared.communication.URLReference;
-import com.vaadin.shared.ui.AlignmentInfo;
-import com.vaadin.shared.ui.LayoutClickRpc;
-import com.vaadin.shared.ui.MarginInfo;
-import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutServerRpc;
-import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState;
-
-public abstract class AbstractBoxLayoutConnector extends
- AbstractLayoutConnector /* implements PostLayoutListener */{
-
- AbstractOrderedLayoutServerRpc rpc;
-
- private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler(
- this) {
-
- @Override
- protected ComponentConnector getChildComponent(Element element) {
- return Util.getConnectorForElement(getConnection(), getWidget(),
- element);
- }
-
- @Override
- protected LayoutClickRpc getLayoutClickRPC() {
- return rpc;
- };
-
- };
-
- @Override
- public void init() {
- super.init();
- rpc = RpcProxy.create(AbstractOrderedLayoutServerRpc.class, this);
- getWidget().setLayoutManager(getLayoutManager());
- }
-
- @Override
- public AbstractOrderedLayoutState getState() {
- return (AbstractOrderedLayoutState) super.getState();
- }
-
- @Override
- public VBoxLayout getWidget() {
- return (VBoxLayout) super.getWidget();
- }
-
- /**
- * For bookkeeping. Used to determine if extra calculations are needed for
- * horizontal layout.
- */
- private HashSet<ComponentConnector> hasVerticalAlignment = new HashSet<ComponentConnector>();
-
- /**
- * For bookkeeping. Used to determine if extra calculations are needed for
- * horizontal layout.
- */
- private HashSet<ComponentConnector> hasRelativeHeight = new HashSet<ComponentConnector>();
-
- /**
- * For bookkeeping. Used to determine if extra calculations are needed for
- * horizontal layout.
- */
- private HashSet<ComponentConnector> hasExpandRatio = new HashSet<ComponentConnector>();
-
- /**
- * For bookkeeping. Used in extra calculations for horizontal layout.
- */
- private HashSet<Element> needsMeasure = new HashSet<Element>();
-
- /**
- * For bookkeeping. Used in extra calculations for horizontal layout.
- */
- // private HashMap<Element, Integer> childElementHeight = new
- // HashMap<Element, Integer>();
-
- /**
- * For bookkeeping. Used in extra calculations for horizontal layout.
- */
- private HashMap<Element, Integer> childCaptionElementHeight = new HashMap<Element, Integer>();
-
- @Override
- public void updateCaption(ComponentConnector child) {
- Slot slot = getWidget().getSlot(child);
-
-
- String caption = child.getState().caption;
- URLReference iconUrl = child.getState().resources
- .get(ComponentConstants.ICON_RESOURCE);
- String iconUrlString = iconUrl != null ? iconUrl.toString() : null;
- List<String> styles = child.getState().styles;
- String error = child.getState().errorMessage;
- boolean showError = error != null;
- if (child.getState() instanceof AbstractFieldState) {
- AbstractFieldState abstractFieldState = (AbstractFieldState) child
- .getState();
- showError = showError && !abstractFieldState.hideErrors;
- }
- boolean required = false;
- if (child instanceof AbstractFieldConnector) {
- required = ((AbstractFieldConnector) child).isRequired();
- }
- boolean enabled = child.getState().enabled;
-
- slot.setCaption(caption, iconUrlString, styles, error, showError,
- required,
- enabled);
-
- slot.setRelativeWidth(child.isRelativeWidth());
- slot.setRelativeHeight(child.isRelativeHeight());
-
- if (slot.hasCaption()) {
- CaptionPosition pos = slot.getCaptionPosition();
- getLayoutManager().addElementResizeListener(
- slot.getCaptionElement(), slotCaptionResizeListener);
- if (child.isRelativeHeight()
- && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
- getWidget().updateCaptionOffset(slot.getCaptionElement());
- } else if (child.isRelativeWidth()
- && (pos == CaptionPosition.LEFT || pos == CaptionPosition.RIGHT)) {
- getWidget().updateCaptionOffset(slot.getCaptionElement());
- }
- } else {
- childCaptionElementHeight.remove(child.getWidget().getElement());
- }
-
- updateLayoutHeight();
-
- if (needsExpand()) {
- updateExpand();
- }
- }
-
- @Override
- public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
- super.onConnectorHierarchyChange(event);
-
- List<ComponentConnector> previousChildren = event.getOldChildren();
- int currentIndex = 0;
- VBoxLayout layout = getWidget();
-
- for (ComponentConnector child : getChildComponents()) {
- Slot slot = layout.getSlot(child);
- if (slot.getParent() != layout) {
- child.addStateChangeHandler(childStateChangeHandler);
- }
- layout.addOrMoveSlot(slot, currentIndex++);
- }
-
- for (ComponentConnector child : previousChildren) {
- if (child.getParent() != this) {
- Slot slot = layout.getSlot(child);
- hasVerticalAlignment.remove(child);
- hasRelativeHeight.remove(child);
- hasExpandRatio.remove(child);
- needsMeasure.remove(child.getWidget().getElement());
- // childElementHeight.remove(child.getWidget().getElement());
- childCaptionElementHeight
- .remove(child.getWidget().getElement());
- getLayoutManager().removeElementResizeListener(
- child.getWidget().getElement(),
- childComponentResizeListener);
- if (slot.hasCaption()) {
- getLayoutManager()
- .removeElementResizeListener(
- slot.getCaptionElement(),
- slotCaptionResizeListener);
- }
- if (slot.getSpacingElement() != null) {
- getLayoutManager().removeElementResizeListener(
- slot.getSpacingElement(), spacingResizeListener);
- }
- child.removeStateChangeHandler(childStateChangeHandler);
- layout.removeSlot(child.getWidget());
- }
- }
-
- // If some component is added/removed, we need to recalculate the expand
- if (needsExpand()) {
- updateExpand();
- } else {
- getWidget().clearExpand();
- }
-
- }
-
- @Override
- public void onStateChanged(StateChangeEvent stateChangeEvent) {
- super.onStateChanged(stateChangeEvent);
-
- clickEventHandler.handleEventHandlerRegistration();
- getWidget().setMargin(new MarginInfo(getState().marginsBitmask));
- getWidget().setSpacing(getState().spacing);
-
- hasExpandRatio.clear();
- hasVerticalAlignment.clear();
- hasRelativeHeight.clear();
- needsMeasure.clear();
-
- boolean equalExpandRatio = getWidget().vertical ? !isUndefinedHeight()
- : !isUndefinedWidth();
- for (ComponentConnector child : getChildComponents()) {
- double expandRatio = getState().childData.get(child).expandRatio;
- if (expandRatio > 0) {
- equalExpandRatio = false;
- break;
- }
- }
-
- for (ComponentConnector child : getChildComponents()) {
- Slot slot = getWidget().getSlot(child);
-
- AlignmentInfo alignment = new AlignmentInfo(
- getState().childData.get(child).alignmentBitmask);
- slot.setAlignment(alignment);
-
- double expandRatio = getState().childData.get(child).expandRatio;
-
- if (equalExpandRatio) {
- expandRatio = 1;
- } else if (expandRatio == 0) {
- expandRatio = -1;
- }
- slot.setExpandRatio(expandRatio);
-
- // Bookkeeping to identify special cases that need extra
- // calculations
- if (alignment.isVerticalCenter() || alignment.isBottom()) {
- hasVerticalAlignment.add(child);
- }
-
- if (expandRatio > 0) {
- hasExpandRatio.add(child);
- }
-
- // if (child.getState().isRelativeHeight()) {
- // hasRelativeHeight.add(child);
- // } else {
- // needsMeasure.add(child.getWidget().getElement());
- // }
- }
-
- updateAllSlotListeners();
-
- updateLayoutHeight();
- }
-
- StateChangeHandler childStateChangeHandler = new StateChangeHandler() {
- @Override
- public void onStateChanged(StateChangeEvent stateChangeEvent) {
-
- ComponentConnector child = (ComponentConnector) stateChangeEvent
- .getConnector();
-
- // We need to update the slot size if the component size is changed
- // to relative
- Slot slot = getWidget().getSlot(child);
- slot.setRelativeWidth(child.isRelativeWidth());
- slot.setRelativeHeight(child.isRelativeHeight());
-
- // For relative sized widgets, we need to set the caption offset
- // if (slot.hasCaption()) {
- // CaptionPosition pos = slot.getCaptionPosition();
- // if (child.isRelativeHeight()
- // && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM))
- // {
- // getWidget().updateCaptionOffset(slot.getCaptionElement());
- // } else if (child.isRelativeWidth()
- // && (pos == CaptionPosition.LEFT || pos == CaptionPosition.RIGHT))
- // {
- // getWidget().updateCaptionOffset(slot.getCaptionElement());
- // }
- // }
-
- updateSlotListeners(child);
- // updateAllSlotListeners();
-
- updateLayoutHeight();
- }
- };
-
- private boolean needsFixedHeight() {
- if (!getWidget().vertical
- && isUndefinedHeight()
- && (hasRelativeHeight.size() > 0 || (hasVerticalAlignment
- .size() > 0 && hasVerticalAlignment.size() < getChildren()
- .size()))) {
- return true;
- }
- return false;
- }
-
- private boolean needsExpand() {
- boolean canApplyExpand = (getWidget().vertical && !isUndefinedHeight())
- || (!getWidget().vertical && !isUndefinedWidth());
- return hasExpandRatio.size() > 0 && canApplyExpand;
- }
-
- private void updateAllSlotListeners() {
- for (ComponentConnector child : getChildComponents()) {
- updateSlotListeners(child);
- }
- // if (needsFixedHeight()) {
- // getWidget().clearHeight();
- // setLayoutHeightListener(true);
- // getLayoutManager().setNeedsMeasure(AbstractBoxLayoutConnector.this);
- // } else {
- // setLayoutHeightListener(false);
- // }
- }
-
- /**
- * Add/remove necessary ElementResizeListeners for one slot. This should be
- * called after each update to the slot's or it's widget.
- */
- private void updateSlotListeners(ComponentConnector child) {
- Slot slot = getWidget().getSlot(child);
-
- // Clear all possible listeners first
- dontListen(slot.getWidget().getElement(), childComponentResizeListener);
- if (slot.hasCaption()) {
- dontListen(slot.getCaptionElement(), slotCaptionResizeListener);
- }
- if (slot.hasSpacing()) {
- dontListen(slot.getSpacingElement(), spacingResizeListener);
- }
-
- // Add all necessary listeners
- if (needsFixedHeight()) {
- listen(slot.getWidget().getElement(), childComponentResizeListener);
- if (slot.hasCaption()) {
- listen(slot.getCaptionElement(), slotCaptionResizeListener);
- }
- } else if ((child.isRelativeHeight() || child.isRelativeWidth())
- && slot.hasCaption()) {
- // If the slot has caption, we need to listen for it's size changes
- // in order to update the padding/margin offset for relative sized
- // components
- listen(slot.getCaptionElement(), slotCaptionResizeListener);
- }
-
- if (needsExpand()) {
- listen(slot.getWidget().getElement(), childComponentResizeListener);
- if (slot.hasSpacing()) {
- listen(slot.getSpacingElement(), spacingResizeListener);
- }
- }
-
- if (child.isRelativeHeight()) {
- hasRelativeHeight.add(child);
- needsMeasure.remove(child.getWidget().getElement());
- } else {
- hasRelativeHeight.remove(child);
- needsMeasure.add(child.getWidget().getElement());
- }
-
- }
-
- // public void postLayout() {
- // if (needsFixedHeight()) {
- // // Re-measure all elements that are available
- // for (Element el : needsMeasure) {
- // childElementHeight.put(el, getLayoutManager()
- // .getOuterHeight(el));
- //
- // Element captionElement = el.getParentElement()
- // .getFirstChildElement().cast();
- // if (captionElement.getClassName().contains("v-caption")) {
- // childCaptionElementHeight.put(el, getLayoutManager()
- // .getOuterHeight(captionElement));
- // }
- // }
- // // System.out.println(" ### Child sizes: "
- // // + childElementHeight.values().toString());
- // // System.out.println(" ### Caption sizes: "
- // // + childCaptionElementHeight.values().toString());
- //
- // int height = getMaxHeight()
- // + getLayoutManager().getBorderHeight(
- // getWidget().getElement())
- // + getLayoutManager().getPaddingHeight(
- // getWidget().getElement());
- // getWidget().getElement().getStyle().setHeight(height, Unit.PX);
- // }
- // }
-
- // private ElementResizeListener layoutResizeListener = new
- // ElementResizeListener() {
- // public void onElementResize(ElementResizeEvent e) {
- // updateLayoutHeight();
- // if (needsExpand() && (isUndefinedHeight() || isUndefinedWidth())) {
- // updateExpand();
- // }
- // }
- // };
-
- private ElementResizeListener slotCaptionResizeListener = new ElementResizeListener() {
- @Override
- public void onElementResize(ElementResizeEvent e) {
-
- // Get all needed element references
- Element captionElement = (Element) e.getElement().cast();
-
- // Caption position determines if the widget element is the first or
- // last child inside the caption wrap
- CaptionPosition pos = getWidget().getCaptionPositionFromElement(
- (Element) captionElement.getParentElement().cast());
-
- // The default is the last child
- Element widgetElement = captionElement.getParentElement()
- .getLastChild().cast();
-
- // ...but if caption position is bottom or right, the widget is the
- // first child
- if (pos == CaptionPosition.BOTTOM || pos == CaptionPosition.RIGHT) {
- widgetElement = captionElement.getParentElement()
- .getFirstChildElement().cast();
- }
-
- if (captionElement == widgetElement) {
- // Caption element already detached
- dontListen(captionElement, slotCaptionResizeListener);
- childCaptionElementHeight.remove(widgetElement);
- return;
- }
-
- String widgetWidth = widgetElement.getStyle().getWidth();
- String widgetHeight = widgetElement.getStyle().getHeight();
-
- if (widgetHeight.endsWith("%")
- && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
- getWidget().updateCaptionOffset(captionElement);
- } else if (widgetWidth.endsWith("%")
- && (pos == CaptionPosition.LEFT || pos == CaptionPosition.RIGHT)) {
- getWidget().updateCaptionOffset(captionElement);
- }
-
- int h = getLayoutManager().getOuterHeight(captionElement)
- - getLayoutManager().getMarginHeight(captionElement);
- childCaptionElementHeight.put(widgetElement, h);
-
- // if (needsFixedHeight()) {
- // getWidget().clearHeight();
- // getLayoutManager().setNeedsMeasure(
- // AbstractBoxLayoutConnector.this);
- // }
-
- updateLayoutHeight();
-
- if (needsExpand()) {
- updateExpand();
- }
- }
- };
-
- private ElementResizeListener childComponentResizeListener = new ElementResizeListener() {
- @Override
- public void onElementResize(ElementResizeEvent e) {
- // int h = getLayoutManager().getOuterHeight(e.getElement());
- // childElementHeight.put((Element) e.getElement().cast(), h);
- updateLayoutHeight();
-
- if (needsExpand()) {
- updateExpand();
- }
- }
- };
-
- private ElementResizeListener spacingResizeListener = new ElementResizeListener() {
- @Override
- public void onElementResize(ElementResizeEvent e) {
- if (needsExpand()) {
- updateExpand();
- }
- }
- };
-
- private void updateLayoutHeight() {
- if (needsFixedHeight()) {
- int h = getMaxHeight();
- h += getLayoutManager().getBorderHeight(getWidget().getElement())
- + getLayoutManager().getPaddingHeight(
- getWidget().getElement());
- getWidget().getElement().getStyle().setHeight(h, Unit.PX);
- getLayoutManager().setNeedsMeasure(this);
- }
- }
-
- private void updateExpand() {
- // System.out.println("All sizes: "
- // + childElementHeight.values().toString() + " - Caption sizes: "
- // + childCaptionElementHeight.values().toString());
- getWidget().updateExpand();
- }
-
- private int getMaxHeight() {
- int highestNonRelative = -1;
- int highestRelative = -1;
-
- for (ComponentConnector child : getChildComponents()) {
- // TODO would be more efficient to measure the slot element if both
- // caption and child widget elements need to be measured. Keeping
- // track of what to measure is the most difficult part of this
- // layout.
- Element el = child.getWidget().getElement();
- CaptionPosition pos = getWidget().getCaptionPositionFromElement(
- (Element) el.getParentElement().cast());
- if (needsMeasure.contains(el)) {
- int h = getLayoutManager().getOuterHeight(el);
- String sHeight = el.getStyle().getHeight();
- // Only add the caption size to the height of the slot if
- // coption position is top or bottom
- if (childCaptionElementHeight.containsKey(el)
- && (sHeight == null || !sHeight.endsWith("%"))
- && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
- h += childCaptionElementHeight.get(el);
- }
- if (h > highestNonRelative) {
- highestNonRelative = h;
- }
- } else {
- int h = getLayoutManager().getOuterHeight(el);
- if (childCaptionElementHeight.containsKey(el)
- && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
- h += childCaptionElementHeight.get(el);
- }
- if (h > highestRelative) {
- highestRelative = h;
- }
- }
- }
- return highestNonRelative > -1 ? highestNonRelative : highestRelative;
- }
-
- @Override
- public void onUnregister() {
- // Cleanup all ElementResizeListeners
-
- // dontListen(getWidget().getElement(), layoutResizeListener);
-
- for (ComponentConnector child : getChildComponents()) {
- Slot slot = getWidget().getSlot(child);
- if (slot.hasCaption()) {
- dontListen(slot.getCaptionElement(), slotCaptionResizeListener);
- }
-
- if (slot.getSpacingElement() != null) {
- dontListen(slot.getSpacingElement(), spacingResizeListener);
- }
-
- dontListen(slot.getWidget().getElement(),
- childComponentResizeListener);
- }
-
- super.onUnregister();
- }
-
- // private void setLayoutHeightListener(boolean add) {
- // if (add) {
- // listen(getWidget().getElement(), layoutResizeListener);
- // } else {
- // dontListen(getWidget().getElement(), layoutResizeListener);
- // if (!needsExpand()) {
- // System.out.println("Clearing element sizes");
- // childElementHeight.clear();
- // childCaptionElementHeight.clear();
- // }
- // }
- // }
-
- /*
- * Convenience methods
- */
-
- private void listen(Element el, ElementResizeListener listener) {
- getLayoutManager().addElementResizeListener(el, listener);
- }
-
- private void dontListen(Element el, ElementResizeListener listener) {
- getLayoutManager().removeElementResizeListener(el, listener);
- }
-
-}
*/
package com.vaadin.client.ui.orderedlayout;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
-import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
-import com.vaadin.client.DirectionalManagedLayout;
-import com.vaadin.client.LayoutManager;
import com.vaadin.client.Util;
-import com.vaadin.client.VCaption;
import com.vaadin.client.communication.RpcProxy;
import com.vaadin.client.communication.StateChangeEvent;
+import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler;
+import com.vaadin.client.ui.AbstractFieldConnector;
import com.vaadin.client.ui.AbstractLayoutConnector;
import com.vaadin.client.ui.LayoutClickEventHandler;
-import com.vaadin.client.ui.layout.ComponentConnectorLayoutSlot;
-import com.vaadin.client.ui.layout.VLayoutSlot;
+import com.vaadin.client.ui.layout.ElementResizeEvent;
+import com.vaadin.client.ui.layout.ElementResizeListener;
+import com.vaadin.client.ui.orderedlayout.VOrderedLayout.CaptionPosition;
+import com.vaadin.client.ui.orderedlayout.VOrderedLayout.Slot;
+import com.vaadin.shared.AbstractFieldState;
+import com.vaadin.shared.ComponentConstants;
+import com.vaadin.shared.communication.URLReference;
import com.vaadin.shared.ui.AlignmentInfo;
import com.vaadin.shared.ui.LayoutClickRpc;
import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutServerRpc;
import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState;
+/**
+ * Base class for vertical and horizontal ordered layouts
+ */
public abstract class AbstractOrderedLayoutConnector extends
- AbstractLayoutConnector implements DirectionalManagedLayout {
+ AbstractLayoutConnector {
AbstractOrderedLayoutServerRpc rpc;
+ /*
+ * Handlers & Listeners
+ */
+
private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler(
this) {
protected LayoutClickRpc getLayoutClickRPC() {
return rpc;
};
+ };
+
+ private StateChangeHandler childStateChangeHandler = new StateChangeHandler() {
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+
+ ComponentConnector child = (ComponentConnector) stateChangeEvent
+ .getConnector();
+
+ // We need to update the slot size if the component size is changed
+ // to relative
+ Slot slot = getWidget().getSlot(child.getWidget());
+ slot.setRelativeWidth(child.isRelativeWidth());
+ slot.setRelativeHeight(child.isRelativeHeight());
+
+ updateSlotListeners(child);
+ // updateAllSlotListeners();
+
+ updateLayoutHeight();
+ }
+ };
+
+ private ElementResizeListener slotCaptionResizeListener = new ElementResizeListener() {
+ @Override
+ public void onElementResize(ElementResizeEvent e) {
+
+ // Get all needed element references
+ Element captionElement = (Element) e.getElement().cast();
+
+ // Caption position determines if the widget element is the first or
+ // last child inside the caption wrap
+ CaptionPosition pos = getWidget().getCaptionPositionFromElement(
+ (Element) captionElement.getParentElement().cast());
+
+ // The default is the last child
+ Element widgetElement = captionElement.getParentElement()
+ .getLastChild().cast();
+
+ // ...but if caption position is bottom or right, the widget is the
+ // first child
+ if (pos == CaptionPosition.BOTTOM || pos == CaptionPosition.RIGHT) {
+ widgetElement = captionElement.getParentElement()
+ .getFirstChildElement().cast();
+ }
+
+ if (captionElement == widgetElement) {
+ // Caption element already detached
+ rmeoveResizeListener(captionElement, slotCaptionResizeListener);
+ childCaptionElementHeight.remove(widgetElement);
+ return;
+ }
+ String widgetWidth = widgetElement.getStyle().getWidth();
+ String widgetHeight = widgetElement.getStyle().getHeight();
+
+ if (widgetHeight.endsWith("%")
+ && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
+ getWidget().updateCaptionOffset(captionElement);
+ } else if (widgetWidth.endsWith("%")
+ && (pos == CaptionPosition.LEFT || pos == CaptionPosition.RIGHT)) {
+ getWidget().updateCaptionOffset(captionElement);
+ }
+
+ int h = getLayoutManager().getOuterHeight(captionElement)
+ - getLayoutManager().getMarginHeight(captionElement);
+ childCaptionElementHeight.put(widgetElement, h);
+
+ updateLayoutHeight();
+
+ if (needsExpand()) {
+ getWidget().updateExpand();
+ }
+ }
+ };
+
+ private ElementResizeListener childComponentResizeListener = new ElementResizeListener() {
+ @Override
+ public void onElementResize(ElementResizeEvent e) {
+ updateLayoutHeight();
+ if (needsExpand()) {
+ getWidget().updateExpand();
+ }
+ }
};
+ private ElementResizeListener spacingResizeListener = new ElementResizeListener() {
+ @Override
+ public void onElementResize(ElementResizeEvent e) {
+ if (needsExpand()) {
+ getWidget().updateExpand();
+ }
+ }
+ };
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.client.ui.AbstractComponentConnector#init()
+ */
@Override
public void init() {
super.init();
rpc = RpcProxy.create(AbstractOrderedLayoutServerRpc.class, this);
- getLayoutManager().registerDependency(this,
- getWidget().spacingMeasureElement);
+ getWidget().setLayoutManager(getLayoutManager());
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.client.ui.AbstractLayoutConnector#getState()
+ */
@Override
- public void onUnregister() {
- LayoutManager lm = getLayoutManager();
-
- VMeasuringOrderedLayout layout = getWidget();
- lm.unregisterDependency(this, layout.spacingMeasureElement);
+ public AbstractOrderedLayoutState getState() {
+ return (AbstractOrderedLayoutState) super.getState();
+ }
- // Unregister child caption listeners
- for (ComponentConnector child : getChildComponents()) {
- VLayoutSlot slot = layout.getSlotForChild(child.getWidget());
- slot.setCaption(null);
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.client.ui.AbstractComponentConnector#getWidget()
+ */
+ @Override
+ public VOrderedLayout getWidget() {
+ return (VOrderedLayout) super.getWidget();
}
+ /**
+ * For bookkeeping. Used to determine if extra calculations are needed for
+ * horizontal layout.
+ */
+ private HashSet<ComponentConnector> hasVerticalAlignment = new HashSet<ComponentConnector>();
+
+ /**
+ * For bookkeeping. Used to determine if extra calculations are needed for
+ * horizontal layout.
+ */
+ private HashSet<ComponentConnector> hasRelativeHeight = new HashSet<ComponentConnector>();
+
+ /**
+ * For bookkeeping. Used to determine if extra calculations are needed for
+ * horizontal layout.
+ */
+ private HashSet<ComponentConnector> hasExpandRatio = new HashSet<ComponentConnector>();
+
+ /**
+ * For bookkeeping. Used in extra calculations for horizontal layout.
+ */
+ private HashSet<Element> needsMeasure = new HashSet<Element>();
+
+ /**
+ * For bookkeeping. Used in extra calculations for horizontal layout.
+ */
+ private HashMap<Element, Integer> childCaptionElementHeight = new HashMap<Element, Integer>();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.client.ComponentContainerConnector#updateCaption(com.vaadin
+ * .client.ComponentConnector)
+ */
@Override
- public AbstractOrderedLayoutState getState() {
- return (AbstractOrderedLayoutState) super.getState();
+ public void updateCaption(ComponentConnector child) {
+ Slot slot = getWidget().getSlot(child.getWidget());
+
+ String caption = child.getState().caption;
+ URLReference iconUrl = child.getState().resources
+ .get(ComponentConstants.ICON_RESOURCE);
+ String iconUrlString = iconUrl != null ? iconUrl.toString() : null;
+ List<String> styles = child.getState().styles;
+ String error = child.getState().errorMessage;
+ boolean showError = error != null;
+ if (child.getState() instanceof AbstractFieldState) {
+ AbstractFieldState abstractFieldState = (AbstractFieldState) child
+ .getState();
+ showError = showError && !abstractFieldState.hideErrors;
+ }
+ boolean required = false;
+ if (child instanceof AbstractFieldConnector) {
+ required = ((AbstractFieldConnector) child).isRequired();
+ }
+ boolean enabled = child.getState().enabled;
+
+ slot.setCaption(caption, iconUrlString, styles, error, showError,
+ required,
+ enabled);
+
+ slot.setRelativeWidth(child.isRelativeWidth());
+ slot.setRelativeHeight(child.isRelativeHeight());
+
+ if (slot.hasCaption()) {
+ CaptionPosition pos = slot.getCaptionPosition();
+ getLayoutManager().addElementResizeListener(
+ slot.getCaptionElement(), slotCaptionResizeListener);
+ if (child.isRelativeHeight()
+ && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
+ getWidget().updateCaptionOffset(slot.getCaptionElement());
+ } else if (child.isRelativeWidth()
+ && (pos == CaptionPosition.LEFT || pos == CaptionPosition.RIGHT)) {
+ getWidget().updateCaptionOffset(slot.getCaptionElement());
+ }
+ } else {
+ childCaptionElementHeight.remove(child.getWidget().getElement());
+ }
+
+ updateLayoutHeight();
+
+ if (needsExpand()) {
+ getWidget().updateExpand();
+ }
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.client.ui.AbstractComponentContainerConnector#
+ * onConnectorHierarchyChange
+ * (com.vaadin.client.ConnectorHierarchyChangeEvent)
+ */
@Override
- public void updateCaption(ComponentConnector component) {
- VMeasuringOrderedLayout layout = getWidget();
- if (VCaption.isNeeded(component.getState())) {
- VLayoutSlot layoutSlot = layout.getSlotForChild(component
- .getWidget());
- VCaption caption = layoutSlot.getCaption();
- if (caption == null) {
- caption = new VCaption(component, getConnection());
-
- Widget widget = component.getWidget();
-
- layout.setCaption(widget, caption);
+ public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
+ super.onConnectorHierarchyChange(event);
+
+ List<ComponentConnector> previousChildren = event.getOldChildren();
+ int currentIndex = 0;
+ VOrderedLayout layout = getWidget();
+
+ for (ComponentConnector child : getChildComponents()) {
+ Slot slot = layout.getSlot(child.getWidget());
+ if (slot.getParent() != layout) {
+ child.addStateChangeHandler(childStateChangeHandler);
+ }
+ layout.addOrMoveSlot(slot, currentIndex++);
+ }
+
+ for (ComponentConnector child : previousChildren) {
+ if (child.getParent() != this) {
+ Slot slot = layout.getSlot(child.getWidget());
+ hasVerticalAlignment.remove(child);
+ hasRelativeHeight.remove(child);
+ hasExpandRatio.remove(child);
+ needsMeasure.remove(child.getWidget().getElement());
+ childCaptionElementHeight
+ .remove(child.getWidget().getElement());
+ getLayoutManager().removeElementResizeListener(
+ child.getWidget().getElement(),
+ childComponentResizeListener);
+ if (slot.hasCaption()) {
+ getLayoutManager()
+ .removeElementResizeListener(
+ slot.getCaptionElement(),
+ slotCaptionResizeListener);
+ }
+ if (slot.getSpacingElement() != null) {
+ getLayoutManager().removeElementResizeListener(
+ slot.getSpacingElement(), spacingResizeListener);
+ }
+ child.removeStateChangeHandler(childStateChangeHandler);
+ layout.removeWidget(child.getWidget());
}
- caption.updateCaption();
+ }
+
+ // If some component is added/removed, we need to recalculate the expand
+ if (needsExpand()) {
+ getWidget().updateExpand();
} else {
- layout.setCaption(component.getWidget(), null);
- getLayoutManager().setNeedsLayout(this);
+ getWidget().clearExpand();
}
- }
- @Override
- public VMeasuringOrderedLayout getWidget() {
- return (VMeasuringOrderedLayout) super.getWidget();
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.client.ui.AbstractComponentConnector#onStateChanged(com.vaadin
+ * .client.communication.StateChangeEvent)
+ */
@Override
public void onStateChanged(StateChangeEvent stateChangeEvent) {
super.onStateChanged(stateChangeEvent);
clickEventHandler.handleEventHandlerRegistration();
+ getWidget().setMargin(new MarginInfo(getState().marginsBitmask));
+ getWidget().setSpacing(getState().spacing);
- VMeasuringOrderedLayout layout = getWidget();
+ hasExpandRatio.clear();
+ hasVerticalAlignment.clear();
+ hasRelativeHeight.clear();
+ needsMeasure.clear();
+ boolean equalExpandRatio = getWidget().vertical ? !isUndefinedHeight()
+ : !isUndefinedWidth();
for (ComponentConnector child : getChildComponents()) {
- VLayoutSlot slot = layout.getSlotForChild(child.getWidget());
+ double expandRatio = getState().childData.get(child).expandRatio;
+ if (expandRatio > 0) {
+ equalExpandRatio = false;
+ break;
+ }
+ }
+
+ for (ComponentConnector child : getChildComponents()) {
+ Slot slot = getWidget().getSlot(child.getWidget());
AlignmentInfo alignment = new AlignmentInfo(
getState().childData.get(child).alignmentBitmask);
slot.setAlignment(alignment);
double expandRatio = getState().childData.get(child).expandRatio;
- slot.setExpandRatio(expandRatio);
- }
- layout.updateMarginStyleNames(new MarginInfo(getState().marginsBitmask));
- layout.updateSpacingStyleName(getState().spacing);
+ if (equalExpandRatio) {
+ expandRatio = 1;
+ } else if (expandRatio == 0) {
+ expandRatio = -1;
+ }
+ slot.setExpandRatio(expandRatio);
- getLayoutManager().setNeedsLayout(this);
- }
+ // Bookkeeping to identify special cases that need extra
+ // calculations
+ if (alignment.isVerticalCenter() || alignment.isBottom()) {
+ hasVerticalAlignment.add(child);
+ }
- private int getSizeForInnerSize(int size, boolean isVertical) {
- LayoutManager layoutManager = getLayoutManager();
- Element element = getWidget().getElement();
- if (isVertical) {
- return size + layoutManager.getBorderHeight(element)
- + layoutManager.getPaddingHeight(element);
- } else {
- return size + layoutManager.getBorderWidth(element)
- + layoutManager.getPaddingWidth(element);
+ if (expandRatio > 0) {
+ hasExpandRatio.add(child);
+ }
}
- }
-
- private static String getSizeProperty(boolean isVertical) {
- return isVertical ? "height" : "width";
- }
- private boolean isUndefinedInDirection(boolean isVertical) {
- if (isVertical) {
- return isUndefinedHeight();
- } else {
- return isUndefinedWidth();
- }
- }
+ updateAllSlotListeners();
- private int getInnerSizeInDirection(boolean isVertical) {
- if (isVertical) {
- return getLayoutManager().getInnerHeight(getWidget().getElement());
- } else {
- return getLayoutManager().getInnerWidth(getWidget().getElement());
- }
+ updateLayoutHeight();
}
- private void layoutPrimaryDirection() {
- VMeasuringOrderedLayout layout = getWidget();
- boolean isVertical = layout.isVertical;
- boolean isUndefined = isUndefinedInDirection(isVertical);
- int startPadding = getStartPadding(isVertical);
- int endPadding = getEndPadding(isVertical);
- int spacingSize = getSpacingInDirection(isVertical);
- int allocatedSize;
-
- if (isUndefined) {
- allocatedSize = -1;
- } else {
- allocatedSize = getInnerSizeInDirection(isVertical);
- }
-
- allocatedSize = layout.layoutPrimaryDirection(spacingSize,
- allocatedSize, startPadding, endPadding);
-
- Style ownStyle = getWidget().getElement().getStyle();
- if (isUndefined) {
- int outerSize = getSizeForInnerSize(allocatedSize, isVertical);
- ownStyle.setPropertyPx(getSizeProperty(isVertical), outerSize);
- reportUndefinedSize(outerSize, isVertical);
- } else {
- ownStyle.setProperty(getSizeProperty(isVertical),
- getDefinedSize(isVertical));
+ /**
+ * Does the layout need a fixed height?
+ */
+ private boolean needsFixedHeight() {
+ if (!getWidget().vertical
+ && isUndefinedHeight()
+ && (hasRelativeHeight.size() > 0 || (hasVerticalAlignment
+ .size() > 0 && hasVerticalAlignment.size() < getChildren()
+ .size()))) {
+ return true;
}
+ return false;
}
- private void reportUndefinedSize(int outerSize, boolean isVertical) {
- if (isVertical) {
- getLayoutManager().reportOuterHeight(this, outerSize);
- } else {
- getLayoutManager().reportOuterWidth(this, outerSize);
- }
+ /**
+ * Does the layout need to expand?
+ */
+ private boolean needsExpand() {
+ boolean canApplyExpand = (getWidget().vertical && !isUndefinedHeight())
+ || (!getWidget().vertical && !isUndefinedWidth());
+ return hasExpandRatio.size() > 0 && canApplyExpand;
}
- private int getSpacingInDirection(boolean isVertical) {
- if (isVertical) {
- return getLayoutManager().getOuterHeight(
- getWidget().spacingMeasureElement);
- } else {
- return getLayoutManager().getOuterWidth(
- getWidget().spacingMeasureElement);
+ /**
+ * Add slot listeners
+ */
+ private void updateAllSlotListeners() {
+ for (ComponentConnector child : getChildComponents()) {
+ updateSlotListeners(child);
}
}
- private void layoutSecondaryDirection() {
- VMeasuringOrderedLayout layout = getWidget();
- boolean isVertical = layout.isVertical;
- boolean isUndefined = isUndefinedInDirection(!isVertical);
-
- int startPadding = getStartPadding(!isVertical);
- int endPadding = getEndPadding(!isVertical);
-
- int allocatedSize;
- if (isUndefined) {
- allocatedSize = -1;
- } else {
- allocatedSize = getInnerSizeInDirection(!isVertical);
+ /**
+ * Add/remove necessary ElementResizeListeners for one slot. This should be
+ * called after each update to the slot's or it's widget.
+ */
+ private void updateSlotListeners(ComponentConnector child) {
+ Slot slot = getWidget().getSlot(child.getWidget());
+
+ // Clear all possible listeners first
+ rmeoveResizeListener(slot.getWidget().getElement(), childComponentResizeListener);
+ if (slot.hasCaption()) {
+ rmeoveResizeListener(slot.getCaptionElement(), slotCaptionResizeListener);
}
-
- allocatedSize = layout.layoutSecondaryDirection(allocatedSize,
- startPadding, endPadding);
-
- Style ownStyle = getWidget().getElement().getStyle();
-
- if (isUndefined) {
- int outerSize = getSizeForInnerSize(allocatedSize,
- !getWidget().isVertical);
- ownStyle.setPropertyPx(getSizeProperty(!getWidget().isVertical),
- outerSize);
- reportUndefinedSize(outerSize, !isVertical);
- } else {
- ownStyle.setProperty(getSizeProperty(!getWidget().isVertical),
- getDefinedSize(!getWidget().isVertical));
+ if (slot.hasSpacing()) {
+ rmeoveResizeListener(slot.getSpacingElement(), spacingResizeListener);
}
- }
- private String getDefinedSize(boolean isVertical) {
- if (isVertical) {
- return getState().height == null ? "" : getState().height;
- } else {
- return getState().width == null ? "" : getState().width;
+ // Add all necessary listeners
+ if (needsFixedHeight()) {
+ addResizeListener(slot.getWidget().getElement(), childComponentResizeListener);
+ if (slot.hasCaption()) {
+ addResizeListener(slot.getCaptionElement(), slotCaptionResizeListener);
+ }
+ } else if ((child.isRelativeHeight() || child.isRelativeWidth())
+ && slot.hasCaption()) {
+ // If the slot has caption, we need to listen for it's size changes
+ // in order to update the padding/margin offset for relative sized
+ // components
+ addResizeListener(slot.getCaptionElement(), slotCaptionResizeListener);
}
- }
- private int getStartPadding(boolean isVertical) {
- if (isVertical) {
- return getLayoutManager().getPaddingTop(getWidget().getElement());
- } else {
- return getLayoutManager().getPaddingLeft(getWidget().getElement());
+ if (needsExpand()) {
+ addResizeListener(slot.getWidget().getElement(), childComponentResizeListener);
+ if (slot.hasSpacing()) {
+ addResizeListener(slot.getSpacingElement(), spacingResizeListener);
+ }
}
- }
- private int getEndPadding(boolean isVertical) {
- if (isVertical) {
- return getLayoutManager()
- .getPaddingBottom(getWidget().getElement());
+ if (child.isRelativeHeight()) {
+ hasRelativeHeight.add(child);
+ needsMeasure.remove(child.getWidget().getElement());
} else {
- return getLayoutManager().getPaddingRight(getWidget().getElement());
+ hasRelativeHeight.remove(child);
+ needsMeasure.add(child.getWidget().getElement());
}
+
}
- @Override
- public void layoutHorizontally() {
- if (getWidget().isVertical) {
- layoutSecondaryDirection();
- } else {
- layoutPrimaryDirection();
+ /**
+ * Re-calculate the layout height
+ */
+ private void updateLayoutHeight() {
+ if (needsFixedHeight()) {
+ int h = getMaxHeight();
+ h += getLayoutManager().getBorderHeight(getWidget().getElement())
+ + getLayoutManager().getPaddingHeight(
+ getWidget().getElement());
+ getWidget().getElement().getStyle().setHeight(h, Unit.PX);
+ getLayoutManager().setNeedsMeasure(this);
}
}
- @Override
- public void layoutVertically() {
- if (getWidget().isVertical) {
- layoutPrimaryDirection();
- } else {
- layoutSecondaryDirection();
+ /**
+ * Measures the maximum height of the layout in pixels
+ */
+ private int getMaxHeight() {
+ int highestNonRelative = -1;
+ int highestRelative = -1;
+
+ for (ComponentConnector child : getChildComponents()) {
+ // TODO would be more efficient to measure the slot element if both
+ // caption and child widget elements need to be measured. Keeping
+ // track of what to measure is the most difficult part of this
+ // layout.
+ Element el = child.getWidget().getElement();
+ CaptionPosition pos = getWidget().getCaptionPositionFromElement(
+ (Element) el.getParentElement().cast());
+ if (needsMeasure.contains(el)) {
+ int h = getLayoutManager().getOuterHeight(el);
+ String sHeight = el.getStyle().getHeight();
+ // Only add the caption size to the height of the slot if
+ // coption position is top or bottom
+ if (childCaptionElementHeight.containsKey(el)
+ && (sHeight == null || !sHeight.endsWith("%"))
+ && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
+ h += childCaptionElementHeight.get(el);
+ }
+ if (h > highestNonRelative) {
+ highestNonRelative = h;
+ }
+ } else {
+ int h = getLayoutManager().getOuterHeight(el);
+ if (childCaptionElementHeight.containsKey(el)
+ && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
+ h += childCaptionElementHeight.get(el);
+ }
+ if (h > highestRelative) {
+ highestRelative = h;
+ }
+ }
}
+ return highestNonRelative > -1 ? highestNonRelative : highestRelative;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.client.ui.AbstractComponentConnector#onUnregister()
+ */
@Override
- public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
- super.onConnectorHierarchyChange(event);
- List<ComponentConnector> previousChildren = event.getOldChildren();
- int currentIndex = 0;
- VMeasuringOrderedLayout layout = getWidget();
-
+ public void onUnregister() {
+ // Cleanup all ElementResizeListeners
for (ComponentConnector child : getChildComponents()) {
- Widget childWidget = child.getWidget();
- VLayoutSlot slot = layout.getSlotForChild(childWidget);
-
- if (childWidget.getParent() != layout) {
- // If the child widget was previously attached to another
- // AbstractOrderedLayout a slot might be found that belongs to
- // another AbstractOrderedLayout. In this case we discard it and
- // create a new slot.
- slot = new ComponentConnectorLayoutSlot(getWidget()
- .getStylePrimaryName(), child, this);
- }
- layout.addOrMove(slot, currentIndex++);
- if (child.isRelativeWidth()) {
- slot.getWrapperElement().getStyle().setWidth(100, Unit.PCT);
+ Slot slot = getWidget().getSlot(child.getWidget());
+ if (slot.hasCaption()) {
+ rmeoveResizeListener(slot.getCaptionElement(), slotCaptionResizeListener);
}
- }
- for (ComponentConnector child : previousChildren) {
- if (child.getParent() != this) {
- // Remove slot if the connector is no longer a child of this
- // layout
- layout.removeSlotForWidget(child.getWidget());
+ if (slot.getSpacingElement() != null) {
+ rmeoveResizeListener(slot.getSpacingElement(), spacingResizeListener);
}
+
+ rmeoveResizeListener(slot.getWidget().getElement(),
+ childComponentResizeListener);
}
- };
+ super.onUnregister();
+ }
+
+ /**
+ * Helper method to add a resize listener to an element
+ *
+ * @param el
+ * The element to add the resize listener to
+ * @param listener
+ * The listener to add
+ */
+ private void addResizeListener(Element el, ElementResizeListener listener) {
+ getLayoutManager().addElementResizeListener(el, listener);
+ }
+
+ /**
+ * Helper method to remove a resize listener to an element
+ *
+ * @param el
+ * The element from where the resize listener should be removed
+ * @param listener
+ * THe listener to remove
+ */
+ private void rmeoveResizeListener(Element el, ElementResizeListener listener) {
+ getLayoutManager().removeElementResizeListener(el, listener);
+ }
}
+++ /dev/null
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.client.ui.orderedlayout;
-
-import com.vaadin.shared.ui.Connect;
-import com.vaadin.shared.ui.Connect.LoadStyle;
-import com.vaadin.ui.HorizontalLayout;
-
-@Connect(value = HorizontalLayout.class, loadStyle = LoadStyle.EAGER)
-public class HorizontalBoxLayoutConnector extends AbstractBoxLayoutConnector {
-
- @Override
- public void init() {
- super.init();
- getWidget().setVertical(false);
- }
-
-}
*/
package com.vaadin.client.ui.orderedlayout;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.Connect.LoadStyle;
+import com.vaadin.ui.HorizontalLayout;
-//@Connect(value = HorizontalLayout.class, loadStyle = LoadStyle.EAGER)
+/**
+ * Connects the client widget {@link VHorizontalLayout} with the Vaadin server
+ * side counterpart {@link HorizontalLayout}
+ */
+@Connect(value = HorizontalLayout.class, loadStyle = LoadStyle.EAGER)
public class HorizontalLayoutConnector extends AbstractOrderedLayoutConnector {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.client.ui.orderedlayout.AbstractOrderedLayoutConnector#getWidget
+ * ()
+ */
@Override
public VHorizontalLayout getWidget() {
return (VHorizontalLayout) super.getWidget();
+++ /dev/null
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.client.ui.orderedlayout;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.google.gwt.dom.client.Node;
-import com.google.gwt.dom.client.Style;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.regexp.shared.MatchResult;
-import com.google.gwt.regexp.shared.RegExp;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.SimplePanel;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.client.ComponentConnector;
-import com.vaadin.client.LayoutManager;
-import com.vaadin.shared.ui.AlignmentInfo;
-import com.vaadin.shared.ui.MarginInfo;
-import com.vaadin.ui.themes.BaseTheme;
-
-public class VBoxLayout extends FlowPanel {
-
- public static final String CLASSNAME = "v-boxlayout";
-
- private static final String ALIGN_CLASS_PREFIX = "v-align-";
-
- protected boolean spacing = false;
-
- protected boolean vertical = true;
-
- protected boolean definedHeight = false;
-
- private Map<Widget, Slot> widgetToSlot = new HashMap<Widget, Slot>();
-
- private LayoutManager layoutManager;
-
- public VBoxLayout() {
- setStyleName(CLASSNAME);
- setVertical(true);
- }
-
- public void setVertical(boolean isVertical) {
- vertical = isVertical;
- if (vertical) {
- addStyleName("v-vertical");
- removeStyleName("v-horizontal");
- } else {
- addStyleName("v-horizontal");
- removeStyleName("v-vertical");
- }
- }
-
- public void addOrMoveSlot(Slot slot, int index) {
- if (slot.getParent() == this) {
- int currentIndex = getWidgetIndex(slot);
- if (index == currentIndex) {
- return;
- }
- }
- insert(slot, index);
- }
-
- @Override
- protected void insert(Widget child, Element container, int beforeIndex,
- boolean domInsert) {
- // Validate index; adjust if the widget is already a child of this
- // panel.
- beforeIndex = adjustIndex(child, beforeIndex);
-
- // Detach new child.
- child.removeFromParent();
-
- // Logical attach.
- getChildren().insert(child, beforeIndex);
-
- // Physical attach.
- container = expandWrapper != null ? expandWrapper : getElement();
- if (domInsert) {
- DOM.insertChild(container, child.getElement(),
- spacing ? beforeIndex * 2 : beforeIndex);
- } else {
- DOM.appendChild(container, child.getElement());
- }
-
- // Adopt.
- adopt(child);
- }
-
- public Slot removeSlot(Widget widget) {
- Slot slot = widgetToSlot.get(widget);
- remove(slot);
- widgetToSlot.remove(widget);
- return slot;
- }
-
- public Slot getSlot(ComponentConnector connector) {
- Slot slot = widgetToSlot.get(connector.getWidget());
- if (slot == null) {
- slot = new Slot(connector);
- widgetToSlot.put(connector.getWidget(), slot);
- }
- return slot;
- }
-
- public enum CaptionPosition {
- TOP, RIGHT, BOTTOM, LEFT
- }
-
- protected class Slot extends SimplePanel {
-
- private ComponentConnector connector;
-
- private Element spacer;
-
- private Element captionWrap;
- private Element caption;
- private Element captionText;
- private Icon icon;
- private Element errorIcon;
- private Element requiredIcon;
-
- // Caption is placed after component unless there is some part which
- // moves it above.
- private CaptionPosition captionPosition = CaptionPosition.RIGHT;
-
- private AlignmentInfo alignment;
- private double expandRatio = -1;
-
- public Slot(ComponentConnector connector) {
- this.connector = connector;
- setWidget(connector.getWidget());
- setStylePrimaryName("v-slot");
- }
-
- public AlignmentInfo getAlignment() {
- return alignment;
- }
-
- public void setAlignment(AlignmentInfo alignment) {
- this.alignment = alignment;
-
- if (alignment.isHorizontalCenter()) {
- addStyleName(ALIGN_CLASS_PREFIX + "center");
- removeStyleName(ALIGN_CLASS_PREFIX + "right");
- } else if (alignment.isRight()) {
- addStyleName(ALIGN_CLASS_PREFIX + "right");
- removeStyleName(ALIGN_CLASS_PREFIX + "center");
- } else {
- removeStyleName(ALIGN_CLASS_PREFIX + "right");
- removeStyleName(ALIGN_CLASS_PREFIX + "center");
- }
- if (alignment.isVerticalCenter()) {
- addStyleName(ALIGN_CLASS_PREFIX + "middle");
- removeStyleName(ALIGN_CLASS_PREFIX + "bottom");
- } else if (alignment.isBottom()) {
- addStyleName(ALIGN_CLASS_PREFIX + "bottom");
- removeStyleName(ALIGN_CLASS_PREFIX + "middle");
- } else {
- removeStyleName(ALIGN_CLASS_PREFIX + "middle");
- removeStyleName(ALIGN_CLASS_PREFIX + "bottom");
- }
- }
-
- public void setExpandRatio(double expandRatio) {
- this.expandRatio = expandRatio;
- }
-
- public double getExpandRatio() {
- return expandRatio;
- }
-
- public void setSpacing(boolean spacing) {
- if (spacing && spacer == null) {
- spacer = DOM.createDiv();
- spacer.addClassName("v-spacing");
- getElement().getParentElement().insertBefore(spacer,
- getElement());
- } else if (!spacing && spacer != null) {
- spacer.removeFromParent();
- spacer = null;
- }
- }
-
- public Element getSpacingElement() {
- return spacer;
- }
-
- public boolean hasSpacing() {
- return getSpacingElement() != null;
- }
-
- protected int getSpacingSize(boolean vertical) {
- if (spacer == null) {
- return 0;
- }
-
- if (layoutManager != null) {
- if (vertical) {
- return layoutManager.getOuterHeight(spacer);
- } else {
- return layoutManager.getOuterWidth(spacer);
- }
- }
- // TODO place for optimization (in expense of theme
- // flexibility): only measure one of the elements and cache the
- // value
- return vertical ? spacer.getOffsetHeight() : spacer
- .getOffsetWidth();
- // }
- }
-
- public void setCaptionPosition(CaptionPosition captionPosition) {
- if (caption == null) {
- return;
- }
-
- captionWrap.removeClassName("v-caption-on-"
- + this.captionPosition.name().toLowerCase());
-
- this.captionPosition = captionPosition;
- if (captionPosition == CaptionPosition.BOTTOM
- || captionPosition == CaptionPosition.RIGHT) {
- captionWrap.appendChild(caption);
- } else {
- captionWrap.insertFirst(caption);
- }
-
- captionWrap.addClassName("v-caption-on-"
- + captionPosition.name().toLowerCase());
- }
-
- public CaptionPosition getCaptionPosition() {
- return captionPosition;
- }
-
- // TODO refactor VCaption and use that instead: creates a tight coupling
- // between this layout and Vaadin, but it's already coupled
- public void setCaption(String captionText, String iconUrl,
- List<String> styles, String error, boolean showError,
- boolean required, boolean enabled) {
-
- // TODO place for optimization: check if any of these have changed
- // since last time, and only run those changes
-
- // Caption wrappers
- if (captionText != null || iconUrl != null || error != null
- || required) {
- if (caption == null) {
- caption = DOM.createDiv();
- captionWrap = DOM.createDiv();
- captionWrap.addClassName(BaseTheme.UI_WIDGET);
- captionWrap.addClassName("v-has-caption");
- getElement().appendChild(captionWrap);
- captionWrap.appendChild(getWidget().getElement());
- }
- } else if (caption != null) {
- getElement().appendChild(getWidget().getElement());
- captionWrap.removeFromParent();
- caption = null;
- captionWrap = null;
- }
-
- // Caption text
- if (captionText != null) {
- if (this.captionText == null) {
- this.captionText = DOM.createSpan();
- this.captionText.addClassName("v-captiontext");
- caption.appendChild(this.captionText);
- }
- if (captionText.trim().equals("")) {
- this.captionText.setInnerHTML(" ");
- } else {
- this.captionText.setInnerText(captionText);
- }
- } else if (this.captionText != null) {
- this.captionText.removeFromParent();
- this.captionText = null;
- }
-
- // Icon
- if (iconUrl != null) {
- if (icon == null) {
- icon = new Icon();
- // icon = DOM.createImg();
- // icon.setClassName("v-icon");
- caption.insertFirst(icon.getElement());
- }
- // icon.setAttribute("src", iconUrl);
- icon.setUri(iconUrl);
- } else if (icon != null) {
- icon.getElement().removeFromParent();
- icon = null;
- }
-
- // Required
- if (required) {
- if (requiredIcon == null) {
- requiredIcon = DOM.createSpan();
- // TODO decide something better (e.g. use CSS to insert the
- // character)
- requiredIcon.setInnerHTML("*");
- requiredIcon.setClassName("v-required-field-indicator");
- }
- caption.appendChild(requiredIcon);
- } else if (requiredIcon != null) {
- requiredIcon.removeFromParent();
- requiredIcon = null;
- }
-
- // Error
- if (error != null && showError) {
- if (errorIcon == null) {
- errorIcon = DOM.createSpan();
- errorIcon.setClassName("v-errorindicator");
- }
- caption.appendChild(errorIcon);
- } else if (errorIcon != null) {
- errorIcon.removeFromParent();
- errorIcon = null;
- }
-
- if (caption != null) {
- // Styles
- caption.setClassName("v-caption");
-
- if (styles != null) {
- for (String style : styles) {
- caption.addClassName("v-caption-" + style);
- }
- }
-
- if (enabled) {
- caption.removeClassName("v-disabled");
- } else {
- caption.addClassName("v-disabled");
- }
-
- // Caption position
- if (captionText != null || iconUrl != null) {
- setCaptionPosition(CaptionPosition.TOP);
- } else {
- setCaptionPosition(CaptionPosition.RIGHT);
- }
- }
-
- // TODO theme flexibility: add extra styles to captionWrap as well?
-
- }
-
- public boolean hasCaption() {
- return caption != null;
- }
-
- public Element getCaptionElement() {
- return caption;
- }
-
- public void setRelativeWidth(boolean relativeWidth) {
- updateRelativeSize(relativeWidth, "width");
- }
-
- public void setRelativeHeight(boolean relativeHeight) {
- updateRelativeSize(relativeHeight, "height");
- }
-
- private void updateRelativeSize(boolean isRelativeSize, String direction) {
- if (isRelativeSize && hasCaption()) {
- captionWrap.getStyle().setProperty(
- direction,
- getWidget().getElement().getStyle()
- .getProperty(direction));
- captionWrap.addClassName("v-has-" + direction);
- } else if (hasCaption()) {
- if (direction.equals("height")) {
- captionWrap.getStyle().clearHeight();
- } else {
- captionWrap.getStyle().clearWidth();
- }
- captionWrap.removeClassName("v-has-" + direction);
- captionWrap.getStyle().clearPaddingTop();
- captionWrap.getStyle().clearPaddingRight();
- captionWrap.getStyle().clearPaddingBottom();
- captionWrap.getStyle().clearPaddingLeft();
- caption.getStyle().clearMarginTop();
- caption.getStyle().clearMarginRight();
- caption.getStyle().clearMarginBottom();
- caption.getStyle().clearMarginLeft();
- }
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
- if (DOM.eventGetType(event) == Event.ONLOAD
- && icon.getElement() == DOM.eventGetTarget(event)) {
- if (layoutManager != null) {
- layoutManager.layoutLater();
- } else {
- updateCaptionOffset(caption);
- }
- }
- }
-
- @Override
- protected Element getContainerElement() {
- if (captionWrap == null) {
- return getElement();
- } else {
- return captionWrap;
- }
- }
-
- @Override
- protected void onDetach() {
- if (spacer != null) {
- spacer.removeFromParent();
- }
- super.onDetach();
- }
-
- @Override
- protected void onAttach() {
- super.onAttach();
- if (spacer != null) {
- getElement().getParentElement().insertBefore(spacer,
- getElement());
- }
- }
-
- }
-
- protected class Icon extends UIObject {
- public static final String CLASSNAME = "v-icon";
- private String myUrl;
-
- public Icon() {
- setElement(DOM.createImg());
- DOM.setElementProperty(getElement(), "alt", "");
- setStyleName(CLASSNAME);
- }
-
- public void setUri(String url) {
- if (!url.equals(myUrl)) {
- /*
- * Start sinking onload events, widgets responsibility to react.
- * We must do this BEFORE we set src as IE fires the event
- * immediately if the image is found in cache (#2592).
- */
- sinkEvents(Event.ONLOAD);
-
- DOM.setElementProperty(getElement(), "src", url);
- myUrl = url;
- }
- }
-
- }
-
- void setLayoutManager(LayoutManager manager) {
- layoutManager = manager;
- }
-
- private static final RegExp captionPositionRegexp = RegExp
- .compile("v-caption-on-(\\S+)");
-
- CaptionPosition getCaptionPositionFromElement(Element captionWrap) {
- // Get caption position from the classname
- MatchResult matcher = captionPositionRegexp.exec(captionWrap
- .getClassName());
- if (matcher == null || matcher.getGroupCount() < 2) {
- return CaptionPosition.TOP;
- }
- String captionClass = matcher.getGroup(1);
- CaptionPosition captionPosition = CaptionPosition.valueOf(
- CaptionPosition.class, captionClass.toUpperCase());
- return captionPosition;
- }
-
- void updateCaptionOffset(Element caption) {
-
- Element captionWrap = caption.getParentElement().cast();
-
- Style captionWrapStyle = captionWrap.getStyle();
- captionWrapStyle.clearPaddingTop();
- captionWrapStyle.clearPaddingRight();
- captionWrapStyle.clearPaddingBottom();
- captionWrapStyle.clearPaddingLeft();
-
- Style captionStyle = caption.getStyle();
- captionStyle.clearMarginTop();
- captionStyle.clearMarginRight();
- captionStyle.clearMarginBottom();
- captionStyle.clearMarginLeft();
-
- // Get caption position from the classname
- CaptionPosition captionPosition = getCaptionPositionFromElement(captionWrap);
-
- if (captionPosition == CaptionPosition.LEFT
- || captionPosition == CaptionPosition.RIGHT) {
- int captionWidth;
- if (layoutManager != null) {
- captionWidth = layoutManager.getOuterWidth(caption)
- - layoutManager.getMarginWidth(caption);
- } else {
- captionWidth = caption.getOffsetWidth();
- }
- if (captionWidth > 0) {
- if (captionPosition == CaptionPosition.LEFT) {
- captionWrapStyle.setPaddingLeft(captionWidth, Unit.PX);
- captionStyle.setMarginLeft(-captionWidth, Unit.PX);
- } else {
- captionWrapStyle.setPaddingRight(captionWidth, Unit.PX);
- captionStyle.setMarginRight(-captionWidth, Unit.PX);
- }
- }
- }
- if (captionPosition == CaptionPosition.TOP
- || captionPosition == CaptionPosition.BOTTOM) {
- int captionHeight;
- if (layoutManager != null) {
- captionHeight = layoutManager.getOuterHeight(caption)
- - layoutManager.getMarginHeight(caption);
- } else {
- captionHeight = caption.getOffsetHeight();
- }
- if (captionHeight > 0) {
- if (captionPosition == CaptionPosition.TOP) {
- captionWrapStyle.setPaddingTop(captionHeight, Unit.PX);
- captionStyle.setMarginTop(-captionHeight, Unit.PX);
- } else {
- captionWrapStyle.setPaddingBottom(captionHeight, Unit.PX);
- captionStyle.setMarginBottom(-captionHeight, Unit.PX);
- }
- }
- }
- }
-
- void setMargin(MarginInfo marginInfo) {
- setStyleName("v-margin-top", marginInfo.hasTop());
- setStyleName("v-margin-right", marginInfo.hasRight());
- setStyleName("v-margin-bottom", marginInfo.hasBottom());
- setStyleName("v-margin-left", marginInfo.hasLeft());
- }
-
- protected void setSpacing(boolean spacingEnabled) {
- spacing = spacingEnabled;
- for (Slot slot : widgetToSlot.values()) {
- if (getWidgetIndex(slot) > 0) {
- slot.setSpacing(spacingEnabled);
- }
- }
- }
-
- private void recalculateExpands() {
- double total = 0;
- for (Slot slot : widgetToSlot.values()) {
- if (slot.getExpandRatio() > -1) {
- total += slot.getExpandRatio();
- } else {
- if (vertical) {
- slot.getElement().getStyle().clearHeight();
- } else {
- slot.getElement().getStyle().clearWidth();
- }
- }
- }
- for (Slot slot : widgetToSlot.values()) {
- if (slot.getExpandRatio() > -1) {
- if (vertical) {
- slot.setHeight((100 * (slot.getExpandRatio() / total))
- + "%");
- if (slot.connector.isRelativeHeight()) {
- layoutManager.setNeedsMeasure(slot.connector);
- }
- } else {
- slot.setWidth((100 * (slot.getExpandRatio() / total)) + "%");
- if (slot.connector.isRelativeWidth()) {
- layoutManager.setNeedsMeasure(slot.connector);
- }
- }
- }
- }
- }
-
- private Element expandWrapper;
-
- void clearExpand() {
- if (expandWrapper != null) {
- for (; expandWrapper.getChildCount() > 0;) {
- Element el = expandWrapper.getChild(0).cast();
- getElement().appendChild(el);
- if (vertical) {
- el.getStyle().clearHeight();
- el.getStyle().clearMarginTop();
- } else {
- el.getStyle().clearWidth();
- el.getStyle().clearMarginLeft();
- }
- }
- expandWrapper.removeFromParent();
- expandWrapper = null;
- }
- }
-
- public void updateExpand() {
- boolean isExpanding = false;
- for (Widget slot : getChildren()) {
- if (((Slot) slot).getExpandRatio() > -1) {
- isExpanding = true;
- } else {
- if (vertical) {
- slot.getElement().getStyle().clearHeight();
- } else {
- slot.getElement().getStyle().clearWidth();
- }
- }
- slot.getElement().getStyle().clearMarginLeft();
- slot.getElement().getStyle().clearMarginTop();
- }
-
- if (isExpanding) {
- if (expandWrapper == null) {
- expandWrapper = DOM.createDiv();
- expandWrapper.setClassName("v-expand");
- for (; getElement().getChildCount() > 0;) {
- Node el = getElement().getChild(0);
- expandWrapper.appendChild(el);
- }
- getElement().appendChild(expandWrapper);
- }
-
- int totalSize = 0;
- for (Widget w : getChildren()) {
- Slot slot = (Slot) w;
- if (slot.getExpandRatio() == -1) {
- if (layoutManager != null) {
- // TODO check caption position
- if (vertical) {
- int size = layoutManager.getOuterHeight(slot
- .getWidget().getElement())
- - layoutManager.getMarginHeight(slot
- .getWidget().getElement());
- if (slot.hasCaption()) {
- size += layoutManager.getOuterHeight(slot
- .getCaptionElement())
- - layoutManager.getMarginHeight(slot
- .getCaptionElement());
- }
- if (size > 0) {
- totalSize += size;
- }
- } else {
- int max = -1;
- max = layoutManager.getOuterWidth(slot.getWidget()
- .getElement())
- - layoutManager.getMarginWidth(slot
- .getWidget().getElement());
- if (slot.hasCaption()) {
- int max2 = layoutManager.getOuterWidth(slot
- .getCaptionElement())
- - layoutManager.getMarginWidth(slot
- .getCaptionElement());
- max = Math.max(max, max2);
- }
- if (max > 0) {
- totalSize += max;
- }
- }
- } else {
- totalSize += vertical ? slot.getOffsetHeight() : slot
- .getOffsetWidth();
- }
- }
- // TODO fails in Opera, always returns 0
- int spacingSize = slot.getSpacingSize(vertical);
- if (spacingSize > 0) {
- totalSize += spacingSize;
- }
- }
-
- // When we set the margin to the first child, we don't need
- // overflow:hidden in the layout root element, since the wrapper
- // would otherwise be placed outside of the layout root element
- // and block events on elements below it.
- if (vertical) {
- expandWrapper.getStyle().setPaddingTop(totalSize, Unit.PX);
- expandWrapper.getFirstChildElement().getStyle()
- .setMarginTop(-totalSize, Unit.PX);
- } else {
- expandWrapper.getStyle().setPaddingLeft(totalSize, Unit.PX);
- expandWrapper.getFirstChildElement().getStyle()
- .setMarginLeft(-totalSize, Unit.PX);
- }
-
- recalculateExpands();
- }
- }
-
- public void recalculateLayoutHeight() {
- // Only needed if a horizontal layout is undefined high, and contains
- // relative height children or vertical alignments
- if (vertical || definedHeight) {
- return;
- }
-
- boolean hasRelativeHeightChildren = false;
- boolean hasVAlign = false;
-
- for (Widget slot : getChildren()) {
- Widget widget = ((Slot) slot).getWidget();
- String h = widget.getElement().getStyle().getHeight();
- if (h != null && h.indexOf("%") > -1) {
- hasRelativeHeightChildren = true;
- }
- AlignmentInfo a = ((Slot) slot).getAlignment();
- if (a != null && (a.isVerticalCenter() || a.isBottom())) {
- hasVAlign = true;
- }
- }
-
- if (hasRelativeHeightChildren || hasVAlign) {
- int newHeight;
- if (layoutManager != null) {
- newHeight = layoutManager.getOuterHeight(getElement())
- - layoutManager.getMarginHeight(getElement());
- } else {
- newHeight = getElement().getOffsetHeight();
- }
- VBoxLayout.this.getElement().getStyle()
- .setHeight(newHeight, Unit.PX);
- }
-
- }
-
- void clearHeight() {
- getElement().getStyle().clearHeight();
- }
-
- @Override
- public void setHeight(String height) {
- super.setHeight(height);
- definedHeight = (height != null && !"".equals(height));
- }
-}
*/
package com.vaadin.client.ui.orderedlayout;
-public class VHorizontalLayout extends VMeasuringOrderedLayout {
-
- public static final String CLASSNAME = "v-horizontallayout";
+/**
+ * Represents a layout where the children is ordered vertically
+ */
+public class VHorizontalLayout extends VOrderedLayout {
+ /**
+ * Default constructor
+ */
public VHorizontalLayout() {
- super(CLASSNAME, false);
+ setVertical(false);
}
-
}
+++ /dev/null
-/*
- * Copyright 2011 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.vaadin.client.ui.orderedlayout;
-
-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.Node;
-import com.google.gwt.dom.client.Style;
-import com.google.gwt.dom.client.Style.Position;
-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.google.gwt.user.client.ui.WidgetCollection;
-import com.vaadin.client.VCaption;
-import com.vaadin.client.ui.layout.VLayoutSlot;
-import com.vaadin.shared.ui.MarginInfo;
-
-public class VMeasuringOrderedLayout extends ComplexPanel {
-
- final boolean isVertical;
-
- final DivElement spacingMeasureElement;
-
- private Map<Widget, VLayoutSlot> widgetToSlot = new HashMap<Widget, VLayoutSlot>();
-
- protected VMeasuringOrderedLayout(String className, boolean isVertical) {
- DivElement element = Document.get().createDivElement();
- setElement(element);
-
- spacingMeasureElement = Document.get().createDivElement();
- Style spacingStyle = spacingMeasureElement.getStyle();
- spacingStyle.setPosition(Position.ABSOLUTE);
- getElement().appendChild(spacingMeasureElement);
-
- setStyleName(className);
- this.isVertical = isVertical;
- }
-
- public void addOrMove(VLayoutSlot layoutSlot, int index) {
- Widget widget = layoutSlot.getWidget();
- Element wrapperElement = layoutSlot.getWrapperElement();
-
- Element containerElement = getElement();
- Node childAtIndex = containerElement.getChild(index);
- if (childAtIndex != wrapperElement) {
- // Insert at correct location not attached or at wrong location
- containerElement.insertBefore(wrapperElement, childAtIndex);
- insert(widget, wrapperElement, index, false);
- }
-
- widgetToSlot.put(widget, layoutSlot);
- }
-
- private void togglePrefixedStyleName(String name, boolean enabled) {
- if (enabled) {
- addStyleDependentName(name);
- } else {
- removeStyleDependentName(name);
- }
- }
-
- void updateMarginStyleNames(MarginInfo 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) {
- String styleName = getStylePrimaryName();
- if (spacingEnabled) {
- spacingMeasureElement.addClassName(styleName + "-spacing-on");
- spacingMeasureElement.removeClassName(styleName + "-spacing-off");
- } else {
- spacingMeasureElement.removeClassName(styleName + "-spacing-on");
- spacingMeasureElement.addClassName(styleName + "-spacing-off");
- }
- }
-
- public void removeSlotForWidget(Widget widget) {
- VLayoutSlot slot = getSlotForChild(widget);
- VCaption caption = slot.getCaption();
- if (caption != null) {
- // Must remove using setCaption to ensure dependencies (layout ->
- // caption) are unregistered
- slot.setCaption(null);
- }
-
- remove(slot.getWidget());
- getElement().removeChild(slot.getWrapperElement());
- widgetToSlot.remove(widget);
- }
-
- public VLayoutSlot getSlotForChild(Widget widget) {
- return widgetToSlot.get(widget);
- }
-
- 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 endPadding) {
- 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;
-
- WidgetCollection children = getChildren();
- for (int i = 0; i < children.size(); i++) {
- Widget child = children.get(i);
- 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 endLocation = currentLocation + extraPixels;
- if (!slot.isRelativeInDirection(isVertical)) {
- endLocation += slot.getUsedSizeInDirection(isVertical);
- }
-
- /*
- * currentLocation and allocatedSpace are used with full precision
- * to avoid missing pixels in the end. The pixel dimensions passed
- * to the DOM are still rounded. Otherwise e.g. 10.5px start
- * position + 10.5px space might be cause the component to go 1px
- * beyond the edge as the effect of the browser's rounding may cause
- * something similar to 11px + 11px.
- *
- * It's most efficient to use doubles all the way because native
- * javascript emulates other number types using doubles.
- */
- double roundedLocation = Math.round(currentLocation);
-
- /*
- * Space is calculated as the difference between rounded start and
- * end locations. Just rounding the space would cause e.g. 10.5px +
- * 10.5px = 21px -> 11px + 11px = 22px but in this way we get 11px +
- * 10px = 21px.
- */
- double roundedSpace = Math.round(endLocation) - roundedLocation;
-
- // Reserve room for the padding if we're at the end
- double slotEndMargin;
- if (i == children.size() - 1) {
- slotEndMargin = endPadding;
- } else {
- slotEndMargin = 0;
- }
-
- slot.positionInDirection(roundedLocation, roundedSpace,
- slotEndMargin, isVertical);
-
- currentLocation = endLocation + spacingSize;
- }
-
- return allocatedSize;
- }
-
- public int layoutSecondaryDirection(int allocatedSize, int startPadding,
- int endPadding) {
- 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, endPadding,
- !isVertical);
- }
-
- return allocatedSize;
- }
-}
--- /dev/null
+/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.ui.orderedlayout;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gwt.dom.client.Node;
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.regexp.shared.MatchResult;
+import com.google.gwt.regexp.shared.RegExp;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.SimplePanel;
+import com.google.gwt.user.client.ui.UIObject;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.LayoutManager;
+import com.vaadin.client.Util;
+import com.vaadin.shared.ui.AlignmentInfo;
+import com.vaadin.shared.ui.MarginInfo;
+import com.vaadin.ui.themes.BaseTheme;
+
+/**
+ * Base class for ordered layouts
+ */
+public class VOrderedLayout extends FlowPanel {
+
+ public static final String CLASSNAME = "v-boxlayout";
+
+ private static final String ALIGN_CLASS_PREFIX = "v-align-";
+
+ protected boolean spacing = false;
+
+ protected boolean vertical = true;
+
+ protected boolean definedHeight = false;
+
+ private Map<Widget, Slot> widgetToSlot = new HashMap<Widget, Slot>();
+
+ private Element expandWrapper;
+
+ private LayoutManager layoutManager;
+
+ /**
+ * Constructor
+ */
+ public VOrderedLayout() {
+ setStyleName(CLASSNAME);
+ setVertical(true);
+ }
+
+ /**
+ * Does the layout order its children horizontally or vertically
+ *
+ * @param vertical
+ * true to order the childer vertically, false to order them
+ * horizontally
+ *
+ */
+ protected void setVertical(boolean vertical) {
+ this.vertical = vertical;
+ if (vertical) {
+ addStyleName("v-vertical");
+ removeStyleName("v-horizontal");
+ } else {
+ addStyleName("v-horizontal");
+ removeStyleName("v-vertical");
+ }
+ }
+
+ /**
+ * Add or move a slot to another index
+ *
+ * @param slot
+ * The slot to move or add
+ * @param index
+ * The index where the slot should be placed
+ */
+ void addOrMoveSlot(Slot slot, int index) {
+ if (slot.getParent() == this) {
+ int currentIndex = getWidgetIndex(slot);
+ if (index == currentIndex) {
+ return;
+ }
+ }
+ insert(slot, index);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void insert(Widget child, Element container, int beforeIndex,
+ boolean domInsert) {
+ // Validate index; adjust if the widget is already a child of this
+ // panel.
+ beforeIndex = adjustIndex(child, beforeIndex);
+
+ // Detach new child.
+ child.removeFromParent();
+
+ // Logical attach.
+ getChildren().insert(child, beforeIndex);
+
+ // Physical attach.
+ container = expandWrapper != null ? expandWrapper : getElement();
+ if (domInsert) {
+ DOM.insertChild(container, child.getElement(),
+ spacing ? beforeIndex * 2 : beforeIndex);
+ } else {
+ DOM.appendChild(container, child.getElement());
+ }
+
+ // Adopt.
+ adopt(child);
+ }
+
+ /**
+ * Remove a slot from the layout
+ *
+ * @param widget
+ * @return
+ */
+ public void removeWidget(Widget widget) {
+ Slot slot = widgetToSlot.get(widget);
+ remove(slot);
+ widgetToSlot.remove(widget);
+ }
+
+ /**
+ * Get the containing slot for a widget
+ *
+ * @param widget
+ * The widget whose slot you want to get
+ *
+ * @return
+ */
+ public Slot getSlot(Widget widget) {
+ Slot slot = widgetToSlot.get(widget);
+ if (slot == null) {
+ slot = new Slot(widget, this);
+ widgetToSlot.put(widget, slot);
+ }
+ return slot;
+ }
+
+ /**
+ * Defines where the caption should be placed
+ */
+ public enum CaptionPosition {
+ TOP, RIGHT, BOTTOM, LEFT
+ }
+
+ /**
+ * Represents a slot which contains the actual widget in the layout.
+ */
+ public static final class Slot extends SimplePanel {
+
+ private Element spacer;
+ private Element captionWrap;
+ private Element caption;
+ private Element captionText;
+ private Icon icon;
+ private Element errorIcon;
+ private Element requiredIcon;
+ private final VOrderedLayout layout;
+
+ // Caption is placed after component unless there is some part which
+ // moves it above.
+ private CaptionPosition captionPosition = CaptionPosition.RIGHT;
+
+ private AlignmentInfo alignment;
+
+ private double expandRatio = -1;
+
+ /**
+ * Constructor
+ *
+ * @param widget
+ * The widget to put in the slot
+ *
+ * @param layoutManager
+ * The layout manager used by the layout
+ */
+ private Slot(Widget widget, VOrderedLayout layout) {
+ this.layout = layout;
+ setWidget(widget);
+ setStylePrimaryName("v-slot");
+ }
+
+ /**
+ * Returns the alignment for the slot
+ *
+ */
+ public AlignmentInfo getAlignment() {
+ return alignment;
+ }
+
+ /**
+ * Sets how the widget is aligned inside the slot
+ *
+ * @param alignment
+ * The alignment inside the slot
+ */
+ public void setAlignment(AlignmentInfo alignment) {
+ this.alignment = alignment;
+
+ if (alignment.isHorizontalCenter()) {
+ addStyleName(ALIGN_CLASS_PREFIX + "center");
+ removeStyleName(ALIGN_CLASS_PREFIX + "right");
+ } else if (alignment.isRight()) {
+ addStyleName(ALIGN_CLASS_PREFIX + "right");
+ removeStyleName(ALIGN_CLASS_PREFIX + "center");
+ } else {
+ removeStyleName(ALIGN_CLASS_PREFIX + "right");
+ removeStyleName(ALIGN_CLASS_PREFIX + "center");
+ }
+ if (alignment.isVerticalCenter()) {
+ addStyleName(ALIGN_CLASS_PREFIX + "middle");
+ removeStyleName(ALIGN_CLASS_PREFIX + "bottom");
+ } else if (alignment.isBottom()) {
+ addStyleName(ALIGN_CLASS_PREFIX + "bottom");
+ removeStyleName(ALIGN_CLASS_PREFIX + "middle");
+ } else {
+ removeStyleName(ALIGN_CLASS_PREFIX + "middle");
+ removeStyleName(ALIGN_CLASS_PREFIX + "bottom");
+ }
+ }
+
+ /**
+ * Set how the slot should be expanded relative to the other slots
+ *
+ * @param expandRatio
+ * The ratio of the space the slot should occupy
+ *
+ */
+ public void setExpandRatio(double expandRatio) {
+ this.expandRatio = expandRatio;
+ }
+
+ /**
+ * Get the expand ratio for the slot. The expand ratio describes how the
+ * slot should be resized compared to other slots in the layout
+ *
+ * @return
+ */
+ public double getExpandRatio() {
+ return expandRatio;
+ }
+
+ /**
+ * Set the spacing for the slot. The spacing determines if there should
+ * be empty space around the slot when the slot.
+ *
+ * @param spacing
+ * Should spacing be enabled
+ */
+ public void setSpacing(boolean spacing) {
+ if (spacing && spacer == null) {
+ spacer = DOM.createDiv();
+ spacer.addClassName("v-spacing");
+ getElement().getParentElement().insertBefore(spacer,
+ getElement());
+ } else if (!spacing && spacer != null) {
+ spacer.removeFromParent();
+ spacer = null;
+ }
+ }
+
+ /**
+ * Get the element which is added to make the spacing
+ *
+ * @return
+ */
+ public Element getSpacingElement() {
+ return spacer;
+ }
+
+ /**
+ * Does the slot have spacing
+ */
+ public boolean hasSpacing() {
+ return getSpacingElement() != null;
+ }
+
+ /**
+ * Get the vertical amount in pixels of the spacing
+ */
+ protected int getVerticalSpacing() {
+ if (spacer == null) {
+ return 0;
+ } else if (layout.getLayoutManager() != null) {
+ return layout.getLayoutManager().getOuterHeight(spacer);
+ }
+ return spacer.getOffsetHeight();
+ }
+
+ /**
+ * Get the horizontal amount of pixels of the spacing
+ *
+ * @return
+ */
+ protected int getHorizontalSpacing() {
+ if (spacer == null) {
+ return 0;
+ } else if (layout.getLayoutManager() != null) {
+ return layout.getLayoutManager().getOuterWidth(spacer);
+ }
+ return spacer.getOffsetWidth();
+ }
+
+ /**
+ * Set the position of the caption relative to the slot
+ *
+ * @param captionPosition
+ * The position of the caption
+ */
+ public void setCaptionPosition(CaptionPosition captionPosition) {
+ if (caption == null) {
+ return;
+ }
+ captionWrap.removeClassName("v-caption-on-"
+ + this.captionPosition.name().toLowerCase());
+
+ this.captionPosition = captionPosition;
+ if (captionPosition == CaptionPosition.BOTTOM
+ || captionPosition == CaptionPosition.RIGHT) {
+ captionWrap.appendChild(caption);
+ } else {
+ captionWrap.insertFirst(caption);
+ }
+
+ captionWrap.addClassName("v-caption-on-"
+ + captionPosition.name().toLowerCase());
+ }
+
+ /**
+ * Get the position of the caption relative to the slot
+ */
+ public CaptionPosition getCaptionPosition() {
+ return captionPosition;
+ }
+
+ /**
+ * Set the caption of the slot
+ *
+ * @param captionText
+ * The text of the caption
+ * @param iconUrl
+ * The icon URL
+ * @param styles
+ * The style names
+ * @param error
+ * The error message
+ * @param showError
+ * Should the error message be shown
+ * @param required
+ * Is the (field) required
+ * @param enabled
+ * Is the component enabled
+ */
+ public void setCaption(String captionText, String iconUrl,
+ List<String> styles, String error, boolean showError,
+ boolean required, boolean enabled) {
+
+ // TODO place for optimization: check if any of these have changed
+ // since last time, and only run those changes
+
+ // Caption wrappers
+ if (captionText != null || iconUrl != null || error != null
+ || required) {
+ if (caption == null) {
+ caption = DOM.createDiv();
+ captionWrap = DOM.createDiv();
+ captionWrap.addClassName(BaseTheme.UI_WIDGET);
+ captionWrap.addClassName("v-has-caption");
+ getElement().appendChild(captionWrap);
+ captionWrap.appendChild(getWidget().getElement());
+ }
+ } else if (caption != null) {
+ getElement().appendChild(getWidget().getElement());
+ captionWrap.removeFromParent();
+ caption = null;
+ captionWrap = null;
+ }
+
+ // Caption text
+ if (captionText != null) {
+ if (this.captionText == null) {
+ this.captionText = DOM.createSpan();
+ this.captionText.addClassName("v-captiontext");
+ caption.appendChild(this.captionText);
+ }
+ if (captionText.trim().equals("")) {
+ this.captionText.setInnerHTML(" ");
+ } else {
+ this.captionText.setInnerText(captionText);
+ }
+ } else if (this.captionText != null) {
+ this.captionText.removeFromParent();
+ this.captionText = null;
+ }
+
+ // Icon
+ if (iconUrl != null) {
+ if (icon == null) {
+ icon = new Icon();
+ caption.insertFirst(icon.getElement());
+ }
+ icon.setUri(iconUrl);
+ } else if (icon != null) {
+ icon.getElement().removeFromParent();
+ icon = null;
+ }
+
+ // Required
+ if (required) {
+ if (requiredIcon == null) {
+ requiredIcon = DOM.createSpan();
+ // TODO decide something better (e.g. use CSS to insert the
+ // character)
+ requiredIcon.setInnerHTML("*");
+ requiredIcon.setClassName("v-required-field-indicator");
+ }
+ caption.appendChild(requiredIcon);
+ } else if (requiredIcon != null) {
+ requiredIcon.removeFromParent();
+ requiredIcon = null;
+ }
+
+ // Error
+ if (error != null && showError) {
+ if (errorIcon == null) {
+ errorIcon = DOM.createSpan();
+ errorIcon.setClassName("v-errorindicator");
+ }
+ caption.appendChild(errorIcon);
+ } else if (errorIcon != null) {
+ errorIcon.removeFromParent();
+ errorIcon = null;
+ }
+
+ if (caption != null) {
+ // Styles
+ caption.setClassName("v-caption");
+
+ if (styles != null) {
+ for (String style : styles) {
+ caption.addClassName("v-caption-" + style);
+ }
+ }
+
+ if (enabled) {
+ caption.removeClassName("v-disabled");
+ } else {
+ caption.addClassName("v-disabled");
+ }
+
+ // Caption position
+ if (captionText != null || iconUrl != null) {
+ setCaptionPosition(CaptionPosition.TOP);
+ } else {
+ setCaptionPosition(CaptionPosition.RIGHT);
+ }
+ }
+ }
+
+ /**
+ * Does the slot have a caption
+ */
+ public boolean hasCaption() {
+ return caption != null;
+ }
+
+ /**
+ * Get the slots caption element
+ */
+ public Element getCaptionElement() {
+ return caption;
+ }
+
+ /**
+ * Set if the slot has a relative width
+ *
+ * @param relativeWidth
+ * True if slot uses relative width, false if the slot has a
+ * static width
+ */
+ private boolean relativeWidth = false;
+ protected void setRelativeWidth(boolean relativeWidth) {
+ this.relativeWidth = relativeWidth;
+ updateRelativeSize(relativeWidth, "width");
+ }
+
+ /**
+ * Set if the slot has a relative height
+ *
+ * @param relativeHeight
+ * Trie if the slot uses a relative height, false if the slot
+ * has a static height
+ */
+ private boolean relativeHeight = false;
+ protected void setRelativeHeight(boolean relativeHeight) {
+ this.relativeHeight = relativeHeight;
+ updateRelativeSize(relativeHeight, "height");
+ }
+
+ /**
+ * Updates the captions size if the slot is relative
+ *
+ * @param isRelativeSize
+ * Is the slot relatived sized
+ * @param direction
+ * The directorion of the caption
+ */
+ private void updateRelativeSize(boolean isRelativeSize, String direction) {
+ if (isRelativeSize && hasCaption()) {
+ captionWrap.getStyle().setProperty(
+ direction,
+ getWidget().getElement().getStyle()
+ .getProperty(direction));
+ captionWrap.addClassName("v-has-" + direction);
+ } else if (hasCaption()) {
+ if (direction.equals("height")) {
+ captionWrap.getStyle().clearHeight();
+ } else {
+ captionWrap.getStyle().clearWidth();
+ }
+ captionWrap.removeClassName("v-has-" + direction);
+ captionWrap.getStyle().clearPaddingTop();
+ captionWrap.getStyle().clearPaddingRight();
+ captionWrap.getStyle().clearPaddingBottom();
+ captionWrap.getStyle().clearPaddingLeft();
+ caption.getStyle().clearMarginTop();
+ caption.getStyle().clearMarginRight();
+ caption.getStyle().clearMarginBottom();
+ caption.getStyle().clearMarginLeft();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt
+ * .user.client.Event)
+ */
+ @Override
+ public void onBrowserEvent(Event event) {
+ super.onBrowserEvent(event);
+ if (DOM.eventGetType(event) == Event.ONLOAD
+ && icon.getElement() == DOM.eventGetTarget(event)) {
+ if (layout.getLayoutManager() != null) {
+ layout.getLayoutManager().layoutLater();
+ } else {
+ layout.updateCaptionOffset(caption);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.SimplePanel#getContainerElement()
+ */
+ @Override
+ protected Element getContainerElement() {
+ if (captionWrap == null) {
+ return getElement();
+ } else {
+ return captionWrap;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.Widget#onDetach()
+ */
+ @Override
+ protected void onDetach() {
+ if (spacer != null) {
+ spacer.removeFromParent();
+ }
+ super.onDetach();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.Widget#onAttach()
+ */
+ @Override
+ protected void onAttach() {
+ super.onAttach();
+ if (spacer != null) {
+ getElement().getParentElement().insertBefore(spacer,
+ getElement());
+ }
+ }
+ }
+
+ /**
+ * The icon for each widget. Located in the caption of the slot.
+ */
+ public static class Icon extends UIObject {
+
+ public static final String CLASSNAME = "v-icon";
+
+ private String myUrl;
+
+ /**
+ * Constructor
+ */
+ public Icon() {
+ setElement(DOM.createImg());
+ DOM.setElementProperty(getElement(), "alt", "");
+ setStyleName(CLASSNAME);
+ }
+
+ /**
+ * Set the URL where the icon is located
+ *
+ * @param url
+ * A fully qualified URL
+ */
+ public void setUri(String url) {
+ if (!url.equals(myUrl)) {
+ /*
+ * Start sinking onload events, widgets responsibility to react.
+ * We must do this BEFORE we set src as IE fires the event
+ * immediately if the image is found in cache (#2592).
+ */
+ sinkEvents(Event.ONLOAD);
+
+ DOM.setElementProperty(getElement(), "src", url);
+ myUrl = url;
+ }
+ }
+ }
+
+ /**
+ * Set the layout manager for the layout
+ *
+ * @param manager
+ * The layout manager to use
+ */
+ public void setLayoutManager(LayoutManager manager) {
+ layoutManager = manager;
+ }
+
+ /**
+ * Get the layout manager used by this layout
+ *
+ */
+ public LayoutManager getLayoutManager() {
+ return layoutManager;
+ }
+
+ /**
+ * Deducts the caption position by examining the wrapping element
+ *
+ * @param captionWrap
+ * The wrapping element
+ *
+ * @return The caption position
+ */
+ CaptionPosition getCaptionPositionFromElement(Element captionWrap) {
+ RegExp captionPositionRegexp = RegExp.compile("v-caption-on-(\\S+)");
+
+ // Get caption position from the classname
+ MatchResult matcher = captionPositionRegexp.exec(captionWrap
+ .getClassName());
+ if (matcher == null || matcher.getGroupCount() < 2) {
+ return CaptionPosition.TOP;
+ }
+ String captionClass = matcher.getGroup(1);
+ CaptionPosition captionPosition = CaptionPosition.valueOf(
+ CaptionPosition.class, captionClass.toUpperCase());
+ return captionPosition;
+ }
+
+ /**
+ * Update the offset off the caption relative to the slot
+ *
+ * @param caption
+ * The caption element
+ */
+ void updateCaptionOffset(Element caption) {
+
+ Element captionWrap = caption.getParentElement().cast();
+
+ Style captionWrapStyle = captionWrap.getStyle();
+ captionWrapStyle.clearPaddingTop();
+ captionWrapStyle.clearPaddingRight();
+ captionWrapStyle.clearPaddingBottom();
+ captionWrapStyle.clearPaddingLeft();
+
+ Style captionStyle = caption.getStyle();
+ captionStyle.clearMarginTop();
+ captionStyle.clearMarginRight();
+ captionStyle.clearMarginBottom();
+ captionStyle.clearMarginLeft();
+
+ // Get caption position from the classname
+ CaptionPosition captionPosition = getCaptionPositionFromElement(captionWrap);
+
+ if (captionPosition == CaptionPosition.LEFT
+ || captionPosition == CaptionPosition.RIGHT) {
+ int captionWidth;
+ if (layoutManager != null) {
+ captionWidth = layoutManager.getOuterWidth(caption)
+ - layoutManager.getMarginWidth(caption);
+ } else {
+ captionWidth = caption.getOffsetWidth();
+ }
+ if (captionWidth > 0) {
+ if (captionPosition == CaptionPosition.LEFT) {
+ captionWrapStyle.setPaddingLeft(captionWidth, Unit.PX);
+ captionStyle.setMarginLeft(-captionWidth, Unit.PX);
+ } else {
+ captionWrapStyle.setPaddingRight(captionWidth, Unit.PX);
+ captionStyle.setMarginRight(-captionWidth, Unit.PX);
+ }
+ }
+ }
+ if (captionPosition == CaptionPosition.TOP
+ || captionPosition == CaptionPosition.BOTTOM) {
+ int captionHeight;
+ if (layoutManager != null) {
+ captionHeight = layoutManager.getOuterHeight(caption)
+ - layoutManager.getMarginHeight(caption);
+ } else {
+ captionHeight = caption.getOffsetHeight();
+ }
+ if (captionHeight > 0) {
+ if (captionPosition == CaptionPosition.TOP) {
+ captionWrapStyle.setPaddingTop(captionHeight, Unit.PX);
+ captionStyle.setMarginTop(-captionHeight, Unit.PX);
+ } else {
+ captionWrapStyle.setPaddingBottom(captionHeight, Unit.PX);
+ captionStyle.setMarginBottom(-captionHeight, Unit.PX);
+ }
+ }
+ }
+ }
+
+ /**
+ * Set the margin of the layout
+ *
+ * @param marginInfo
+ * The margin information
+ */
+ public void setMargin(MarginInfo marginInfo) {
+ if (marginInfo != null) {
+ setStyleName("v-margin-top", marginInfo.hasTop());
+ setStyleName("v-margin-right", marginInfo.hasRight());
+ setStyleName("v-margin-bottom", marginInfo.hasBottom());
+ setStyleName("v-margin-left", marginInfo.hasLeft());
+ }
+ }
+
+ /**
+ * Turn on or off spacing in the layout
+ *
+ * @param spacing
+ * True if spacing should be used, false if not
+ */
+ public void setSpacing(boolean spacing) {
+ this.spacing = spacing;
+ for (Slot slot : widgetToSlot.values()) {
+ if (getWidgetIndex(slot) > 0) {
+ slot.setSpacing(spacing);
+ }
+ }
+ }
+
+ /**
+ * Triggers a recalculation of the expand width and heights
+ */
+ private void recalculateExpands() {
+ double total = 0;
+ for (Slot slot : widgetToSlot.values()) {
+ if (slot.getExpandRatio() > -1) {
+ total += slot.getExpandRatio();
+ } else {
+ if (vertical) {
+ slot.getElement().getStyle().clearHeight();
+ } else {
+ slot.getElement().getStyle().clearWidth();
+ }
+ }
+ }
+ for (Slot slot : widgetToSlot.values()) {
+ if (slot.getExpandRatio() > -1) {
+ if (vertical) {
+ slot.setHeight((100 * (slot.getExpandRatio() / total))
+ + "%");
+ if (slot.relativeHeight) {
+ Util.notifyParentOfSizeChange(this, true);
+ }
+ } else {
+ slot.setWidth((100 * (slot.getExpandRatio() / total)) + "%");
+ if (slot.relativeWidth) {
+ Util.notifyParentOfSizeChange(this, true);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes elements used to expand a slot
+ */
+ void clearExpand() {
+ if (expandWrapper != null) {
+ for (; expandWrapper.getChildCount() > 0;) {
+ Element el = expandWrapper.getChild(0).cast();
+ getElement().appendChild(el);
+ if (vertical) {
+ el.getStyle().clearHeight();
+ el.getStyle().clearMarginTop();
+ } else {
+ el.getStyle().clearWidth();
+ el.getStyle().clearMarginLeft();
+ }
+ }
+ expandWrapper.removeFromParent();
+ expandWrapper = null;
+ }
+ }
+
+ /**
+ * Adds elements used to expand a slot
+ */
+ public void updateExpand() {
+ boolean isExpanding = false;
+ for (Widget slot : getChildren()) {
+ if (((Slot) slot).getExpandRatio() > -1) {
+ isExpanding = true;
+ } else {
+ if (vertical) {
+ slot.getElement().getStyle().clearHeight();
+ } else {
+ slot.getElement().getStyle().clearWidth();
+ }
+ }
+ slot.getElement().getStyle().clearMarginLeft();
+ slot.getElement().getStyle().clearMarginTop();
+ }
+
+ if (isExpanding) {
+ if (expandWrapper == null) {
+ expandWrapper = DOM.createDiv();
+ expandWrapper.setClassName("v-expand");
+ for (; getElement().getChildCount() > 0;) {
+ Node el = getElement().getChild(0);
+ expandWrapper.appendChild(el);
+ }
+ getElement().appendChild(expandWrapper);
+ }
+
+ int totalSize = 0;
+ for (Widget w : getChildren()) {
+ Slot slot = (Slot) w;
+ if (slot.getExpandRatio() == -1) {
+
+ if (layoutManager != null) {
+ // TODO check caption position
+ if (vertical) {
+ int size = layoutManager.getOuterHeight(slot
+ .getWidget().getElement())
+ - layoutManager.getMarginHeight(slot
+ .getWidget().getElement());
+ if (slot.hasCaption()) {
+ size += layoutManager.getOuterHeight(slot
+ .getCaptionElement())
+ - layoutManager.getMarginHeight(slot
+ .getCaptionElement());
+ }
+ if (size > 0) {
+ totalSize += size;
+ }
+ } else {
+ int max = -1;
+ max = layoutManager.getOuterWidth(slot.getWidget()
+ .getElement())
+ - layoutManager.getMarginWidth(slot
+ .getWidget().getElement());
+ if (slot.hasCaption()) {
+ int max2 = layoutManager.getOuterWidth(slot
+ .getCaptionElement())
+ - layoutManager.getMarginWidth(slot
+ .getCaptionElement());
+ max = Math.max(max, max2);
+ }
+ if (max > 0) {
+ totalSize += max;
+ }
+ }
+ } else {
+ totalSize += vertical ? slot.getOffsetHeight() : slot
+ .getOffsetWidth();
+ }
+ }
+ // TODO fails in Opera, always returns 0
+ int spacingSize = vertical ? slot.getVerticalSpacing() : slot
+ .getHorizontalSpacing();
+ if (spacingSize > 0) {
+ totalSize += spacingSize;
+ }
+ }
+
+ // When we set the margin to the first child, we don't need
+ // overflow:hidden in the layout root element, since the wrapper
+ // would otherwise be placed outside of the layout root element
+ // and block events on elements below it.
+ if (vertical) {
+ expandWrapper.getStyle().setPaddingTop(totalSize, Unit.PX);
+ expandWrapper.getFirstChildElement().getStyle()
+ .setMarginTop(-totalSize, Unit.PX);
+ } else {
+ expandWrapper.getStyle().setPaddingLeft(totalSize, Unit.PX);
+ expandWrapper.getFirstChildElement().getStyle()
+ .setMarginLeft(-totalSize, Unit.PX);
+ }
+
+ recalculateExpands();
+ }
+ }
+
+ /**
+ * Perform a recalculation of the layout height
+ */
+ public void recalculateLayoutHeight() {
+ // Only needed if a horizontal layout is undefined high, and contains
+ // relative height children or vertical alignments
+ if (vertical || definedHeight) {
+ return;
+ }
+
+ boolean hasRelativeHeightChildren = false;
+ boolean hasVAlign = false;
+
+ for (Widget slot : getChildren()) {
+ Widget widget = ((Slot) slot).getWidget();
+ String h = widget.getElement().getStyle().getHeight();
+ if (h != null && h.indexOf("%") > -1) {
+ hasRelativeHeightChildren = true;
+ }
+ AlignmentInfo a = ((Slot) slot).getAlignment();
+ if (a != null && (a.isVerticalCenter() || a.isBottom())) {
+ hasVAlign = true;
+ }
+ }
+
+ if (hasRelativeHeightChildren || hasVAlign) {
+ int newHeight;
+ if (layoutManager != null) {
+ newHeight = layoutManager.getOuterHeight(getElement())
+ - layoutManager.getMarginHeight(getElement());
+ } else {
+ newHeight = getElement().getOffsetHeight();
+ }
+ VOrderedLayout.this.getElement().getStyle()
+ .setHeight(newHeight, Unit.PX);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setHeight(String height) {
+ super.setHeight(height);
+ definedHeight = (height != null && !"".equals(height));
+ }
+}
*/
package com.vaadin.client.ui.orderedlayout;
-public class VVerticalLayout extends VMeasuringOrderedLayout {
-
- public static final String CLASSNAME = "v-verticallayout";
+/**
+ * Represents a layout where the children is ordered vertically
+ */
+public class VVerticalLayout extends VOrderedLayout {
+ /**
+ * Default constructor
+ */
public VVerticalLayout() {
- super(CLASSNAME, true);
+ setVertical(true);
}
-
}
+++ /dev/null
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.client.ui.orderedlayout;
-
-import com.vaadin.shared.ui.Connect;
-import com.vaadin.shared.ui.Connect.LoadStyle;
-import com.vaadin.ui.VerticalLayout;
-
-@Connect(value = VerticalLayout.class, loadStyle = LoadStyle.EAGER)
-public class VerticalBoxLayoutConnector extends AbstractBoxLayoutConnector {
-
- @Override
- public void init() {
- super.init();
- getWidget().setVertical(true);
- }
-
-}
*/
package com.vaadin.client.ui.orderedlayout;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.Connect.LoadStyle;
+import com.vaadin.ui.VerticalLayout;
-//@Connect(value = VerticalLayout.class, loadStyle = LoadStyle.EAGER)
+/**
+ * Connects the client widget {@link VVerticalLayout} with the Vaadin server
+ * side counterpart {@link VerticalLayout}
+ */
+@Connect(value = VerticalLayout.class, loadStyle = LoadStyle.EAGER)
public class VerticalLayoutConnector extends AbstractOrderedLayoutConnector {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.client.ui.orderedlayout.AbstractOrderedLayoutConnector#getWidget
+ * ()
+ */
@Override
public VVerticalLayout getWidget() {
return (VVerticalLayout) super.getWidget();