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<Widget, ChildComponentContainer> widgetToComponentContainer = new HashMap<Widget, ChildComponentContainer>();
-
HashMap<Widget, Cell> widgetToCell = new HashMap<Widget, Cell>();
- 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;
private int[] minRowHeights;
- boolean rendering;
-
- HashMap<Widget, ChildComponentContainer> 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);
}
/**
* @return
*/
protected int getHorizontalSpacing() {
- return spacingPixelsHorizontal;
+ return getMeasuredSize().getDependencyOuterWidth(spacingMeasureElement);
}
/**
* @return
*/
protected int getVerticalSpacing() {
- return spacingPixelsVertical;
+ return getMeasuredSize()
+ .getDependencyOuterHeight(spacingMeasureElement);
}
static int[] cloneArray(int[] toBeCloned) {
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) {
}
}
- 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<Integer> 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<Integer>();
- }
- 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) {
}
}
- 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<Cell> 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()) {
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) {
l.cells.add(cell);
}
- void renderRemainingComponentsWithNoRelativeHeight(
- LinkedList<Cell> pendingCells) {
-
- for (Iterator<Cell> 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
// subsequent renders
int width = cell.hasRelativeWidth() ? 0 : cell.getWidth();
distributeSpanSize(columnWidths, cell.col, cell.colspan,
- spacingPixelsHorizontal, width, colExpandRatioArray);
+ getHorizontalSpacing(), width, colExpandRatioArray);
}
}
}
// subsequent renders
int height = cell.hasRelativeHeight() ? 0 : cell.getHeight();
distributeSpanSize(rowHeights, cell.row, cell.rowspan,
- spacingPixelsVertical, height, rowExpandRatioArray);
+ getVerticalSpacing(), height, rowExpandRatioArray);
}
}
}
private LinkedList<SpanList> colSpans = new LinkedList<SpanList>();
private LinkedList<SpanList> rowSpans = new LinkedList<SpanList>();
- private int marginTopAndBottom;
-
private class SpanList {
final int span;
List<Cell> cells = new LinkedList<Cell>();
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<Widget> changedChildren) {
- boolean needsLayout = false;
- boolean reDistributeColSpanWidths = false;
- boolean reDistributeRowSpanHeights = false;
- int offsetHeight = canvas.getOffsetHeight();
- int offsetWidth = canvas.getOffsetWidth();
- if (isUndefinedWidth() || isUndefinedHeight()) {
- needsLayout = true;
- }
- ArrayList<Integer> dirtyColumns = new ArrayList<Integer>();
- ArrayList<Integer> dirtyRows = new ArrayList<Integer>();
- 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;
+ }
}
/**
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;
}
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++) {
}
}
- 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);
}
}
cell = new Cell(c);
cells[col][row] = cell;
} else {
- cell.setUidl(c);
+ cell.updateFromUidl(c);
}
return cell;
}
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");
+ }
+ }
+
}
*/
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;
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 {
}
};
+ 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<Widget, ChildComponentContainer>) getWidgetForPaintable().widgetToComponentContainer
- .clone();
-
final int[] alignments = uidl.getIntArrayAttribute("alignments");
int alignmentIndex = 0;
- LinkedList<Cell> pendingCells = new LinkedList<Cell>();
-
- LinkedList<Cell> relativeHeighted = new LinkedList<Cell>();
+ HashSet<Widget> nonRenderedWidgets = new HashSet<Widget>(
+ layout.widgetToCell.keySet());
for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) {
final UIDL r = (UIDL) i.next();
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);
}
}
}
public void updateVerticalSizes() {
- int innerHeight = getMeasuredSize().getInnerHeight();
- getWidgetForPaintable().updateHeight(innerHeight, isUndefinedHeight());
- layoutAllChildren();
- }
-
- private void layoutAllChildren() {
- HashSet<Widget> childWidgets = new HashSet<Widget>();
- Collection<VPaintableWidget> 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();
}
}
+++ /dev/null
-/*
-@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<Widget> iterator() {
- return new ChildComponentContainerIterator<Widget>();
- }
-
- public class ChildComponentContainerIterator<T> implements Iterator<Widget> {
- 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("");
- }
-
- }
-
-}