From cbc8c2da27a74025f54c3be902289d5db72fca6b Mon Sep 17 00:00:00 2001 From: Jouni Koivuviita Date: Sun, 20 May 2012 22:13:31 +0300 Subject: [PATCH] Extensive refactoring of BoxLayout Reduced many unnecessary element resize listeners and layout methods. Refactored ComponentConnector style name handling so that it will now only alter the style names and not completely override them on each update. --- .../base/absolutelayout/absolutelayout.css | 3 +- .../themes/base/boxlayout/boxlayout.css | 28 +- WebContent/VAADIN/themes/base/label/label.css | 4 + .../terminal/gwt/client/ComponentState.java | 20 + .../terminal/gwt/client/LayoutManager.java | 3 + .../client/ui/AbstractBoxLayoutConnector.java | 471 ++++++++---------- .../client/ui/AbstractComponentConnector.java | 57 ++- .../ui/HorizontalBoxLayoutConnector.java | 11 - .../terminal/gwt/client/ui/VBoxLayout.java | 6 +- .../client/ui/VerticalBoxLayoutConnector.java | 11 - .../orderedlayout/BoxLayoutTest.java | 33 +- .../orderedlayout/LayoutResizeTest.java | 3 +- 12 files changed, 337 insertions(+), 313 deletions(-) diff --git a/WebContent/VAADIN/themes/base/absolutelayout/absolutelayout.css b/WebContent/VAADIN/themes/base/absolutelayout/absolutelayout.css index 637d829d78..0eb557560e 100644 --- a/WebContent/VAADIN/themes/base/absolutelayout/absolutelayout.css +++ b/WebContent/VAADIN/themes/base/absolutelayout/absolutelayout.css @@ -1,5 +1,6 @@ /* THIS IS HERE ONLY BECAUSE WE WANT TO DEFINE IT FIRST, TO MAKE IT EASY TO OVERRIDE */ -.v-connector { +/* TODO fix by using a better build script that allows us to define the order of the imports */ +.v { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; diff --git a/WebContent/VAADIN/themes/base/boxlayout/boxlayout.css b/WebContent/VAADIN/themes/base/boxlayout/boxlayout.css index 3188d68520..f899e8f4ac 100644 --- a/WebContent/VAADIN/themes/base/boxlayout/boxlayout.css +++ b/WebContent/VAADIN/themes/base/boxlayout/boxlayout.css @@ -20,8 +20,8 @@ TODO display: inline-block; } -.v-boxlayout.v-horizontal { - white-space: nowrap !important; +div.v-boxlayout.v-horizontal.v { + white-space: nowrap; } .v-boxlayout > .v-expand { @@ -40,7 +40,7 @@ TODO } /* Clear any floats inside the slot, to prevent unwanted collapsing */ -.v-slot:after { +.v-vertical > .v-slot:after { content: ""; display: inline-block; clear: both; @@ -88,16 +88,18 @@ TODO white-space: nowrap; } -.v-align-middle > .v-connector, -.v-align-bottom > .v-connector { +.v-align-middle > .v, +.v-align-bottom > .v { display: inline-block; } -.v-align-middle > .v-connector { +.v-align-middle, +.v-align-middle > .v { vertical-align: middle; } -.v-align-bottom > .v-connector { +.v-align-bottom, +.v-align-bottom > .v { vertical-align: bottom; } @@ -105,7 +107,7 @@ TODO text-align: center; } -.v-align-center > .v-connector { +.v-align-center > .v { margin-left: auto; margin-right: auto; } @@ -114,7 +116,7 @@ TODO text-align: right; } -.v-align-right > .v-connector { +.v-align-right > .v { margin-left: auto; } @@ -146,17 +148,17 @@ TODO padding-left: .5em; } -.v-caption-on-left > .v-connector, -.v-caption-on-right > .v-connector { +.v-caption-on-left > .v, +.v-caption-on-right > .v { display: inline-block; vertical-align: middle; } -.v-has-caption.v-has-width > .v-connector { +.v-has-caption.v-has-width > .v { width: 100% !important; } -.v-has-caption.v-has-height > .v-connector { +.v-has-caption.v-has-height > .v { height: 100% !important; } diff --git a/WebContent/VAADIN/themes/base/label/label.css b/WebContent/VAADIN/themes/base/label/label.css index 366dbdf26f..953584ffd7 100644 --- a/WebContent/VAADIN/themes/base/label/label.css +++ b/WebContent/VAADIN/themes/base/label/label.css @@ -1,3 +1,7 @@ .v-label { overflow: hidden; +} + +.v-label.v-has-width { + white-space: normal; } \ No newline at end of file diff --git a/src/com/vaadin/terminal/gwt/client/ComponentState.java b/src/com/vaadin/terminal/gwt/client/ComponentState.java index 10cd14251b..7f01300d68 100644 --- a/src/com/vaadin/terminal/gwt/client/ComponentState.java +++ b/src/com/vaadin/terminal/gwt/client/ComponentState.java @@ -81,6 +81,16 @@ public class ComponentState extends SharedState { return "".equals(getHeight()); } + /** + * Returns true if the component height is relative to the parent, i.e. + * percentage, false if it is fixed/auto. + * + * @return true if component height is relative (percentage) + */ + public boolean isRelativeHeight() { + return getHeight().endsWith("%"); + } + /** * Returns the component width as set by the server. * @@ -119,6 +129,16 @@ public class ComponentState extends SharedState { return "".equals(getWidth()); } + /** + * Returns true if the component width is relative to the parent, i.e. + * percentage, false if it is fixed/auto. + * + * @return true if component width is relative (percentage) + */ + public boolean isRelativeWidth() { + return getWidth().endsWith("%"); + } + /** * Returns true if the component is in read-only mode. * diff --git a/src/com/vaadin/terminal/gwt/client/LayoutManager.java b/src/com/vaadin/terminal/gwt/client/LayoutManager.java index 0a2e90f2f2..239a948a10 100644 --- a/src/com/vaadin/terminal/gwt/client/LayoutManager.java +++ b/src/com/vaadin/terminal/gwt/client/LayoutManager.java @@ -277,6 +277,9 @@ public class LayoutManager { for (Element element : listenersToFire) { Collection listeners = elementResizeListeners .get(element); + if (listeners == null) { + continue; + } ElementResizeListener[] array = listeners .toArray(new ElementResizeListener[listeners.size()]); ElementResizeEvent event = new ElementResizeEvent(this, diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractBoxLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractBoxLayoutConnector.java index 26ec96003e..752e567f4c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/AbstractBoxLayoutConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractBoxLayoutConnector.java @@ -12,13 +12,9 @@ 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.terminal.gwt.client.AbstractFieldState; -import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.ComponentConnector; import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ValueMap; import com.vaadin.terminal.gwt.client.communication.RpcProxy; import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler; @@ -30,8 +26,7 @@ import com.vaadin.terminal.gwt.client.ui.orderedlayout.AbstractOrderedLayoutServ import com.vaadin.terminal.gwt.client.ui.orderedlayout.AbstractOrderedLayoutState; public abstract class AbstractBoxLayoutConnector extends - AbstractLayoutConnector implements Paintable, /* PreLayoutListener, */ -PostLayoutListener { + AbstractLayoutConnector /* implements PostLayoutListener */{ AbstractOrderedLayoutServerRpc rpc; @@ -105,103 +100,6 @@ PostLayoutListener { */ private HashMap childCaptionElementHeight = new HashMap(); - // For debugging - private static int resizeCount = 0; - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (!isRealUpdate(uidl)) { - return; - } - - clickEventHandler.handleEventHandlerRegistration(); - - VBoxLayout layout = getWidget(); - - ValueMap expandRatios = uidl.getMapAttribute("expandRatios"); - ValueMap alignments = uidl.getMapAttribute("alignments"); - - for (ComponentConnector child : getChildren()) { - Slot slot = layout.getSlot(child); - String pid = child.getConnectorId(); - - AlignmentInfo alignment; - if (alignments.containsKey(pid)) { - alignment = new AlignmentInfo(alignments.getInt(pid)); - if (alignment.isVerticalCenter() || alignment.isBottom()) { - hasVerticalAlignment.add(child); - } else { - hasVerticalAlignment.remove(child); - } - } else { - alignment = AlignmentInfo.TOP_LEFT; - hasVerticalAlignment.remove(child); - } - slot.setAlignment(alignment); - - double expandRatio; - // TODO discuss the layout specs, is this what we want: distribute - // extra space equally if no expand ratios are specified inside a - // layout with specified size - if (expandRatios.getKeySet().size() == 0 - && ((getWidget().vertical && !isUndefinedHeight()) || (!getWidget().vertical && !isUndefinedWidth()))) { - expandRatio = 1; - hasExpandRatio.add(child); - } else if (expandRatios.containsKey(pid) - && expandRatios.getRawNumber(pid) > 0) { - expandRatio = expandRatios.getRawNumber(pid); - hasExpandRatio.add(child); - } else { - expandRatio = -1; - hasExpandRatio.remove(child); - if (expandRatios.getKeySet().size() > 0 - || hasExpandRatio.size() > 0) { - // Only add resize listeners if there are expand ratios in - // use - getLayoutManager().addElementResizeListener( - child.getWidget().getElement(), - childComponentResizeListener); - if (slot.hasCaption()) { - getLayoutManager().addElementResizeListener( - slot.getCaptionElement(), - slotCaptionResizeListener); - } - } - } - slot.setExpandRatio(expandRatio); - - // TODO only needed if expand ratios are used - if (slot.getSpacingElement() != null) { - getLayoutManager().addElementResizeListener( - slot.getSpacingElement(), spacingResizeListener); - } else if (slot.getSpacingElement() != null) { - getLayoutManager().removeElementResizeListener( - slot.getSpacingElement(), spacingResizeListener); - } - - } - - if (needsFixedHeight()) { - for (ComponentConnector child : getChildren()) { - Slot slot = layout.getSlot(child); - getLayoutManager().addElementResizeListener( - child.getWidget().getElement(), - childComponentResizeListener); - if (slot.hasCaption()) { - getLayoutManager() - .addElementResizeListener(slot.getCaptionElement(), - slotCaptionResizeListener); - } - } - } - - if (needsExpand()) { - updateExpand(); - } else { - getWidget().clearExpand(); - } - - } - public void updateCaption(ComponentConnector child) { Slot slot = getWidget().getSlot(child); @@ -241,19 +139,9 @@ PostLayoutListener { getWidget().updateCaptionOffset(slot.getCaptionElement()); } } else { - // getLayoutManager().removeElementResizeListener( - // slot.getCaptionElement(), slotCaptionResizeListener); - } - - if (!slot.hasCaption()) { childCaptionElementHeight.remove(child.getWidget().getElement()); } - if (needsFixedHeight()) { - getWidget().clearHeight(); - getLayoutManager().setNeedsMeasure(this); - } - updateLayoutHeight(); if (needsExpand()) { @@ -270,7 +158,6 @@ PostLayoutListener { VBoxLayout layout = getWidget(); for (ComponentConnector child : getChildren()) { - Widget childWidget = child.getWidget(); Slot slot = layout.getSlot(child); if (slot.getParent() != layout) { child.addStateChangeHandler(childStateChangeHandler); @@ -306,8 +193,9 @@ PostLayoutListener { } } + // If some component is added/removed, we need to recalculate the expand if (needsExpand()) { - getWidget().updateExpand(); + updateExpand(); } else { getWidget().clearExpand(); } @@ -318,22 +206,55 @@ PostLayoutListener { public void onStateChanged(StateChangeEvent stateChangeEvent) { super.onStateChanged(stateChangeEvent); + clickEventHandler.handleEventHandlerRegistration(); + getWidget().setMargin(new VMarginInfo(getState().getMarginsBitmask())); getWidget().setSpacing(getState().isSpacing()); - if (needsFixedHeight()) { - getWidget().clearHeight(); - setLayoutHeightListener(true); - getLayoutManager().setNeedsMeasure(this); - } else { - setLayoutHeightListener(false); + hasExpandRatio.clear(); + hasVerticalAlignment.clear(); + hasRelativeHeight.clear(); + needsMeasure.clear(); + + for (ComponentConnector child : getChildren()) { + Slot slot = getWidget().getSlot(child); + + AlignmentInfo alignment = new AlignmentInfo(getState() + .getChildData().get(child).getAlignmentBitmask()); + slot.setAlignment(alignment); + + double expandRatio = getState().getChildData().get(child) + .getExpandRatio(); + 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()); + } } - // TODO recognize special cases here, using child states + updateAllSlotListeners(); + + updateLayoutHeight(); } StateChangeHandler childStateChangeHandler = new StateChangeHandler() { public void onStateChanged(StateChangeEvent stateChangeEvent) { + ComponentConnector child = (ComponentConnector) stateChangeEvent .getConnector(); @@ -344,77 +265,30 @@ PostLayoutListener { 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()); - } - } - - // TODO 'needsExpand' might return false during the first render, - // since updateFromUidl is called last - - // 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 - if ((child.isRelativeHeight() || needsFixedHeight()) - && slot.hasCaption()) { - getLayoutManager().addElementResizeListener( - slot.getCaptionElement(), slotCaptionResizeListener); - } else if (!needsExpand()) { - // TODO recheck if removing the listener here breaks anything. - // Should be cleaned up. - // getLayoutManager().removeElementResizeListener( - // slot.getCaptionElement(), slotCaptionResizeListener); - } - - if (slot.getSpacingElement() != null && needsExpand()) { - // Spacing is on - getLayoutManager().addElementResizeListener( - slot.getSpacingElement(), spacingResizeListener); - } else if (slot.getSpacingElement() != null) { - getLayoutManager().removeElementResizeListener( - slot.getSpacingElement(), spacingResizeListener); - } - - if (child.isRelativeHeight()) { - hasRelativeHeight.add(child); - needsMeasure.remove(child.getWidget().getElement()); - } else { - hasRelativeHeight.remove(child); - needsMeasure.add(child.getWidget().getElement()); - } - - if (needsFixedHeight()) { - getLayoutManager().addElementResizeListener( - child.getWidget().getElement(), - childComponentResizeListener); - } else if (!needsExpand()) { - getLayoutManager().removeElementResizeListener( - child.getWidget().getElement(), - childComponentResizeListener); - } - - if (needsFixedHeight()) { - getWidget().clearHeight(); - setLayoutHeightListener(true); - getLayoutManager().setNeedsMeasure( - AbstractBoxLayoutConnector.this); - } else { - setLayoutHeightListener(false); - } + // 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); } }; private boolean needsFixedHeight() { - if (!getWidget().vertical - && isUndefinedHeight() - && (hasRelativeHeight.size() > 0 || hasVerticalAlignment.size() > 0)) { + if (!getWidget().vertical && isUndefinedHeight() + && (hasRelativeHeight.size() > 0 /* + * || + * hasVerticalAlignment.size() + * > 0 + */)) { return true; } return false; @@ -426,72 +300,121 @@ PostLayoutListener { return hasExpandRatio.size() > 0 && canApplyExpand; } - // public void preLayout() { - // resizeCount = 0; - // } + private void updateAllSlotListeners() { + for (ComponentConnector child : getChildren()) { + updateSlotListeners(child); + } + // if (needsFixedHeight()) { + // getWidget().clearHeight(); + // setLayoutHeightListener(true); + // getLayoutManager().setNeedsMeasure(AbstractBoxLayoutConnector.this); + // } else { + // setLayoutHeightListener(false); + // } + } - public void postLayout() { - if (needsFixedHeight()) { - // Re-measure all elements that are available - for (Element el : needsMeasure) { - childElementHeight.put(el, getLayoutManager() - .getOuterHeight(el)); + /** + * 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); - Element captionElement = el.getParentElement() - .getFirstChildElement().cast(); - if (captionElement.getClassName().contains("v-caption")) { - childCaptionElementHeight.put(el, getLayoutManager() - .getOuterHeight(captionElement)); - } + // 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); } - System.out.println(" ### Child sizes: " - + childElementHeight.values().toString()); - System.out.println(" ### Caption sizes: " - + childCaptionElementHeight.values().toString()); - - // If no height has been set, use the natural height for the - // component (this is mostly just a precaution so that something - // renders correctly) - // String h = getWidget().getElement().getStyle().getHeight(); - // if (h == null || h.equals("")) { - // int height = getLayoutManager().getOuterHeight( - // getWidget().getElement()) - // - getLayoutManager().getMarginHeight( - // getWidget().getElement()); - int height = getMaxHeight() - + getLayoutManager().getBorderHeight( - getWidget().getElement()) - + getLayoutManager().getPaddingHeight( - getWidget().getElement()); - getWidget().getElement().getStyle().setHeight(height, Unit.PX); - // } + } 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); } - // System.err.println("Element resize listeners fired for " + - // resizeCount - // + " times"); - } - private ElementResizeListener layoutResizeListener = new ElementResizeListener() { - public void onElementResize(ElementResizeEvent e) { - resizeCount++; - updateLayoutHeight(); - if (needsExpand() && (isUndefinedHeight() || isUndefinedWidth())) { - updateExpand(); + 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() { public void onElementResize(ElementResizeEvent e) { - resizeCount++; + // 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(); @@ -499,8 +422,7 @@ PostLayoutListener { if (captionElement == widgetElement) { // Caption element already detached - getLayoutManager().removeElementResizeListener(captionElement, - slotCaptionResizeListener); + dontListen(captionElement, slotCaptionResizeListener); childCaptionElementHeight.remove(widgetElement); return; } @@ -519,13 +441,12 @@ PostLayoutListener { int h = getLayoutManager().getOuterHeight(captionElement) - getLayoutManager().getMarginHeight(captionElement); childCaptionElementHeight.put(widgetElement, h); - // System.out.println("Caption size: " + h); - if (needsFixedHeight()) { - getWidget().clearHeight(); - getLayoutManager().setNeedsMeasure( - AbstractBoxLayoutConnector.this); - } + // if (needsFixedHeight()) { + // getWidget().clearHeight(); + // getLayoutManager().setNeedsMeasure( + // AbstractBoxLayoutConnector.this); + // } updateLayoutHeight(); @@ -537,7 +458,6 @@ PostLayoutListener { private ElementResizeListener childComponentResizeListener = new ElementResizeListener() { public void onElementResize(ElementResizeEvent e) { - resizeCount++; int h = getLayoutManager().getOuterHeight(e.getElement()); childElementHeight.put((Element) e.getElement().cast(), h); updateLayoutHeight(); @@ -550,7 +470,6 @@ PostLayoutListener { private ElementResizeListener spacingResizeListener = new ElementResizeListener() { public void onElementResize(ElementResizeEvent e) { - resizeCount++; if (needsExpand()) { updateExpand(); } @@ -576,8 +495,12 @@ PostLayoutListener { } private int getMaxHeight() { + // TODO should use layout manager instead of inner lists of element + // sizes int highestNonRelative = -1; int highestRelative = -1; + // System.out.println("Child sizes: " + // + childElementHeight.values().toString()); for (Element el : childElementHeight.keySet()) { // TODO would be more efficient to measure the slot element if both // caption and child widget elements need to be measured. Keeping @@ -616,44 +539,48 @@ PostLayoutListener { public void onUnregister() { // Cleanup all ElementResizeListeners - getLayoutManager().removeElementResizeListener( - getWidget().getElement(), layoutResizeListener); - - for (int i = 0; i < getWidget().getWidgetCount(); i++) { - // TODO unsafe - Slot slot = (Slot) getWidget().getWidget(i); + // dontListen(getWidget().getElement(), layoutResizeListener); + for (ComponentConnector child : getChildren()) { + Slot slot = getWidget().getSlot(child); if (slot.hasCaption()) { - getLayoutManager().removeElementResizeListener( - slot.getCaptionElement(), slotCaptionResizeListener); + dontListen(slot.getCaptionElement(), slotCaptionResizeListener); } if (slot.getSpacingElement() != null) { - getLayoutManager().removeElementResizeListener( - slot.getSpacingElement(), spacingResizeListener); + dontListen(slot.getSpacingElement(), spacingResizeListener); } - getLayoutManager() - .removeElementResizeListener(slot.getWidget().getElement(), - childComponentResizeListener); - + dontListen(slot.getWidget().getElement(), + childComponentResizeListener); } super.onUnregister(); } - private void setLayoutHeightListener(boolean add) { - if (add) { - getLayoutManager().addElementResizeListener( - getWidget().getElement(), layoutResizeListener); - } else { - getLayoutManager().removeElementResizeListener( - getWidget().getElement(), layoutResizeListener); - if (!needsExpand()) { - childElementHeight.clear(); - childCaptionElementHeight.clear(); - } - } + // 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); } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java index d690bdded1..1caec0428e 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java @@ -3,6 +3,8 @@ */ package com.vaadin.terminal.gwt.client.ui; +import java.util.LinkedList; +import java.util.List; import java.util.Set; import com.google.gwt.user.client.ui.Focusable; @@ -31,6 +33,8 @@ public abstract class AbstractComponentConnector extends AbstractConnector private String lastKnownWidth = ""; private String lastKnownHeight = ""; + List styleNames; + /** * Default constructor */ @@ -97,8 +101,9 @@ public abstract class AbstractComponentConnector extends AbstractConnector setWidgetEnabled(isEnabled()); // Style names - String styleName = getStyleNames(getWidget().getStylePrimaryName()); - getWidget().setStyleName(styleName); + // String styleName = getStyleNames(getWidget().getStylePrimaryName()); + // getWidget().setStyleName(styleName); + updateStyleNames(); // Update tooltip TooltipInfo tooltipInfo = paintableMap.getTooltipInfo(this, null); @@ -270,6 +275,54 @@ public abstract class AbstractComponentConnector extends AbstractConnector return styleBuf.toString(); } + protected void updateStyleNames() { + Widget widget = getWidget(); + + widget.addStyleName("v"); + + // Disabled + if (!isEnabled()) { + widget.addStyleName(ApplicationConnection.DISABLED_CLASSNAME); + } else { + widget.removeStyleName(ApplicationConnection.DISABLED_CLASSNAME); + } + + // Read-only + if (isReadOnly()) { + widget.addStyleName("v-readonly"); + } else { + widget.removeStyleName("v-readonly"); + } + + // Error + if (null != getState().getErrorMessage()) { + widget.addStyleDependentName("error"); + } else { + widget.removeStyleDependentName("error"); + } + + // Additional style names + List newStyleNames = getState().getStyles(); + if (newStyleNames == null) { + newStyleNames = new LinkedList(); + } + if (styleNames != null) { + // Remove previous styles which are no longer in the current list + for (String style : styleNames) { + if (!newStyleNames.contains(style)) { + widget.removeStyleName(style); + widget.removeStyleDependentName(style); + } + } + } + // Add any new styles + for (String style : newStyleNames) { + widget.addStyleName(style); + widget.addStyleDependentName(style); + } + styleNames = newStyleNames; + } + /* * (non-Javadoc) * diff --git a/src/com/vaadin/terminal/gwt/client/ui/HorizontalBoxLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/HorizontalBoxLayoutConnector.java index dd15528cf7..53477571ed 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/HorizontalBoxLayoutConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/HorizontalBoxLayoutConnector.java @@ -3,8 +3,6 @@ */ package com.vaadin.terminal.gwt.client.ui; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.ui.Connect.LoadStyle; import com.vaadin.ui.HorizontalLayout; @@ -17,13 +15,4 @@ public class HorizontalBoxLayoutConnector extends AbstractBoxLayoutConnector { getWidget().setVertical(false); } - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // TODO remove when Vaadin style name handling is improved so that it - // won't override extra client side style names - getWidget().setVertical(false); - super.updateFromUIDL(uidl, client); - getWidget().setVertical(false); - } - } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VBoxLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VBoxLayout.java index 3a6beaa48a..c49587c29b 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VBoxLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VBoxLayout.java @@ -187,6 +187,10 @@ public class VBoxLayout extends FlowPanel { return spacer; } + public boolean hasSpacing() { + return getSpacingElement() != null; + } + protected int getSpacingSize(boolean vertical) { if (spacer == null) { return 0; @@ -246,7 +250,7 @@ public class VBoxLayout extends FlowPanel { if (caption == null) { caption = DOM.createDiv(); captionWrap = DOM.createDiv(); - captionWrap.addClassName("v-connector"); + captionWrap.addClassName("v"); captionWrap.addClassName("v-has-caption"); getElement().appendChild(captionWrap); captionWrap.appendChild(getWidget().getElement()); diff --git a/src/com/vaadin/terminal/gwt/client/ui/VerticalBoxLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/VerticalBoxLayoutConnector.java index 7e10680afb..9953b02b2d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VerticalBoxLayoutConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VerticalBoxLayoutConnector.java @@ -3,8 +3,6 @@ */ package com.vaadin.terminal.gwt.client.ui; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.ui.Connect.LoadStyle; import com.vaadin.ui.VerticalLayout; @@ -17,13 +15,4 @@ public class VerticalBoxLayoutConnector extends AbstractBoxLayoutConnector { getWidget().setVertical(true); } - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // TODO fix when Vaadin style name handling is improved so that it won't - // override extra client side style names - getWidget().setVertical(true); - super.updateFromUIDL(uidl, client); - getWidget().setVertical(true); - } - } diff --git a/tests/testbench/com/vaadin/tests/components/orderedlayout/BoxLayoutTest.java b/tests/testbench/com/vaadin/tests/components/orderedlayout/BoxLayoutTest.java index 6b3f1efde7..5e2de2f262 100644 --- a/tests/testbench/com/vaadin/tests/components/orderedlayout/BoxLayoutTest.java +++ b/tests/testbench/com/vaadin/tests/components/orderedlayout/BoxLayoutTest.java @@ -11,6 +11,7 @@ import com.vaadin.event.LayoutEvents.LayoutClickListener; import com.vaadin.terminal.ThemeResource; import com.vaadin.terminal.UserError; import com.vaadin.terminal.WrappedRequest; +import com.vaadin.terminal.gwt.client.ui.label.ContentMode; import com.vaadin.tests.components.AbstractTestRoot; import com.vaadin.ui.AbstractComponent; import com.vaadin.ui.AbstractField; @@ -23,7 +24,6 @@ import com.vaadin.ui.Component; import com.vaadin.ui.GridLayout; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; -import com.vaadin.ui.Label.ContentMode; import com.vaadin.ui.NativeSelect; import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; @@ -61,10 +61,36 @@ public class BoxLayoutTest extends AbstractTestRoot { view.addComponent(createTestLayout(false)); view.setExpandRatio(view.getComponent(1), 1); + // for (int i = 0; i < 20; i++) { + // view.addComponent(createHorizontalTest()); + // } + setContent(view); getApplication().setRootPreserved(true); } + private Component createHorizontalTest() { + HorizontalLayout l = new HorizontalLayout(); + l.setWidth("100%"); + + Label exp; + + // l.addComponent(new Embedded(null, new ThemeResource( + // "../runo/icons/32/document.png"))); + l.addComponent(exp = new Label( + "Mauris iaculis porttitor posuere. Praesent id metus massa, ut blandit odio. Proin quis tortor orci. Etiam at risus et justo dignissim congue. Donec.")); + // exp.setWidth("300px"); + l.addComponent(new Button("Edit")); + l.addComponent(new Button("Delete")); + l.setExpandRatio(exp, 1); + + for (int i = 0; i < l.getComponentCount(); i++) { + l.setComponentAlignment(l.getComponent(i), Alignment.MIDDLE_LEFT); + } + + return l; + } + protected AbstractOrderedLayout createControls(boolean horizontal) { VerticalLayout root = new VerticalLayout(); root.setSpacing(true); @@ -344,6 +370,11 @@ public class BoxLayoutTest extends AbstractTestRoot { }); component.addComponent(componentRequired); + for (int i = 0; i < component.getComponentCount(); i++) { + component.setComponentAlignment(component.getComponent(i), + Alignment.MIDDLE_LEFT); + } + return root; } diff --git a/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutResizeTest.java b/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutResizeTest.java index 70777b6441..c493b03eb5 100644 --- a/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutResizeTest.java +++ b/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutResizeTest.java @@ -1,6 +1,7 @@ package com.vaadin.tests.components.orderedlayout; import com.vaadin.terminal.ThemeResource; +import com.vaadin.terminal.gwt.client.ui.label.ContentMode; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; @@ -32,7 +33,7 @@ public class LayoutResizeTest extends TestBase { left.setMargin(true); left.addComponent(new Label("

Layout resize test

", - Label.ContentMode.XHTML)); + ContentMode.XHTML)); Button resize = new Button("Resize to 700x400", new Button.ClickListener() { -- 2.39.5