From: Leif Åstrand Date: Mon, 27 Feb 2012 12:02:33 +0000 (+0200) Subject: Merge branch 'layoutperformance' X-Git-Tag: 7.0.0.alpha2~434 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=773044eacc3986d768bf6668da1c201d2bbb19bf;p=vaadin-framework.git Merge branch 'layoutperformance' Conflicts: src/com/vaadin/terminal/gwt/client/ApplicationConnection.java src/com/vaadin/terminal/gwt/client/Util.java src/com/vaadin/terminal/gwt/client/VCaption.java src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java src/com/vaadin/terminal/gwt/client/ui/VOrderedLayoutPaintable.java src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java src/com/vaadin/terminal/gwt/client/ui/layout/CellBasedLayoutPaintable.java src/com/vaadin/terminal/gwt/client/ui/layout/ChildComponentContainer.java --- 773044eacc3986d768bf6668da1c201d2bbb19bf diff --cc src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index cecfcfd39a,24683b0c9c..372a7a39f5 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@@ -1002,53 -996,11 +1003,54 @@@ public class ApplicationConnection JsArray changes = json.getJSValueMapArray("changes"); ArrayList updatedVPaintableWidgets = new ArrayList(); - relativeSizeChanges.clear(); componentCaptionSizeChanges.clear(); + Duration updateDuration = new Duration(); + int length = changes.length(); + + // create paintables if necessary + for (int i = 0; i < length; i++) { + try { + final UIDL change = changes.get(i).cast(); + final UIDL uidl = change.getChildUIDL(0); + VPaintable paintable = paintableMap.getPaintable(uidl + .getId()); + if (null == paintable + && !uidl.getTag().equals( + configuration.getEncodedWindowTag())) { + // create, initialize and register the paintable + getPaintable(uidl); + } + } catch (final Throwable e) { + VConsole.error(e); + } + } + + // set states for all paintables mentioned in "state" + ValueMap states = json.getValueMap("state"); + JsArrayString keyArray = states.getKeyArray(); + for (int i = 0; i < keyArray.length(); i++) { + try { + String paintableId = keyArray.get(i); + VPaintable paintable = paintableMap + .getPaintable(paintableId); + if (null != paintable) { + + JSONArray stateDataAndType = new JSONArray( + states.getJavaScriptObject(paintableId)); + + Object state = JsonDecoder.convertValue( + stateDataAndType, paintableMap); + + paintable.setState((SharedState) state); + } + } catch (final Throwable e) { + VConsole.error(e); + } + } + + // update paintables for (int i = 0; i < length; i++) { try { final UIDL change = changes.get(i).cast(); diff --cc src/com/vaadin/terminal/gwt/client/Util.java index be78959830,a3604b6b63..a563a534d5 --- a/src/com/vaadin/terminal/gwt/client/Util.java +++ b/src/com/vaadin/terminal/gwt/client/Util.java @@@ -5,12 -5,7 +5,8 @@@ package com.vaadin.terminal.gwt.client; import java.util.ArrayList; +import java.util.Arrays; - import java.util.HashMap; - import java.util.HashSet; - import java.util.Iterator; - import java.util.Map; - import java.util.Set; + import java.util.List; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; diff --cc src/com/vaadin/terminal/gwt/client/VCaption.java index 6e2c4a02d2,286d3fc17f..21f1e453b8 --- a/src/com/vaadin/terminal/gwt/client/VCaption.java +++ b/src/com/vaadin/terminal/gwt/client/VCaption.java @@@ -34,40 -30,19 +32,45 @@@ public class VCaption extends HTML private int maxWidth = -1; - private static final String CLASSNAME_CLEAR = CLASSNAME + "-clearelem"; + protected static final String ATTRIBUTE_ICON = "icon"; + protected static final String ATTRIBUTE_CAPTION = "caption"; + protected static final String ATTRIBUTE_DESCRIPTION = "description"; + protected static final String ATTRIBUTE_REQUIRED = "required"; + protected static final String ATTRIBUTE_ERROR = "error"; + protected static final String ATTRIBUTE_HIDEERRORS = "hideErrors"; + private enum InsertPosition { + ICON, CAPTION, REQUIRED, ERROR + } + + /** + * Creates a caption that is not linked to a {@link VPaintableWidget}. + * + * When using this constructor, {@link #getOwner()} returns null. + * + * @param client + * ApplicationConnection + * @deprecated all captions should be associated with a paintable widget and + * be updated from shared state, not UIDL + */ + @Deprecated + public VCaption(ApplicationConnection client) { + super(); + this.client = client; + owner = null; + + setStyleName(CLASSNAME); + sinkEvents(VTooltip.TOOLTIP_EVENTS); + + } + /** + * Creates a caption for a {@link VPaintableWidget}. * * @param component - * optional owner of caption. If not set, getOwner will return - * null + * owner of caption, not null * @param client + * ApplicationConnection */ public VCaption(VPaintableWidget component, ApplicationConnection client) { super(); @@@ -257,118 -225,6 +254,112 @@@ } + @Deprecated + public boolean updateCaptionWithoutOwner(UIDL uidl, String caption, + boolean disabled, boolean hasDescription) { + // TODO temporary method, needed because some tabsheet and accordion + // internal captions do not have an owner or shared state. Simplified to + // only support those cases + setVisible(!uidl.getBooleanAttribute("invisible")); + + boolean wasPlacedAfterComponent = placedAfterComponent; + + // Caption is placed after component unless there is some part which + // moves it above. + placedAfterComponent = true; + + String style = VCaption.CLASSNAME; + if (disabled) { + style += " " + ApplicationConnection.DISABLED_CLASSNAME; + } + setStyleName(style); + if (hasDescription) { + if (captionText != null) { + addStyleDependentName("hasdescription"); + } else { + removeStyleDependentName("hasdescription"); + } + } + boolean hasIcon = uidl + .hasAttribute(VAbstractPaintableWidget.ATTRIBUTE_ICON); + boolean showError = uidl + .hasAttribute(VAbstractPaintableWidget.ATTRIBUTE_ERROR) + && !uidl.getBooleanAttribute(VAbstractPaintableWidget.ATTRIBUTE_HIDEERRORS); + + if (hasIcon) { + if (icon == null) { + icon = new Icon(client); + icon.setWidth("0"); + icon.setHeight("0"); + + DOM.insertChild(getElement(), icon.getElement(), + getInsertPosition(InsertPosition.ICON)); + } + // Icon forces the caption to be above the component + placedAfterComponent = false; + + icon.setUri(uidl + .getStringAttribute(VAbstractPaintableWidget.ATTRIBUTE_ICON)); + + } else if (icon != null) { + // Remove existing + DOM.removeChild(getElement(), icon.getElement()); + icon = null; + } + + if (caption != null) { + // A caption text should be shown if the attribute is set + // If the caption is null the ATTRIBUTE_CAPTION should not be set to + // avoid ending up here. + + if (captionText == null) { + captionText = DOM.createDiv(); + captionText.setClassName("v-captiontext"); + + DOM.insertChild(getElement(), captionText, + getInsertPosition(InsertPosition.CAPTION)); + } + + // Update caption text + // A text forces the caption to be above the component. + placedAfterComponent = false; + if (caption.trim().equals("")) { + // This is required to ensure that the caption uses space in all + // browsers when it is set to the empty string. If there is an + // icon, error indicator or required indicator they will ensure + // that space is reserved. + if (!hasIcon && !showError) { + captionText.setInnerHTML(" "); + } + } else { + DOM.setInnerText(captionText, caption); + } + + } else if (captionText != null) { + // Remove existing + DOM.removeChild(getElement(), captionText); + captionText = null; + } + + if (showError) { + if (errorIndicatorElement == null) { + errorIndicatorElement = DOM.createDiv(); + DOM.setInnerHTML(errorIndicatorElement, " "); + DOM.setElementProperty(errorIndicatorElement, "className", + "v-errorindicator"); + + DOM.insertChild(getElement(), errorIndicatorElement, + getInsertPosition(InsertPosition.ERROR)); + } + } else if (errorIndicatorElement != null) { + // Remove existing + getElement().removeChild(errorIndicatorElement); + errorIndicatorElement = null; + } + - if (clearElement == null) { - clearElement = DOM.createDiv(); - clearElement.setClassName(CLASSNAME_CLEAR); - getElement().appendChild(clearElement); - } - + return (wasPlacedAfterComponent != placedAfterComponent); + } + @Override public void onBrowserEvent(Event event) { super.onBrowserEvent(event); diff --cc src/com/vaadin/terminal/gwt/client/VPaintableWidget.java index 0be1d5050c,c42248e835..2eee3cc98d --- a/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java +++ b/src/com/vaadin/terminal/gwt/client/VPaintableWidget.java @@@ -33,5 -26,62 +33,61 @@@ public interface VPaintableWidget exten * * @return */ - // FIXME: Rename to getParent() public VPaintableWidgetContainer getParent(); + + public LayoutManager getLayoutManager(); + + /** + * Returns true if the width of this paintable is currently + * undefined. If the width is undefined, the actual width of the paintable + * is defined by its contents. + * + * @return true if the width is undefined, else + * false + */ + public boolean isUndefinedWidth(); + + /** + * Returns true if the height of this paintable is currently + * undefined. If the height is undefined, the actual height of the paintable + * is defined by its contents. + * + * @return true if the height is undefined, else + * false + */ + public boolean isUndefinedHeight(); + + /** + * Returns true if the width of this paintable is currently + * relative. If the width is relative, the actual width of the paintable is + * a percentage of the size allocated to it by its parent. + * + * @return true if the width is undefined, else + * false + */ + public boolean isRelativeWidth(); + + /** + * Returns true if the height of this paintable is currently + * relative. If the height is relative, the actual height of the paintable + * is a percentage of the size allocated to it by its parent. + * + * @return true if the width is undefined, else + * false + */ + public boolean isRelativeHeight(); + + /** + * Gets the width of this paintable as defined on the server. + * + * @return the server side width definition + */ + public String getDeclaredWidth(); + + /** + * Gets the height of this paintable as defined on the server. + * + * @return the server side height definition + */ + public String getDeclaredHeight(); } diff --cc src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java index bff6f8ea3b,1fc995f584..ed45751312 --- a/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java @@@ -9,9 -8,9 +9,11 @@@ import com.google.gwt.user.client.ui.Fo import com.google.gwt.user.client.ui.Focusable; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.ComponentState; + import com.vaadin.terminal.gwt.client.LayoutManager; import com.vaadin.terminal.gwt.client.TooltipInfo; import com.vaadin.terminal.gwt.client.UIDL; ++import com.vaadin.terminal.gwt.client.VConsole; import com.vaadin.terminal.gwt.client.VPaintableMap; import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.VPaintableWidgetContainer; @@@ -41,9 -28,9 +43,12 @@@ public abstract class VAbstractPaintabl private boolean enabled = true; private boolean visible = true; + // shared state from the server to the client + private ComponentState state; + + private String declaredWidth = ""; + private String declaredHeight = ""; + /** * Default constructor */ @@@ -235,7 -184,67 +240,79 @@@ * taken into account */ - getConnection().updateComponentSize(this); - updateComponentSize(uidl); ++ updateComponentSize(); + } + - private void updateComponentSize(UIDL uidl) { - String w = uidl.hasAttribute("width") ? uidl - .getStringAttribute("width") : ""; - - String h = uidl.hasAttribute("height") ? uidl - .getStringAttribute("height") : ""; ++ private void updateComponentSize() { ++ SharedState state = getState(); ++ ++ String w = ""; ++ String h = ""; ++ if (null != state || !(state instanceof ComponentState)) { ++ ComponentState componentState = (ComponentState) state; ++ // TODO move logging to VUIDLBrowser and VDebugConsole ++ // VConsole.log("Paintable state for " ++ // + getPaintableMap().getPid(paintable) + ": " ++ // + String.valueOf(state.getState())); ++ h = componentState.getHeight(); ++ w = componentState.getWidth(); ++ } else { ++ // TODO move logging to VUIDLBrowser and VDebugConsole ++ VConsole.log("No state for paintable " + getId() ++ + " in VAbstractPaintableWidget.updateComponentSize()"); ++ } + + // Parent should be updated if either dimension changed between relative + // and non-relative + if (w.endsWith("%") != declaredWidth.endsWith("%")) { + VPaintableWidgetContainer parent = getParent(); + if (parent instanceof ManagedLayout) { + getLayoutManager().setWidthNeedsUpdate((ManagedLayout) parent); + } + } + + if (h.endsWith("%") != declaredHeight.endsWith("%")) { + VPaintableWidgetContainer parent = getParent(); + if (parent instanceof ManagedLayout) { + getLayoutManager().setHeightNeedsUpdate((ManagedLayout) parent); + } + } + + declaredWidth = w; + declaredHeight = h; + + // Set defined sizes + Widget component = getWidgetForPaintable(); + + component.setStyleName("v-undefined-width", isUndefinedWidth()); + component.setStyleName("v-undefined-height", isUndefinedHeight()); + + component.setHeight(h); + component.setWidth(w); + } + + public boolean isRelativeHeight() { + return declaredHeight.endsWith("%"); + } + + public boolean isRelativeWidth() { + return declaredWidth.endsWith("%"); + } + + public boolean isUndefinedHeight() { + return declaredHeight.length() == 0; + } + + public boolean isUndefinedWidth() { + return declaredWidth.length() == 0; + } + + public String getDeclaredHeight() { + return declaredHeight; + } + + public String getDeclaredWidth() { + return declaredWidth; } /** @@@ -367,28 -375,7 +445,32 @@@ return styleBuf.toString(); } + /** + * Sets the shared state for the paintable widget. + * + * @param new shared state (must be compatible with the return value of + * {@link #getState()} - {@link ComponentState} if + * {@link #getState()} is not overridden + */ + public final void setState(SharedState state) { + this.state = (ComponentState) state; + } + + /** + * Initialize the given RPC proxy object so it is connected to this + * paintable. + * + * @param clientToServerRpc + * The RPC instance to initialize. Must have been created using + * GWT.create(). + */ + protected T initRPC(T clientToServerRpc) { + ((InitializableClientToServerRpc) clientToServerRpc).initRpc(getId(), + getConnection()); + return clientToServerRpc; + } ++ + public LayoutManager getLayoutManager() { + return LayoutManager.get(connection); + } } diff --cc src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanelPaintable.java index cdbb895f2c,6242090f58..c795479dd9 --- a/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanelPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanelPaintable.java @@@ -68,21 -68,20 +68,19 @@@ public abstract class VAbstractSplitPan public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { getWidgetForPaintable().client = client; getWidgetForPaintable().id = uidl.getId(); - getWidgetForPaintable().rendering = true; - getWidgetForPaintable().immediate = uidl.hasAttribute("immediate"); + getWidgetForPaintable().immediate = getState().isImmediate(); super.updateFromUIDL(uidl, client); if (!isRealUpdate(uidl)) { - getWidgetForPaintable().rendering = false; return; } - getWidgetForPaintable().setEnabled( - !uidl.getBooleanAttribute("disabled")); + getWidgetForPaintable().setEnabled(!getState().isDisabled()); clickEventHandler.handleEventHandlerRegistration(client); - if (uidl.hasAttribute("style")) { - getWidgetForPaintable().componentStyleNames = uidl - .getStringAttribute("style").split(" "); + if (getState().hasStyles()) { + getWidgetForPaintable().componentStyleNames = getState().getStyle() + .split(" "); } else { getWidgetForPaintable().componentStyleNames = new String[0]; } diff --cc src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java index f54c6dc05d,be8f5736af..15ac97cd1c --- a/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java @@@ -21,13 -20,9 +20,10 @@@ import com.google.gwt.user.client.ui.Si import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; +import com.vaadin.terminal.gwt.client.ComponentState; - import com.vaadin.terminal.gwt.client.Container; import com.vaadin.terminal.gwt.client.Focusable; - import com.vaadin.terminal.gwt.client.RenderSpace; import com.vaadin.terminal.gwt.client.StyleConstants; import com.vaadin.terminal.gwt.client.UIDL; - import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.VPaintableMap; import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.VTooltip; @@@ -280,19 -211,6 +212,7 @@@ public class VFormLayout extends Simple } } - public boolean isDynamicWidth() { - return width.equals(""); - } - - public boolean hasChildComponent(Widget component) { - return table.hasChildComponent(component); - } - - public void replaceChildComponent(Widget oldComponent, Widget newComponent) { - table.replaceChildComponent(oldComponent, newComponent); - } - + // TODO why duplicated here? public class Caption extends HTML { public static final String CLASSNAME = "v-caption"; diff --cc src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java index c8a0f813f3,8ad4cd0496..82176dd353 --- a/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java @@@ -13,24 -10,23 +10,26 @@@ import java.util.List import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; + import com.google.gwt.dom.client.Style; + import com.google.gwt.dom.client.Style.Position; + import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.user.client.Element; - import com.google.gwt.user.client.ui.AbsolutePanel; - import com.google.gwt.user.client.ui.SimplePanel; + import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.ComponentState; - import com.vaadin.terminal.gwt.client.Container; +import com.vaadin.terminal.gwt.client.RenderSpace; +import com.vaadin.terminal.gwt.client.StyleConstants; + import com.vaadin.terminal.gwt.client.LayoutManager; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; + import com.vaadin.terminal.gwt.client.VCaption; import com.vaadin.terminal.gwt.client.VPaintableMap; import com.vaadin.terminal.gwt.client.VPaintableWidget; - import com.vaadin.terminal.gwt.client.ui.layout.CellBasedLayout; - import com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer; + import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot; + import com.vaadin.terminal.gwt.client.ui.layout.VPaintableLayoutSlot; - public class VGridLayout extends SimplePanel implements Container { + public class VGridLayout extends ComplexPanel { public static final String CLASSNAME = "v-gridlayout"; diff --cc src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java index 24d33fc155,2c896825ec..43dbdc9f61 --- a/src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java @@@ -120,68 -100,47 +100,47 @@@ public class VGridLayoutPaintable exten } } - getWidgetForPaintable().colExpandRatioArray = uidl - .getIntArrayAttribute("colExpand"); - getWidgetForPaintable().rowExpandRatioArray = uidl - .getIntArrayAttribute("rowExpand"); - getWidgetForPaintable().distributeColSpanWidths(); - - getWidgetForPaintable().minColumnWidths = VGridLayout - .cloneArray(getWidgetForPaintable().columnWidths); - getWidgetForPaintable().expandColumns(); - - getWidgetForPaintable().renderRemainingComponentsWithNoRelativeHeight( - pendingCells); - - getWidgetForPaintable().detectRowHeights(); - - getWidgetForPaintable().expandRows(); - - getWidgetForPaintable().renderRemainingComponents(pendingCells); - - for (Cell cell : relativeHeighted) { - // rendering done above so cell.cc should not be null - Widget widget2 = cell.cc.getWidget(); - client.handleComponentRelativeSize(widget2); - cell.cc.updateWidgetSize(); - } - - getWidgetForPaintable().layoutCells(); + layout.colExpandRatioArray = uidl.getIntArrayAttribute("colExpand"); + layout.rowExpandRatioArray = uidl.getIntArrayAttribute("rowExpand"); // clean non rendered components - for (Widget w : getWidgetForPaintable().nonRenderedWidgets.keySet()) { - ChildComponentContainer childComponentContainer = getWidgetForPaintable().widgetToComponentContainer - .get(w); - getWidgetForPaintable().widgetToCell.remove(w); - getWidgetForPaintable().widgetToComponentContainer.remove(w); - childComponentContainer.removeFromParent(); - VPaintableMap paintableMap = VPaintableMap.get(client); - paintableMap.unregisterPaintable(paintableMap.getPaintable(w)); + for (Widget w : nonRenderedWidgets) { + Cell cell = layout.widgetToCell.remove(w); + cell.slot.setCaption(null); + + if (w.getParent() == layout) { + w.removeFromParent(); + VPaintableMap paintableMap = VPaintableMap.get(client); + paintableMap.unregisterPaintable(paintableMap.getPaintable(w)); + } + cell.slot.getWrapperElement().removeFromParent(); } - getWidgetForPaintable().nonRenderedWidgets = null; - getWidgetForPaintable().rendering = false; - getWidgetForPaintable().sizeChangedDuringRendering = false; + int bitMask = uidl.getIntAttribute("margins"); + layout.updateMarginStyleNames(new VMarginInfo(bitMask)); + + layout.updateSpacingStyleName(uidl.getBooleanAttribute("spacing")); + getLayoutManager().setNeedsUpdate(this); } - public void updateCaption(VPaintableWidget component, UIDL uidl) { + public void updateCaption(VPaintableWidget paintable, UIDL uidl) { - Widget widget = paintable.getWidgetForPaintable(); - ChildComponentContainer cc = getWidgetForPaintable().widgetToComponentContainer - .get(widget); - if (cc != null) { - cc.updateCaption(uidl, getConnection()); - } - if (!getWidgetForPaintable().rendering) { - // ensure rel size details are updated - boolean cached = uidl.getBooleanAttribute("cached"); - getWidgetForPaintable().widgetToCell.get(widget) - .updateRelSizeStatus(paintable.getState(), cached); - /* - * This was a component-only update and the possible size change - * must be propagated to the layout - */ - getConnection().captionSizeUpdated(widget); + VGridLayout layout = getWidgetForPaintable(); - if (VCaption.isNeeded(uidl)) { - Cell cell = layout.widgetToCell.get(component ++ if (VCaption.isNeeded(uidl, paintable.getState())) { ++ Cell cell = layout.widgetToCell.get(paintable + .getWidgetForPaintable()); + VLayoutSlot layoutSlot = cell.slot; + VCaption caption = layoutSlot.getCaption(); + if (caption == null) { - caption = new VCaption(component, getConnection()); ++ caption = new VCaption(paintable, getConnection()); + - Widget widget = component.getWidgetForPaintable(); ++ Widget widget = paintable.getWidgetForPaintable(); + + layout.setCaption(widget, caption); + } + caption.updateCaption(uidl); + } else { - layout.setCaption(component.getWidgetForPaintable(), null); ++ layout.setCaption(paintable.getWidgetForPaintable(), null); } } diff --cc src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayoutPaintable.java index 0000000000,5f35815cd8..141726b90d mode 000000,100644..100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayoutPaintable.java @@@ -1,0 -1,290 +1,290 @@@ + /* + @VaadinApache2LicenseForJavaFiles@ + */ + package com.vaadin.terminal.gwt.client.ui; + + import java.util.HashSet; + import java.util.Iterator; + + import com.google.gwt.dom.client.Node; + import com.google.gwt.dom.client.Style; + import com.google.gwt.user.client.Element; + import com.google.gwt.user.client.ui.Widget; + import com.vaadin.terminal.gwt.client.ApplicationConnection; + import com.vaadin.terminal.gwt.client.DirectionalManagedLayout; + import com.vaadin.terminal.gwt.client.LayoutManager; + import com.vaadin.terminal.gwt.client.UIDL; + import com.vaadin.terminal.gwt.client.VCaption; + import com.vaadin.terminal.gwt.client.VPaintableMap; + import com.vaadin.terminal.gwt.client.VPaintableWidget; + import com.vaadin.terminal.gwt.client.ValueMap; + import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot; + import com.vaadin.terminal.gwt.client.ui.layout.VPaintableLayoutSlot; + + public abstract class VMeasuringOrderedLayoutPaintable extends + VAbstractPaintableWidgetContainer implements DirectionalManagedLayout { + + @Override + public void init() { + getLayoutManager().registerDependency(this, + getWidgetForPaintable().spacingMeasureElement); + } + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + VMeasuringOrderedLayout layout = getWidgetForPaintable(); - if (VCaption.isNeeded(uidl)) { ++ if (VCaption.isNeeded(uidl, component.getState())) { + VLayoutSlot layoutSlot = layout.getSlotForChild(component + .getWidgetForPaintable()); + VCaption caption = layoutSlot.getCaption(); + if (caption == null) { + caption = new VCaption(component, getConnection()); + + Widget widget = component.getWidgetForPaintable(); + + layout.setCaption(widget, caption); + } + caption.updateCaption(uidl); + } else { + layout.setCaption(component.getWidgetForPaintable(), null); + } + } + + @Override + public VMeasuringOrderedLayout getWidgetForPaintable() { + return (VMeasuringOrderedLayout) super.getWidgetForPaintable(); + } + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + super.updateFromUIDL(uidl, client); + if (!isRealUpdate(uidl)) { + return; + } + + HashSet previousChildren = new HashSet( + getChildren()); + + VMeasuringOrderedLayout layout = getWidgetForPaintable(); + + ValueMap expandRatios = uidl.getMapAttribute("expandRatios"); + ValueMap alignments = uidl.getMapAttribute("alignments"); + + int currentIndex = 0; + // TODO Support reordering elements! + for (final Iterator it = uidl.getChildIterator(); it.hasNext();) { + final UIDL childUIDL = (UIDL) it.next(); + final VPaintableWidget child = client.getPaintable(childUIDL); + Widget widget = child.getWidgetForPaintable(); + + VLayoutSlot slot = layout.getSlotForChild(widget); + + if (widget.getParent() != layout) { + slot = new VPaintableLayoutSlot(getWidgetForPaintable() + .getStylePrimaryName(), child); + } + layout.addOrMove(slot, currentIndex++); + + String pid = child.getId(); + + AlignmentInfo alignment; + if (alignments.containsKey(pid)) { + alignment = new AlignmentInfo(alignments.getInt(pid)); + } else { + alignment = AlignmentInfo.TOP_LEFT; + } + slot.setAlignment(alignment); + + double expandRatio; + if (expandRatios.containsKey(pid)) { + expandRatio = expandRatios.getRawNumber(pid); + } else { + expandRatio = 0; + } + slot.setExpandRatio(expandRatio); + + if (!childUIDL.getBooleanAttribute("cached")) { + child.updateFromUIDL(childUIDL, client); + } + + previousChildren.remove(child); + } + + for (VPaintableWidget child : previousChildren) { + Widget widget = child.getWidgetForPaintable(); + + // Don't remove and unregister if it has been moved to a different + // parent. Slot element will be left behind, but that is taken care + // of later + if (widget.getParent() == getWidgetForPaintable()) { + layout.removeSlot(layout.getSlotForChild(widget)); + + VPaintableMap vPaintableMap = VPaintableMap.get(client); + vPaintableMap.unregisterPaintable(child); + } + } + + // Remove empty layout slots left behind after children have moved to + // other paintables + while (true) { + int childCount = layout.getElement().getChildCount(); + if (childCount <= 1) { + // Stop if no more slots (spacing element is always present) + break; + } + + Node lastSlot = layout.getElement().getChild(childCount - 2); + if (lastSlot.getChildCount() == 0) { + // Remove if empty + lastSlot.removeFromParent(); + } else { + // Stop searching when last slot is not empty + break; + } + } + + int bitMask = uidl.getIntAttribute("margins"); + layout.updateMarginStyleNames(new VMarginInfo(bitMask)); + + layout.updateSpacingStyleName(uidl.getBooleanAttribute("spacing")); + + getLayoutManager().setNeedsUpdate(this); + } + + private int getSizeForInnerSize(int size, boolean isVertical) { + LayoutManager layoutManager = getLayoutManager(); + Element element = getWidgetForPaintable().getElement(); + if (isVertical) { + return size + layoutManager.getBorderHeight(element) + + layoutManager.getPaddingHeight(element); + } else { + return size + layoutManager.getBorderWidth(element) + + layoutManager.getPaddingWidth(element); + } + } + + private static String getSizeProperty(boolean isVertical) { + return isVertical ? "height" : "width"; + } + + private boolean isUndefinedInDirection(boolean isVertical) { + if (isVertical) { + return isUndefinedHeight(); + } else { + return isUndefinedWidth(); + } + } + + private int getInnerSizeInDirection(boolean isVertical) { + if (isVertical) { + return getLayoutManager().getInnerHeight( + getWidgetForPaintable().getElement()); + } else { + return getLayoutManager().getInnerWidth( + getWidgetForPaintable().getElement()); + } + } + + private void layoutPrimaryDirection() { + VMeasuringOrderedLayout layout = getWidgetForPaintable(); + boolean isVertical = layout.isVertical; + boolean isUndefined = isUndefinedInDirection(isVertical); + + int startPadding = getStartPadding(isVertical); + int spacingSize = getSpacingInDirection(isVertical); + int allocatedSize; + + if (isUndefined) { + allocatedSize = -1; + } else { + allocatedSize = getInnerSizeInDirection(isVertical); + } + + allocatedSize = layout.layoutPrimaryDirection(spacingSize, + allocatedSize, startPadding); + + Style ownStyle = getWidgetForPaintable().getElement().getStyle(); + if (isUndefined) { + ownStyle.setPropertyPx(getSizeProperty(isVertical), + getSizeForInnerSize(allocatedSize, isVertical)); + } else { + ownStyle.setProperty(getSizeProperty(isVertical), + getDefinedSize(isVertical)); + } + } + + private int getSpacingInDirection(boolean isVertical) { + if (isVertical) { + return getLayoutManager().getOuterHeight( + getWidgetForPaintable().spacingMeasureElement); + } else { + return getLayoutManager().getOuterWidth( + getWidgetForPaintable().spacingMeasureElement); + } + } + + private void layoutSecondaryDirection() { + VMeasuringOrderedLayout layout = getWidgetForPaintable(); + boolean isVertical = layout.isVertical; + boolean isUndefined = isUndefinedInDirection(!isVertical); + + int startPadding = getStartPadding(!isVertical); + + int allocatedSize; + if (isUndefined) { + allocatedSize = -1; + } else { + allocatedSize = getInnerSizeInDirection(!isVertical); + } + + allocatedSize = layout.layoutSecondaryDirection(allocatedSize, + startPadding); + + Style ownStyle = getWidgetForPaintable().getElement().getStyle(); + + if (isUndefined) { + ownStyle.setPropertyPx( + getSizeProperty(!getWidgetForPaintable().isVertical), + getSizeForInnerSize(allocatedSize, + !getWidgetForPaintable().isVertical)); + } else { + ownStyle.setProperty( + getSizeProperty(!getWidgetForPaintable().isVertical), + getDefinedSize(!getWidgetForPaintable().isVertical)); + } + } + + private String getDefinedSize(boolean isVertical) { + if (isVertical) { + return getDeclaredHeight(); + } else { + return getDeclaredWidth(); + } + } + + private int getStartPadding(boolean isVertical) { + if (isVertical) { + return getLayoutManager().getPaddingTop( + getWidgetForPaintable().getElement()); + } else { + return getLayoutManager().getPaddingLeft( + getWidgetForPaintable().getElement()); + } + } + + public void layoutHorizontally() { + if (getWidgetForPaintable().isVertical) { + layoutSecondaryDirection(); + } else { + layoutPrimaryDirection(); + } + } + + public void layoutVertically() { + if (getWidgetForPaintable().isVertical) { + layoutPrimaryDirection(); + } else { + layoutSecondaryDirection(); + } + } + + } diff --cc src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index b4499cd2d5,07d9de5f20..c4651ee626 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@@ -59,11 -59,8 +59,9 @@@ import com.google.gwt.user.client.ui.UI import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; +import com.vaadin.terminal.gwt.client.ComponentState; - import com.vaadin.terminal.gwt.client.Container; import com.vaadin.terminal.gwt.client.Focusable; import com.vaadin.terminal.gwt.client.MouseEventDetails; - import com.vaadin.terminal.gwt.client.RenderSpace; import com.vaadin.terminal.gwt.client.TooltipInfo; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; diff --cc src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java index c126e81aec,0b5c43d30f..9b154c0d91 --- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java @@@ -23,9 -22,6 +22,7 @@@ import com.google.gwt.user.client.ui.Si import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; +import com.vaadin.terminal.gwt.client.ComponentState; - import com.vaadin.terminal.gwt.client.RenderInformation; - import com.vaadin.terminal.gwt.client.RenderSpace; import com.vaadin.terminal.gwt.client.TooltipInfo; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util;