From ed7f508695d4147285d48e09365cdc68f9bd5b4c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Tue, 21 Feb 2012 15:27:36 +0200 Subject: [PATCH] Update GridLayout to use VLayoutSlot (#8313) --- .../themes/base/gridlayout/gridlayout.css | 6 + .../terminal/gwt/client/ui/VGridLayout.java | 731 +++++------------ .../gwt/client/ui/VGridLayoutPaintable.java | 182 ++--- .../ui/layout/ChildComponentContainer.java | 757 ------------------ 4 files changed, 271 insertions(+), 1405 deletions(-) delete mode 100644 src/com/vaadin/terminal/gwt/client/ui/layout/ChildComponentContainer.java diff --git a/WebContent/VAADIN/themes/base/gridlayout/gridlayout.css b/WebContent/VAADIN/themes/base/gridlayout/gridlayout.css index 38e2bb3aed..9edaf152a0 100644 --- a/WebContent/VAADIN/themes/base/gridlayout/gridlayout.css +++ b/WebContent/VAADIN/themes/base/gridlayout/gridlayout.css @@ -1,3 +1,9 @@ +.v-gridlayout { + position: relative; +} +.v-gridlayout-slot { + position: absolute; +} .v-gridlayout-margin-top { padding-top: 12px; } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java index 6285121901..0d56f47a6f 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java @@ -4,56 +4,39 @@ package com.vaadin.terminal.gwt.client.ui; -import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Set; 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.RenderSpace; -import com.vaadin.terminal.gwt.client.StyleConstants; +import com.vaadin.terminal.gwt.client.MeasuredSize; 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.ChildComponentContainer; +import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot; +import com.vaadin.terminal.gwt.client.ui.layout.VPaintableLayoutSlot; -public class VGridLayout extends SimplePanel { +public class VGridLayout extends ComplexPanel { public static final String CLASSNAME = "v-gridlayout"; - private DivElement margin = Document.get().createDivElement(); - - final AbsolutePanel canvas = new AbsolutePanel(); - ApplicationConnection client; - protected HashMap widgetToComponentContainer = new HashMap(); - HashMap widgetToCell = new HashMap(); - private int spacingPixelsHorizontal; - private int spacingPixelsVertical; - int[] columnWidths; int[] rowHeights; - private int height; - - private int width; - - private boolean undefinedWidth; - - private boolean undefinedHeight; - int[] colExpandRatioArray; int[] rowExpandRatioArray; @@ -62,22 +45,26 @@ public class VGridLayout extends SimplePanel { private int[] minRowHeights; - boolean rendering; - - HashMap nonRenderedWidgets; - - boolean sizeChangedDuringRendering = false; + DivElement spacingMeasureElement; public VGridLayout() { super(); - getElement().appendChild(margin); + setElement(Document.get().createDivElement()); + + spacingMeasureElement = Document.get().createDivElement(); + Style spacingStyle = spacingMeasureElement.getStyle(); + spacingStyle.setPosition(Position.ABSOLUTE); + getElement().appendChild(spacingMeasureElement); + setStyleName(CLASSNAME); - setWidget(canvas); } - @Override - protected Element getContainerElement() { - return margin.cast(); + private MeasuredSize getMeasuredSize() { + return getPaintable().getMeasuredSize(); + } + + private VPaintableWidget getPaintable() { + return VPaintableMap.get(client).getPaintable(this); } /** @@ -104,7 +91,7 @@ public class VGridLayout extends SimplePanel { * @return */ protected int getHorizontalSpacing() { - return spacingPixelsHorizontal; + return getMeasuredSize().getDependencyOuterWidth(spacingMeasureElement); } /** @@ -113,7 +100,8 @@ public class VGridLayout extends SimplePanel { * @return */ protected int getVerticalSpacing() { - return spacingPixelsVertical; + return getMeasuredSize() + .getDependencyOuterHeight(spacingMeasureElement); } static int[] cloneArray(int[] toBeCloned) { @@ -127,10 +115,11 @@ public class VGridLayout extends SimplePanel { void expandRows() { if (!isUndefinedHeight()) { int usedSpace = minRowHeights[0]; + int verticalSpacing = getVerticalSpacing(); for (int i = 1; i < minRowHeights.length; i++) { - usedSpace += spacingPixelsVertical + minRowHeights[i]; + usedSpace += verticalSpacing + minRowHeights[i]; } - int availableSpace = getOffsetHeight() - marginTopAndBottom; + int availableSpace = getMeasuredSize().getInnerHeight(); int excessSpace = availableSpace - usedSpace; int distributed = 0; if (excessSpace > 0) { @@ -150,125 +139,36 @@ public class VGridLayout extends SimplePanel { } } - void updateHeight(int height, boolean undefinedHeight) { - if (height != this.height || this.undefinedHeight != undefinedHeight) { - this.undefinedHeight = undefinedHeight; - this.height = height; - if (rendering) { - sizeChangedDuringRendering = true; - } else { - expandRows(); - layoutCells(); - for (Widget w : widgetToCell.keySet()) { - client.handleComponentRelativeSize(w); - } - } - } + void updateHeight() { + // Detect minimum heights & calculate spans + detectRowHeights(); + + // Expand + expandRows(); + + // Position + layoutCellsVertically(); } - void updateWidth(int width, boolean undefinedWidth) { - if (width != this.width || undefinedWidth != this.undefinedWidth) { - this.undefinedWidth = undefinedWidth; - this.width = width; - if (rendering) { - sizeChangedDuringRendering = true; - } else { - int[] oldWidths = cloneArray(columnWidths); - expandColumns(); - boolean heightChanged = false; - HashSet dirtyRows = null; - for (int i = 0; i < oldWidths.length; i++) { - if (columnWidths[i] != oldWidths[i]) { - Cell[] column = cells[i]; - for (int j = 0; j < column.length; j++) { - Cell c = column[j]; - if (c != null && c.cc != null - && c.widthCanAffectHeight()) { - c.cc.setContainerSize(c.getAvailableWidth(), - c.getAvailableHeight()); - client.handleComponentRelativeSize(c.cc - .getWidget()); - c.cc.updateWidgetSize(); - int newHeight = c.getHeight(); - if (columnWidths[i] < oldWidths[i] - && newHeight > minRowHeights[j] - && c.rowspan == 1) { - /* - * The width of this column was reduced and - * this affected the height. The height is - * now greater than the previously - * calculated minHeight for the row. - */ - minRowHeights[j] = newHeight; - if (newHeight > rowHeights[j]) { - /* - * The new height is greater than the - * previously calculated rowHeight -> we - * need to recalculate heights later on - */ - rowHeights[j] = newHeight; - heightChanged = true; - } - } else if (newHeight < minRowHeights[j]) { - /* - * The new height of the component is less - * than the previously calculated min row - * height. The min row height may be - * affected and must thus be recalculated - */ - if (dirtyRows == null) { - dirtyRows = new HashSet(); - } - dirtyRows.add(j); - } - } - } - } - } - if (dirtyRows != null) { - /* flag indicating that there is a potential row shrinking */ - boolean rowMayShrink = false; - for (Integer rowIndex : dirtyRows) { - int oldMinimum = minRowHeights[rowIndex]; - int newMinimum = 0; - for (int colIndex = 0; colIndex < columnWidths.length; colIndex++) { - Cell cell = cells[colIndex][rowIndex]; - if (cell != null && !cell.hasRelativeHeight() - && cell.getHeight() > newMinimum) { - newMinimum = cell.getHeight(); - } - } - if (newMinimum < oldMinimum) { - minRowHeights[rowIndex] = rowHeights[rowIndex] = newMinimum; - rowMayShrink = true; - } - } - if (rowMayShrink) { - distributeRowSpanHeights(); - minRowHeights = cloneArray(rowHeights); - heightChanged = true; - } + void updateWidth() { + // Detect widths & calculate spans + detectColWidths(); + // Expand + expandColumns(); + // Position + layoutCellsHorizontally(); - } - layoutCells(); - for (Widget w : widgetToCell.keySet()) { - client.handleComponentRelativeSize(w); - } - if (heightChanged && isUndefinedHeight()) { - Util.notifyParentOfSizeChange(this, false); - } - } - } } void expandColumns() { if (!isUndefinedWidth()) { int usedSpace = minColumnWidths[0]; + int horizontalSpacing = getHorizontalSpacing(); for (int i = 1; i < minColumnWidths.length; i++) { - usedSpace += spacingPixelsHorizontal + minColumnWidths[i]; + usedSpace += horizontalSpacing + minColumnWidths[i]; } - canvas.setWidth(""); - int availableSpace = canvas.getOffsetWidth(); + + int availableSpace = getMeasuredSize().getInnerWidth(); int excessSpace = availableSpace - usedSpace; int distributed = 0; if (excessSpace > 0) { @@ -288,70 +188,58 @@ public class VGridLayout extends SimplePanel { } } - void layoutCells() { - int x = 0; + void layoutCellsVertically() { + int verticalSpacing = getVerticalSpacing(); int y = 0; for (int i = 0; i < cells.length; i++) { y = 0; for (int j = 0; j < cells[i].length; j++) { Cell cell = cells[i][j]; if (cell != null) { - cell.layout(x, y); + cell.layoutVertically(y); } - y += rowHeights[j] + spacingPixelsVertical; + y += rowHeights[j] + verticalSpacing; } - x += columnWidths[i] + spacingPixelsHorizontal; } - if (isUndefinedWidth()) { - canvas.setWidth((x - spacingPixelsHorizontal) + "px"); - } else { - // main element defines width - canvas.setWidth(""); + if (isUndefinedHeight()) { + int innerHeight = y - verticalSpacing; + getElement().getStyle().setHeight(innerHeight, Unit.PX); } + } - int canvasHeight; - if (isUndefinedHeight()) { - canvasHeight = y - spacingPixelsVertical; - } else { - canvasHeight = getOffsetHeight() - marginTopAndBottom; - if (canvasHeight < 0) { - canvasHeight = 0; + void layoutCellsHorizontally() { + int x = 0; + int horizontalSpacing = getHorizontalSpacing(); + for (int i = 0; i < cells.length; i++) { + for (int j = 0; j < cells[i].length; j++) { + Cell cell = cells[i][j]; + if (cell != null) { + cell.layoutHorizontally(x); + } } + x += columnWidths[i] + horizontalSpacing; + } + + if (isUndefinedWidth()) { + getElement().getStyle().setWidth((x - horizontalSpacing), Unit.PX); } - canvas.setHeight(canvasHeight + "px"); } private boolean isUndefinedHeight() { - return undefinedHeight; + return getPaintable().isUndefinedHeight(); } private boolean isUndefinedWidth() { - return undefinedWidth; - } - - void renderRemainingComponents(LinkedList pendingCells) { - for (Cell cell : pendingCells) { - cell.render(); - } + return getPaintable().isUndefinedWidth(); } - void detectRowHeights() { - + private void detectRowHeights() { // collect min rowheight from non-rowspanned cells for (int i = 0; i < cells.length; i++) { for (int j = 0; j < cells[i].length; j++) { Cell cell = cells[i][j]; if (cell != null) { - /* - * Setting fixing container width may in some situations - * affect height. Example: Label with wrapping text without - * or with relative width. - */ - if (cell.cc != null && cell.widthCanAffectHeight()) { - cell.cc.setWidth(cell.getAvailableWidth() + "px"); - cell.cc.updateWidgetSize(); - } if (cell.rowspan == 1) { if (!cell.hasRelativeHeight() && rowHeights[j] < cell.getHeight()) { @@ -369,6 +257,29 @@ public class VGridLayout extends SimplePanel { minRowHeights = cloneArray(rowHeights); } + private void detectColWidths() { + // collect min colwidths from non-colspanned cells + for (int i = 0; i < cells.length; i++) { + for (int j = 0; j < cells[i].length; j++) { + Cell cell = cells[i][j]; + if (cell != null) { + if (cell.colspan == 1) { + if (!cell.hasRelativeWidth() + && columnWidths[i] < cell.getWidth()) { + columnWidths[i] = cell.getWidth(); + } + } else { + storeColSpannedCell(cell); + } + } + } + } + + distributeColSpanWidths(); + + minColumnWidths = cloneArray(columnWidths); + } + private void storeRowSpannedCell(Cell cell) { SpanList l = null; for (SpanList list : rowSpans) { @@ -391,20 +302,6 @@ public class VGridLayout extends SimplePanel { l.cells.add(cell); } - void renderRemainingComponentsWithNoRelativeHeight( - LinkedList pendingCells) { - - for (Iterator iterator = pendingCells.iterator(); iterator - .hasNext();) { - Cell cell = iterator.next(); - if (!cell.hasRelativeHeight()) { - cell.render(); - iterator.remove(); - } - } - - } - /** * Iterates colspanned cells, ensures cols have enough space to accommodate * them @@ -416,7 +313,7 @@ public class VGridLayout extends SimplePanel { // subsequent renders int width = cell.hasRelativeWidth() ? 0 : cell.getWidth(); distributeSpanSize(columnWidths, cell.col, cell.colspan, - spacingPixelsHorizontal, width, colExpandRatioArray); + getHorizontalSpacing(), width, colExpandRatioArray); } } } @@ -432,7 +329,7 @@ public class VGridLayout extends SimplePanel { // subsequent renders int height = cell.hasRelativeHeight() ? 0 : cell.getHeight(); distributeSpanSize(rowHeights, cell.row, cell.rowspan, - spacingPixelsVertical, height, rowExpandRatioArray); + getVerticalSpacing(), height, rowExpandRatioArray); } } } @@ -492,8 +389,6 @@ public class VGridLayout extends SimplePanel { private LinkedList colSpans = new LinkedList(); private LinkedList rowSpans = new LinkedList(); - private int marginTopAndBottom; - private class SpanList { final int span; List cells = new LinkedList(); @@ -526,226 +421,28 @@ public class VGridLayout extends SimplePanel { l.cells.add(cell); } - void detectSpacing(UIDL uidl) { - DivElement spacingmeter = Document.get().createDivElement(); - spacingmeter.setClassName(CLASSNAME + "-" + "spacing-" - + (uidl.getBooleanAttribute("spacing") ? "on" : "off")); - spacingmeter.getStyle().setProperty("width", "0"); - spacingmeter.getStyle().setProperty("height", "0"); - canvas.getElement().appendChild(spacingmeter); - spacingPixelsHorizontal = spacingmeter.getOffsetWidth(); - spacingPixelsVertical = spacingmeter.getOffsetHeight(); - canvas.getElement().removeChild(spacingmeter); - } - - void handleMargins(UIDL uidl) { - final VMarginInfo margins = new VMarginInfo( - uidl.getIntAttribute("margins")); - - String styles = CLASSNAME + "-margin"; - if (margins.hasTop()) { - styles += " " + CLASSNAME + "-" + StyleConstants.MARGIN_TOP; - } - if (margins.hasRight()) { - styles += " " + CLASSNAME + "-" + StyleConstants.MARGIN_RIGHT; - } - if (margins.hasBottom()) { - styles += " " + CLASSNAME + "-" + StyleConstants.MARGIN_BOTTOM; - } - if (margins.hasLeft()) { - styles += " " + CLASSNAME + "-" + StyleConstants.MARGIN_LEFT; - } - margin.setClassName(styles); - - marginTopAndBottom = margin.getOffsetHeight() - - canvas.getOffsetHeight(); - } - - public boolean requestLayout(final Set changedChildren) { - boolean needsLayout = false; - boolean reDistributeColSpanWidths = false; - boolean reDistributeRowSpanHeights = false; - int offsetHeight = canvas.getOffsetHeight(); - int offsetWidth = canvas.getOffsetWidth(); - if (isUndefinedWidth() || isUndefinedHeight()) { - needsLayout = true; - } - ArrayList dirtyColumns = new ArrayList(); - ArrayList dirtyRows = new ArrayList(); - for (Widget widget : changedChildren) { - - Cell cell = widgetToCell.get(widget); - if (!cell.hasRelativeHeight() || !cell.hasRelativeWidth()) { - // cell sizes will only stay still if only relatively - // sized components - // check if changed child affects min col widths - assert cell.cc != null; - cell.cc.setWidth(""); - cell.cc.setHeight(""); - - cell.cc.updateWidgetSize(); - - /* - * If this is the result of an caption icon onload event the - * caption size may have changed - */ - cell.cc.updateCaptionSize(); - - int width = cell.getWidth(); - int allocated = columnWidths[cell.col]; - for (int i = 1; i < cell.colspan; i++) { - allocated += spacingPixelsHorizontal - + columnWidths[cell.col + i]; - } - if (allocated < width) { - needsLayout = true; - if (cell.colspan == 1) { - // do simple column width expansion - columnWidths[cell.col] = minColumnWidths[cell.col] = width; - } else { - // mark that col span expansion is needed - reDistributeColSpanWidths = true; - } - } else if (allocated != width) { - // size is smaller thant allocated, column might - // shrink - dirtyColumns.add(cell.col); - } - - int height = cell.getHeight(); - - allocated = rowHeights[cell.row]; - for (int i = 1; i < cell.rowspan; i++) { - allocated += spacingPixelsVertical - + rowHeights[cell.row + i]; - } - if (allocated < height) { - needsLayout = true; - if (cell.rowspan == 1) { - // do simple row expansion - rowHeights[cell.row] = minRowHeights[cell.row] = height; - } else { - // mark that row span expansion is needed - reDistributeRowSpanHeights = true; - } - } else if (allocated != height) { - // size is smaller than allocated, row might shrink - dirtyRows.add(cell.row); - } - } - } - - if (dirtyColumns.size() > 0) { - for (Integer colIndex : dirtyColumns) { - int colW = 0; - for (int i = 0; i < rowHeights.length; i++) { - Cell cell = cells[colIndex][i]; - if (cell != null && cell.getChildUIDL() != null - && !cell.hasRelativeWidth() && cell.colspan == 1) { - int width = cell.getWidth(); - if (width > colW) { - colW = width; - } - } - } - minColumnWidths[colIndex] = colW; - } - needsLayout = true; - // ensure colspanned columns have enough space - columnWidths = cloneArray(minColumnWidths); - distributeColSpanWidths(); - reDistributeColSpanWidths = false; - } - - if (reDistributeColSpanWidths) { - distributeColSpanWidths(); - } - - if (dirtyRows.size() > 0) { - needsLayout = true; - for (Integer rowIndex : dirtyRows) { - // recalculate min row height - int rowH = minRowHeights[rowIndex] = 0; - // loop all columns on row rowIndex - for (int i = 0; i < columnWidths.length; i++) { - Cell cell = cells[i][rowIndex]; - if (cell != null && cell.getChildUIDL() != null - && !cell.hasRelativeHeight() && cell.rowspan == 1) { - int h = cell.getHeight(); - if (h > rowH) { - rowH = h; - } - } - } - minRowHeights[rowIndex] = rowH; - } - // TODO could check only some row spans - rowHeights = cloneArray(minRowHeights); - distributeRowSpanHeights(); - reDistributeRowSpanHeights = false; - } - - if (reDistributeRowSpanHeights) { - distributeRowSpanHeights(); - } - - if (needsLayout) { - expandColumns(); - expandRows(); - layoutCells(); - // loop all relative sized components and update their size - for (int i = 0; i < cells.length; i++) { - for (int j = 0; j < cells[i].length; j++) { - Cell cell = cells[i][j]; - if (cell != null - && cell.cc != null - && (cell.hasRelativeHeight() || cell - .hasRelativeWidth())) { - client.handleComponentRelativeSize(cell.cc.getWidget()); - } - } - } - } - if (canvas.getOffsetHeight() != offsetHeight - || canvas.getOffsetWidth() != offsetWidth) { - return false; - } else { - return true; - } - } - Cell[][] cells; /** * Private helper class. */ class Cell { - private boolean relHeight = false; - private boolean relWidth = false; - private boolean widthCanAffectHeight = false; - public Cell(UIDL c) { row = c.getIntAttribute("y"); col = c.getIntAttribute("x"); - setUidl(c); + updateFromUidl(c); } - public boolean widthCanAffectHeight() { - return widthCanAffectHeight; + public boolean hasContent() { + return hasContent; } public boolean hasRelativeHeight() { - return relHeight; - } - - public RenderSpace getAllocatedSpace() { - return new RenderSpace(getAvailableWidth() - - cc.getCaptionWidthAfterComponent(), getAvailableHeight() - - cc.getCaptionHeightAboveComponent()); - } - - public boolean hasContent() { - return childUidl != null; + if (slot != null) { + return slot.getPaintable().isRelativeHeight(); + } else { + return true; + } } /** @@ -754,7 +451,7 @@ public class VGridLayout extends SimplePanel { private int getAvailableWidth() { int width = columnWidths[col]; for (int i = 1; i < colspan; i++) { - width += spacingPixelsHorizontal + columnWidths[col + i]; + width += getHorizontalSpacing() + columnWidths[col + i]; } return width; } @@ -765,110 +462,65 @@ public class VGridLayout extends SimplePanel { private int getAvailableHeight() { int height = rowHeights[row]; for (int i = 1; i < rowspan; i++) { - height += spacingPixelsVertical + rowHeights[row + i]; + height += getVerticalSpacing() + rowHeights[row + i]; } return height; } - public void layout(int x, int y) { - if (cc != null && cc.isAttached()) { - canvas.setWidgetPosition(cc, x, y); - cc.setContainerSize(getAvailableWidth(), getAvailableHeight()); - cc.setAlignment(new AlignmentInfo(alignment)); - cc.updateAlignments(getAvailableWidth(), getAvailableHeight()); + public void layoutHorizontally(int x) { + if (slot != null) { + slot.positionHorizontally(x, getAvailableWidth()); } } - public int getWidth() { - if (cc != null) { - int w = cc.getWidgetSize().getWidth() - + cc.getCaptionWidthAfterComponent(); - return w; - } else { - return 0; + public void layoutVertically(int y) { + if (slot != null) { + slot.positionVertically(y, getAvailableHeight()); } } - public int getHeight() { - if (cc != null) { - return cc.getWidgetSize().getHeight() - + cc.getCaptionHeightAboveComponent(); + public int getWidth() { + if (slot != null) { + return slot.getUsedWidth(); } else { return 0; } } - public boolean renderIfNoRelativeWidth() { - if (childUidl == null) { - return false; - } - if (!hasRelativeWidth()) { - render(); - return true; + public int getHeight() { + if (slot != null) { + return slot.getUsedHeight(); } else { - return false; + return 0; } } protected boolean hasRelativeWidth() { - return relWidth; - } - - protected void render() { - assert childUidl != null; - - VPaintableWidget paintable = client.getPaintable(childUidl); - Widget w = paintable.getWidgetForPaintable(); - assert paintable != null; - if (cc == null || cc.getWidget() != w) { - if (widgetToComponentContainer.containsKey(w)) { - // Component moving from one place to another - cc = widgetToComponentContainer.get(w); - cc.setWidth(""); - cc.setHeight(""); - /* - * Widget might not be set if moving from another component - * and this layout has been hidden when moving out, see - * #5372 - */ - cc.setPaintable(paintable); - } else { - // A new component - cc = new ChildComponentContainer(paintable, - ChildComponentContainer.ORIENTATION_VERTICAL); - widgetToComponentContainer.put(w, cc); - cc.setWidth(""); - canvas.add(cc, 0, 0); - } - widgetToCell.put(w, this); - } - cc.renderChild(childUidl, client, -1); - if (sizeChangedDuringRendering && Util.isCached(childUidl)) { - client.handleComponentRelativeSize(cc.getWidget()); + if (slot != null) { + return slot.getPaintable().isRelativeWidth(); + } else { + return true; } - cc.updateWidgetSize(); - nonRenderedWidgets.remove(w); - } - - public UIDL getChildUIDL() { - return childUidl; } final int row; final int col; int colspan = 1; int rowspan = 1; - UIDL childUidl; - int alignment; - // may be null after setUidl() if content has vanished or changed, set - // in render() - ChildComponentContainer cc; - public void setUidl(UIDL c) { + private boolean hasContent; + + private AlignmentInfo alignment; + + VPaintableLayoutSlot slot; + + public void updateFromUidl(UIDL cellUidl) { // Set cell width - colspan = c.hasAttribute("w") ? c.getIntAttribute("w") : 1; + colspan = cellUidl.hasAttribute("w") ? cellUidl + .getIntAttribute("w") : 1; // Set cell height - rowspan = c.hasAttribute("h") ? c.getIntAttribute("h") : 1; + rowspan = cellUidl.hasAttribute("h") ? cellUidl + .getIntAttribute("h") : 1; // ensure we will lose reference to old cells, now overlapped by // this cell for (int i = 0; i < colspan; i++) { @@ -879,52 +531,32 @@ public class VGridLayout extends SimplePanel { } } - c = c.getChildUIDL(0); // we are interested about childUidl - if (childUidl != null) { - if (c == null) { - // content has vanished, old content will be removed from - // canvas later during the render phase - cc = null; - } else if (cc != null - && cc.getWidget() != client.getPaintable(c) - .getWidgetForPaintable()) { - // content has changed - cc = null; - VPaintableWidget paintable = client.getPaintable(c); - Widget w = paintable.getWidgetForPaintable(); - if (widgetToComponentContainer.containsKey(w)) { - // cc exist for this component (moved) use that for this - // cell - cc = widgetToComponentContainer.get(w); - cc.setWidth(""); - cc.setHeight(""); - widgetToCell.put(w, this); + UIDL childUidl = cellUidl.getChildUIDL(0); // we are interested + // about childUidl + hasContent = childUidl != null; + if (hasContent) { + VPaintableWidget paintable = client.getPaintable(childUidl); + + if (slot == null || slot.getPaintable() != paintable) { + slot = new VPaintableLayoutSlot(CLASSNAME, paintable); + Element slotWrapper = slot.getWrapperElement(); + getElement().appendChild(slotWrapper); + + Widget widget = paintable.getWidgetForPaintable(); + insert(widget, slotWrapper, getWidgetCount(), false); + Cell oldCell = widgetToCell.put(widget, this); + if (oldCell != null) { + oldCell.slot.getWrapperElement().removeFromParent(); + oldCell.slot = null; } } + + paintable.updateFromUIDL(childUidl, client); } - childUidl = c; - updateRelSizeStatus(c); } - protected void updateRelSizeStatus(UIDL uidl) { - if (uidl != null && !uidl.getBooleanAttribute("cached")) { - if (uidl.hasAttribute("height") - && uidl.getStringAttribute("height").contains("%")) { - relHeight = true; - } else { - relHeight = false; - } - if (uidl.hasAttribute("width")) { - widthCanAffectHeight = relWidth = uidl.getStringAttribute( - "width").contains("%"); - if (uidl.hasAttribute("height")) { - widthCanAffectHeight = false; - } - } else { - widthCanAffectHeight = !uidl.hasAttribute("height"); - relWidth = false; - } - } + public void setAlignment(AlignmentInfo alignmentInfo) { + slot.setAlignment(alignmentInfo); } } @@ -936,7 +568,7 @@ public class VGridLayout extends SimplePanel { cell = new Cell(c); cells[col][row] = cell; } else { - cell.setUidl(c); + cell.updateFromUidl(c); } return cell; } @@ -955,4 +587,47 @@ public class VGridLayout extends SimplePanel { return Util.getPaintableForElement(client, this, element); } + void setCaption(Widget widget, VCaption caption) { + VLayoutSlot slot = widgetToCell.get(widget).slot; + + 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); + } + } + + private void togglePrefixedStyleName(String name, boolean enabled) { + if (enabled) { + addStyleDependentName(name); + } else { + removeStyleDependentName(name); + } + } + + void updateMarginStyleNames(VMarginInfo marginInfo) { + togglePrefixedStyleName("margin-top", marginInfo.hasTop()); + togglePrefixedStyleName("margin-right", marginInfo.hasRight()); + togglePrefixedStyleName("margin-bottom", marginInfo.hasBottom()); + togglePrefixedStyleName("margin-left", marginInfo.hasLeft()); + } + + 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"); + } + } + } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java index 909612933b..beb72d45b4 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java @@ -3,11 +3,8 @@ */ package com.vaadin.terminal.gwt.client.ui; -import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedList; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.DomEvent.Type; @@ -19,10 +16,11 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.CalculatingLayout; import com.vaadin.terminal.gwt.client.EventId; 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.ui.VGridLayout.Cell; -import com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer; +import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot; public class VGridLayoutPaintable extends VAbstractPaintableWidgetContainer implements CalculatingLayout { @@ -41,53 +39,48 @@ public class VGridLayoutPaintable extends VAbstractPaintableWidgetContainer } }; + public VGridLayoutPaintable() { + getMeasuredSize().registerDependency( + getWidgetForPaintable().spacingMeasureElement); + } + @Override public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - getWidgetForPaintable().rendering = true; - getWidgetForPaintable().client = client; + VGridLayout layout = getWidgetForPaintable(); + layout.client = client; super.updateFromUIDL(uidl, client); if (!isRealUpdate(uidl)) { - getWidgetForPaintable().rendering = false; return; } clickEventHandler.handleEventHandlerRegistration(client); - getWidgetForPaintable().canvas.setWidth("0px"); - - getWidgetForPaintable().handleMargins(uidl); - getWidgetForPaintable().detectSpacing(uidl); - int cols = uidl.getIntAttribute("w"); int rows = uidl.getIntAttribute("h"); - getWidgetForPaintable().columnWidths = new int[cols]; - getWidgetForPaintable().rowHeights = new int[rows]; + layout.columnWidths = new int[cols]; + layout.rowHeights = new int[rows]; - if (getWidgetForPaintable().cells == null) { - getWidgetForPaintable().cells = new Cell[cols][rows]; - } else if (getWidgetForPaintable().cells.length != cols - || getWidgetForPaintable().cells[0].length != rows) { + if (layout.cells == null) { + layout.cells = new Cell[cols][rows]; + } else if (layout.cells.length != cols + || layout.cells[0].length != rows) { Cell[][] newCells = new Cell[cols][rows]; - for (int i = 0; i < getWidgetForPaintable().cells.length; i++) { - for (int j = 0; j < getWidgetForPaintable().cells[i].length; j++) { + for (int i = 0; i < layout.cells.length; i++) { + for (int j = 0; j < layout.cells[i].length; j++) { if (i < cols && j < rows) { - newCells[i][j] = getWidgetForPaintable().cells[i][j]; + newCells[i][j] = layout.cells[i][j]; } } } - getWidgetForPaintable().cells = newCells; + layout.cells = newCells; } - getWidgetForPaintable().nonRenderedWidgets = (HashMap) getWidgetForPaintable().widgetToComponentContainer - .clone(); - final int[] alignments = uidl.getIntArrayAttribute("alignments"); int alignmentIndex = 0; - LinkedList pendingCells = new LinkedList(); - - LinkedList relativeHeighted = new LinkedList(); + HashSet nonRenderedWidgets = new HashSet( + layout.widgetToCell.keySet()); for (final Iterator i = uidl.getChildIterator(); i.hasNext();) { final UIDL r = (UIDL) i.next(); @@ -95,96 +88,59 @@ public class VGridLayoutPaintable extends VAbstractPaintableWidgetContainer for (final Iterator j = r.getChildIterator(); j.hasNext();) { final UIDL c = (UIDL) j.next(); if ("gc".equals(c.getTag())) { - Cell cell = getWidgetForPaintable().getCell(c); + Cell cell = layout.getCell(c); if (cell.hasContent()) { - boolean rendered = cell.renderIfNoRelativeWidth(); - cell.alignment = alignments[alignmentIndex++]; - if (!rendered) { - pendingCells.add(cell); - } - - if (cell.colspan > 1) { - getWidgetForPaintable().storeColSpannedCell( - cell); - } else if (rendered) { - // strore non-colspanned widths to columnWidth - // array - if (getWidgetForPaintable().columnWidths[cell.col] < cell - .getWidth()) { - getWidgetForPaintable().columnWidths[cell.col] = cell - .getWidth(); - } - } - if (cell.hasRelativeHeight()) { - relativeHeighted.add(cell); - } + cell.setAlignment(new AlignmentInfo( + alignments[alignmentIndex++])); + nonRenderedWidgets.remove(cell.slot.getWidget()); } } } } } - 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")); + + getMeasuredSize().setHeightNeedsUpdate(); + getMeasuredSize().setWidthNeedsUpdate(); } - public void updateCaption(VPaintableWidget paintable, UIDL uidl) { - Widget widget = paintable.getWidgetForPaintable(); - ChildComponentContainer cc = getWidgetForPaintable().widgetToComponentContainer - .get(widget); - if (cc != null) { - cc.updateCaption(uidl, getConnection(), getMeasuredSize()); - } - if (!getWidgetForPaintable().rendering) { - // ensure rel size details are updated - getWidgetForPaintable().widgetToCell.get(widget) - .updateRelSizeStatus(uidl); - /* - * This was a component-only update and the possible size change - * must be propagated to the layout - */ - getConnection().captionSizeUpdated(widget); + public void updateCaption(VPaintableWidget component, UIDL uidl) { + VGridLayout layout = getWidgetForPaintable(); + if (VCaption.isNeeded(uidl)) { + Cell cell = layout.widgetToCell.get(component + .getWidgetForPaintable()); + VLayoutSlot layoutSlot = cell.slot; + 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); } } @@ -199,24 +155,10 @@ public class VGridLayoutPaintable extends VAbstractPaintableWidgetContainer } public void updateVerticalSizes() { - int innerHeight = getMeasuredSize().getInnerHeight(); - getWidgetForPaintable().updateHeight(innerHeight, isUndefinedHeight()); - layoutAllChildren(); - } - - private void layoutAllChildren() { - HashSet childWidgets = new HashSet(); - Collection children = getChildren(); - for (VPaintableWidget vPaintableWidget : children) { - childWidgets.add(vPaintableWidget.getWidgetForPaintable()); - } - getWidgetForPaintable().requestLayout(childWidgets); + getWidgetForPaintable().updateHeight(); } public void updateHorizontalSizes() { - int innerWidth = getMeasuredSize().getInnerWidth(); - getWidgetForPaintable().updateWidth(innerWidth, isUndefinedWidth()); - - layoutAllChildren(); + getWidgetForPaintable().updateWidth(); } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/ChildComponentContainer.java b/src/com/vaadin/terminal/gwt/client/ui/layout/ChildComponentContainer.java deleted file mode 100644 index 6972cfb587..0000000000 --- a/src/com/vaadin/terminal/gwt/client/ui/layout/ChildComponentContainer.java +++ /dev/null @@ -1,757 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.terminal.gwt.client.ui.layout; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import com.google.gwt.dom.client.DivElement; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.Style.Display; -import com.google.gwt.user.client.ui.Panel; -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.MeasuredSize; -import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize; -import com.vaadin.terminal.gwt.client.RenderInformation.Size; -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.VConsole; -import com.vaadin.terminal.gwt.client.VPaintableWidget; -import com.vaadin.terminal.gwt.client.ui.AlignmentInfo; - -public class ChildComponentContainer extends Panel { - - public static final int ORIENTATION_VERTICAL = 0; - public static final int ORIENTATION_HORIZONTAL = 1; - - /** - * Size of the container DIV excluding any margins and also excluding the - * expansion amount (containerExpansion) - */ - private Size contSize = new Size(0, 0); - - /** - * Size of the widget inside the container DIV - */ - private Size widgetSize = new Size(0, 0); - /** - * Size of the caption - */ - private int captionRequiredWidth = 0; - private int captionWidth = 0; - private int captionHeight = 0; - - /** - * - * Padding added to the container when it is larger than the component. - */ - private Size containerExpansion = new Size(0, 0); - - private double expandRatio; - - // private int containerMarginLeft = 0; - private int containerMarginTop = 0; - - AlignmentInfo alignment = AlignmentInfo.TOP_LEFT; - - private int alignmentLeftOffsetForWidget = 0; - private int alignmentLeftOffsetForCaption = 0; - /** - * Top offset for implementing alignment. Top offset is set to the container - * DIV as it otherwise would have to be set to either the Caption or the - * Widget depending on whether there is a caption and where the caption is - * located. - */ - private int alignmentTopOffset = 0; - - // private Margins alignmentOffset = new Margins(0, 0, 0, 0); - private VCaption caption = null; - private DivElement containerDIV; - private DivElement widgetDIV; - private VPaintableWidget paintable; - private Widget widget; - private FloatSize relativeSize = null; - - public ChildComponentContainer(VPaintableWidget child, int orientation) { - super(); - - containerDIV = Document.get().createDivElement(); - - widgetDIV = Document.get().createDivElement(); - - setElement(containerDIV); - containerDIV.getStyle().setProperty("height", "0"); - containerDIV.getStyle().setProperty("width", "0px"); - containerDIV.getStyle().setProperty("overflow", "hidden"); - - if (BrowserInfo.get().isIE()) { - /* - * IE requires position: relative on overflow:hidden elements if - * they should hide position:relative elements. Without this e.g. a - * 1000x1000 Panel inside an 500x500 OrderedLayout will not be - * clipped but fully shown. - */ - containerDIV.getStyle().setProperty("position", "relative"); - widgetDIV.getStyle().setProperty("position", "relative"); - } - - containerDIV.appendChild(widgetDIV); - - setOrientation(orientation); - - setPaintable(child); - } - - public void setPaintable(VPaintableWidget childPaintable) { - paintable = childPaintable; - setWidget(childPaintable.getWidgetForPaintable()); - } - - private void setWidget(Widget w) { - // Validate - if (w == widget) { - return; - } - - // Detach new child. - if (w != null) { - w.removeFromParent(); - } - - // Remove old child. - if (widget != null) { - remove(widget); - } - - // Logical attach. - widget = w; - - if (w != null) { - // Physical attach. - widgetDIV.appendChild(widget.getElement()); - adopt(w); - w.getElement().getStyle().setDisplay(Display.INLINE_BLOCK); - } - } - - private static void setFloat(Element div, String floatString) { - if (BrowserInfo.get().isIE()) { - div.getStyle().setProperty("styleFloat", floatString); - // IE requires display:inline for margin-left to work together - // with float:left - if (floatString.equals("left")) { - div.getStyle().setProperty("display", "inline"); - } else { - div.getStyle().setProperty("display", "block"); - } - - } else { - div.getStyle().setProperty("cssFloat", floatString); - } - } - - public void setOrientation(int orientation) { - if (orientation == ORIENTATION_HORIZONTAL) { - setFloat(getElement(), "left"); - } else { - setFloat(getElement(), ""); - } - setHeight("0px"); - // setWidth("0px"); - contSize.setHeight(0); - contSize.setWidth(0); - // containerMarginLeft = 0; - containerMarginTop = 0; - containerDIV.getStyle().setProperty("paddingLeft", "0"); - containerDIV.getStyle().setProperty("paddingTop", "0"); - - containerExpansion.setHeight(0); - containerExpansion.setWidth(0); - - // Clear old alignments - clearAlignments(); - - } - - public void renderChild(UIDL childUIDL, ApplicationConnection client, - int fixedWidth) { - /* - * Must remove width specification from container before rendering to - * allow components to grow in horizontal direction. - * - * For fixed width layouts we specify the width directly so that height - * is automatically calculated correctly (e.g. for Labels). - */ - /* - * This should no longer be needed (after #2563) as all components are - * such that they can be rendered inside a 0x0 DIV. - * - * The exception seems to be complex components (Tree and Table) on - * Opera (#3444). - */ - if (fixedWidth < 0 && BrowserInfo.get().isOpera()) { - setUnlimitedContainerWidth(); - } - paintable.updateFromUIDL(childUIDL, client); - } - - public void setUnlimitedContainerWidth() { - setLimitedContainerWidth(1000000); - } - - public void setLimitedContainerWidth(int width) { - containerDIV.getStyle().setProperty("width", width + "px"); - } - - public void updateWidgetSize() { - /* - * Widget wrapper includes margin which the widget offsetWidth/Height - * does not include - */ - int w = Util.getRequiredWidth(widgetDIV); - int h = Util.getRequiredHeight(widgetDIV); - - widgetSize.setWidth(w); - widgetSize.setHeight(h); - - // ApplicationConnection.getConsole().log( - // Util.getSimpleName(widget) + " size is " + w + "," + h); - - } - - public void setMarginLeft(int marginLeft) { - // containerMarginLeft = marginLeft; - containerDIV.getStyle().setPropertyPx("paddingLeft", marginLeft); - } - - public void setMarginTop(int marginTop) { - containerMarginTop = marginTop; - containerDIV.getStyle().setPropertyPx("paddingTop", - marginTop + alignmentTopOffset); - - updateContainerDOMSize(); - } - - public void updateAlignments(int parentWidth, int parentHeight) { - if (parentHeight == -1) { - parentHeight = contSize.getHeight(); - } - if (parentWidth == -1) { - parentWidth = contSize.getWidth(); - } - - alignmentTopOffset = calculateVerticalAlignmentTopOffset(parentHeight); - - calculateHorizontalAlignment(parentWidth); - - applyAlignments(); - - } - - private void applyAlignments() { - - // Update top margin to take alignment into account - setMarginTop(containerMarginTop); - - if (caption != null) { - caption.getElement().getStyle() - .setPropertyPx("marginLeft", alignmentLeftOffsetForCaption); - } - widgetDIV.getStyle().setPropertyPx("marginLeft", - alignmentLeftOffsetForWidget); - } - - public int getCaptionRequiredWidth() { - if (caption == null) { - return 0; - } - - return captionRequiredWidth; - } - - public int getCaptionWidth() { - if (caption == null) { - return 0; - } - - return captionWidth; - } - - public int getCaptionHeight() { - if (caption == null) { - return 0; - } - - return captionHeight; - } - - public int getCaptionWidthAfterComponent() { - if (caption == null || !caption.shouldBePlacedAfterComponent()) { - return 0; - } - - return getCaptionWidth(); - } - - public int getCaptionHeightAboveComponent() { - if (caption == null || caption.shouldBePlacedAfterComponent()) { - return 0; - } - - return getCaptionHeight(); - } - - private int calculateVerticalAlignmentTopOffset(int emptySpace) { - if (alignment.isTop()) { - return 0; - } - - if (caption != null) { - if (caption.shouldBePlacedAfterComponent()) { - /* - * Take into account the rare case that the caption on the right - * side of the component AND is higher than the component - */ - emptySpace -= Math.max(widgetSize.getHeight(), - caption.getHeight()); - } else { - emptySpace -= widgetSize.getHeight(); - emptySpace -= getCaptionHeight(); - } - } else { - /* - * There is no caption and thus we do not need to take anything but - * the widget into account - */ - emptySpace -= widgetSize.getHeight(); - } - - int top = 0; - if (alignment.isVerticalCenter()) { - top = emptySpace / 2; - } else if (alignment.isBottom()) { - top = emptySpace; - } - - if (top < 0) { - top = 0; - } - return top; - } - - private void calculateHorizontalAlignment(int emptySpace) { - alignmentLeftOffsetForCaption = 0; - alignmentLeftOffsetForWidget = 0; - - if (alignment.isLeft()) { - return; - } - - int captionSpace = emptySpace; - int widgetSpace = emptySpace; - - if (caption != null) { - // There is a caption - if (caption.shouldBePlacedAfterComponent()) { - /* - * The caption is after component. In this case the caption - * needs no alignment. - */ - captionSpace = 0; - widgetSpace -= widgetSize.getWidth(); - widgetSpace -= getCaptionWidth(); - } else { - /* - * The caption is above the component. Caption and widget needs - * separate alignment offsets. - */ - widgetSpace -= widgetSize.getWidth(); - captionSpace -= getCaptionWidth(); - } - } else { - /* - * There is no caption and thus we do not need to take anything but - * the widget into account - */ - captionSpace = 0; - widgetSpace -= widgetSize.getWidth(); - } - - if (alignment.isHorizontalCenter()) { - alignmentLeftOffsetForCaption = captionSpace / 2; - alignmentLeftOffsetForWidget = widgetSpace / 2; - } else if (alignment.isRight()) { - alignmentLeftOffsetForCaption = captionSpace; - alignmentLeftOffsetForWidget = widgetSpace; - } - - if (alignmentLeftOffsetForCaption < 0) { - alignmentLeftOffsetForCaption = 0; - } - if (alignmentLeftOffsetForWidget < 0) { - alignmentLeftOffsetForWidget = 0; - } - - } - - public void setAlignment(AlignmentInfo alignmentInfo) { - alignment = alignmentInfo; - } - - public Size getWidgetSize() { - return widgetSize; - } - - public void updateCaption(UIDL uidl, ApplicationConnection client, - MeasuredSize parentSize) { - if (VCaption.isNeeded(uidl)) { - // We need a caption - - VCaption newCaption = caption; - - if (newCaption == null) { - newCaption = new VCaption(paintable, client); - // Set initial height to avoid Safari flicker - newCaption.setHeight("18px"); - parentSize.registerDependency(newCaption.getElement()); - // newCaption.setHeight(newCaption.getHeight()); // This might - // be better... ?? - if (BrowserInfo.get().isIE()) { - /* - * Must attach caption here so IE sends an immediate onload - * event for images coming from the cache - */ - setCaption(newCaption); - } - } - - boolean positionChanged = newCaption.updateCaption(uidl); - - if (newCaption != caption || positionChanged) { - setCaption(newCaption); - } - - } else { - // Caption is not needed - if (caption != null) { - parentSize.deRegisterDependency(caption.getElement()); - remove(caption); - } - - } - - updateCaptionSize(); - - if (relativeSize == null) { - /* - * relativeSize may be null if component is updated via independent - * update, after it has initially been hidden. See #4608 - * - * It might also change in which case there would be similar issues. - * - * Yes, it is an ugly hack. Don't come telling me about it. - */ - setRelativeSize(Util.parseRelativeSize(uidl)); - } - } - - public void updateCaptionSize() { - captionWidth = 0; - captionHeight = 0; - - if (caption != null) { - captionWidth = caption.getRenderedWidth(); - captionHeight = caption.getHeight(); - captionRequiredWidth = caption.getRequiredWidth(); - - /* - * ApplicationConnection.getConsole().log( - * "Caption rendered width: " + captionWidth + - * ", caption required width: " + captionRequiredWidth + - * ", caption height: " + captionHeight); - */ - } - - } - - private void setCaption(VCaption newCaption) { - // Validate - // if (newCaption == caption) { - // return; - // } - - // Detach new child. - if (newCaption != null) { - newCaption.removeFromParent(); - } - - // Remove old child. - if (caption != null && newCaption != caption) { - remove(caption); - } - - // Logical attach. - caption = newCaption; - - if (caption != null) { - // Physical attach. - if (caption.shouldBePlacedAfterComponent()) { - Util.setFloat(caption.getElement(), "left"); - containerDIV.appendChild(caption.getElement()); - } else { - Util.setFloat(caption.getElement(), ""); - containerDIV.insertBefore(caption.getElement(), widgetDIV); - } - - adopt(caption); - } - - } - - @Override - public boolean remove(Widget child) { - // Validate - if (child != caption && child != widget) { - return false; - } - - // Orphan - orphan(child); - - // Physical && Logical Detach - if (child == caption) { - containerDIV.removeChild(child.getElement()); - caption = null; - } else { - widgetDIV.removeChild(child.getElement()); - widget = null; - } - - return true; - } - - public Iterator iterator() { - return new ChildComponentContainerIterator(); - } - - public class ChildComponentContainerIterator implements Iterator { - private int id = 0; - - public boolean hasNext() { - return (id < size()); - } - - public Widget next() { - Widget w = get(id); - id++; - return w; - } - - private Widget get(int i) { - if (i == 0) { - if (widget != null) { - return widget; - } else if (caption != null) { - return caption; - } else { - throw new NoSuchElementException(); - } - } else if (i == 1) { - if (widget != null && caption != null) { - return caption; - } else { - throw new NoSuchElementException(); - } - } else { - throw new NoSuchElementException(); - } - } - - public void remove() { - int toRemove = id - 1; - if (toRemove == 0) { - if (widget != null) { - ChildComponentContainer.this.remove(widget); - } else if (caption != null) { - ChildComponentContainer.this.remove(caption); - } else { - throw new IllegalStateException(); - } - - } else if (toRemove == 1) { - if (widget != null && caption != null) { - ChildComponentContainer.this.remove(caption); - } else { - throw new IllegalStateException(); - } - } else { - throw new IllegalStateException(); - } - - id--; - } - } - - public int size() { - if (widget != null) { - if (caption != null) { - return 2; - } else { - return 1; - } - } else { - if (caption != null) { - return 1; - } else { - return 0; - } - } - } - - public Widget getWidget() { - return widget; - } - - /** - * Return true if the size of the widget has been specified in the selected - * orientation. - * - * @return - */ - public boolean widgetHasSizeSpecified(int orientation) { - String size; - if (orientation == ORIENTATION_HORIZONTAL) { - size = widget.getElement().getStyle().getProperty("width"); - } else { - size = widget.getElement().getStyle().getProperty("height"); - } - return (size != null && !size.equals("")); - } - - public boolean isComponentRelativeSized(int orientation) { - if (relativeSize == null) { - return false; - } - if (orientation == ORIENTATION_HORIZONTAL) { - return relativeSize.getWidth() >= 0; - } else { - return relativeSize.getHeight() >= 0; - } - } - - public void setRelativeSize(FloatSize relativeSize) { - this.relativeSize = relativeSize; - } - - public Size getContSize() { - return contSize; - } - - public void clearAlignments() { - alignmentLeftOffsetForCaption = 0; - alignmentLeftOffsetForWidget = 0; - alignmentTopOffset = 0; - applyAlignments(); - - } - - /** - * Sets the normalized expand ratio of this slot. The fraction that this - * slot will use of "excess space". - * - * @param expandRatio - */ - public void setNormalizedExpandRatio(double expandRatio) { - this.expandRatio = expandRatio; - } - - public int expand(int orientation, int spaceForExpansion) { - int expansionAmount = (int) (spaceForExpansion * expandRatio); - - if (orientation == ORIENTATION_HORIZONTAL) { - // HORIZONTAL - containerExpansion.setWidth(expansionAmount); - } else { - // VERTICAL - containerExpansion.setHeight(expansionAmount); - } - - return expansionAmount; - } - - public void expandExtra(int orientation, int extra) { - if (orientation == ORIENTATION_HORIZONTAL) { - // HORIZONTAL - containerExpansion.setWidth(containerExpansion.getWidth() + extra); - } else { - // VERTICAL - containerExpansion - .setHeight(containerExpansion.getHeight() + extra); - } - - } - - public void setContainerSize(int widgetAndCaptionWidth, - int widgetAndCaptionHeight) { - - int containerWidth = widgetAndCaptionWidth; - containerWidth += containerExpansion.getWidth(); - - int containerHeight = widgetAndCaptionHeight; - containerHeight += containerExpansion.getHeight(); - - // ApplicationConnection.getConsole().log( - // "Setting container size for " + Util.getSimpleName(widget) - // + " to " + containerWidth + "," + containerHeight); - - if (containerWidth < 0) { - VConsole.log("containerWidth should never be negative: " - + containerWidth); - containerWidth = 0; - } - if (containerHeight < 0) { - VConsole.log("containerHeight should never be negative: " - + containerHeight); - containerHeight = 0; - } - - contSize.setWidth(containerWidth); - contSize.setHeight(containerHeight); - - updateContainerDOMSize(); - } - - public void updateContainerDOMSize() { - int width = contSize.getWidth(); - int height = contSize.getHeight() - alignmentTopOffset; - if (width < 0) { - width = 0; - } - if (height < 0) { - height = 0; - } - - setWidth(width + "px"); - setHeight(height + "px"); - - // Also update caption max width - if (caption != null) { - if (caption.shouldBePlacedAfterComponent()) { - caption.setMaxWidth(captionWidth); - } else { - caption.setMaxWidth(width); - } - captionWidth = caption.getRenderedWidth(); - - // Remove initial height - caption.setHeight(""); - } - - } - -} -- 2.39.5