all cells in a row should have the same height

Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TableCell.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TableCell.java
index b0576fd..cdfad2d 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TableCell.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TableCell.java
@@ -35,6 +35,8 @@
 	private String startColumnName;
 	private String endColumnName;
 
+	private int naturalHeight;
+
 	@Override
 	public void setParent(final IBox parent) {
 		this.parent = parent;
@@ -88,6 +90,14 @@
 		return height;
 	}
 
+	public void setHeight(final int height) {
+		this.height = height;
+	}
+
+	public int getNaturalHeight() {
+		return naturalHeight;
+	}
+
 	@Override
 	public Rectangle getBounds() {
 		return new Rectangle(left, top, width, height);
@@ -184,27 +194,47 @@
 		this.endColumnName = endColumnName;
 	}
 
-	public void layout(final Graphics graphics) {
-		height = 0;
+	public int calculateNaturalHeight(final Graphics graphics, final int width) {
+		naturalHeight = 0;
 		for (int i = 0; i < children.size(); i += 1) {
 			final IStructuralBox child = children.get(i);
-			child.setPosition(height, 0);
 			child.setWidth(width);
 			child.layout(graphics);
-			height += child.getHeight();
+			naturalHeight += child.getHeight();
+		}
+		height = naturalHeight;
+
+		return naturalHeight;
+	}
+
+	public void layout(final Graphics graphics) {
+		if (naturalHeight == 0) {
+			naturalHeight = calculateNaturalHeight(graphics, width);
+		}
+
+		positionChildren();
+	}
+
+	private void positionChildren() {
+		int childTop = 0;
+		for (int i = 0; i < children.size(); i += 1) {
+			final IStructuralBox child = children.get(i);
+			child.setPosition(childTop, 0);
+			childTop += child.getHeight();
 		}
 	}
 
 	@Override
 	public boolean reconcileLayout(final Graphics graphics) {
-		final int oldHeight = height;
-		height = 0;
-		for (int i = 0; i < children.size(); i += 1) {
-			final IStructuralBox child = children.get(i);
-			child.setPosition(height, 0);
-			height += child.getHeight();
+		final int oldHeight = naturalHeight;
+		naturalHeight = calculateNaturalHeight(graphics, width);
+
+		if (oldHeight == naturalHeight) {
+			return false;
 		}
-		return oldHeight != height;
+
+		positionChildren();
+		return true;
 	}
 
 	@Override
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TableRow.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TableRow.java
index 9a45ace..b67c49b 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TableRow.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TableRow.java
@@ -154,22 +154,35 @@
 
 	public void layout(final Graphics graphics) {
 		TableColumnLayout.addColumnLayoutInformationForChildren(graphics, this, columnLayout);
-		height = 0;
+		int cellHeight = 0;
 		int columnIndex = 1;
 		for (int i = 0; i < children.size(); i += 1) {
 			final IStructuralBox child = children.get(i);
+			final TableCell cell = getContainedTableCell(child);
+			if (cell != null) {
+				final int startColumn = getStartColumn(cell, columnIndex);
+				final int endColumn = getEndColumn(cell, startColumn);
 
-			final int startColumn = getStartColumn(child, columnIndex);
-			final int endColumn = getEndColumn(child, startColumn);
+				final int childLeft = getColumnWidth(1, startColumn - 1);
+				final int columnWidth = getColumnWidth(startColumn, endColumn);
 
-			final int childLeft = getColumnWidth(1, startColumn - 1);
-			final int columnWidth = getColumnWidth(startColumn, endColumn);
+				child.setWidth(columnWidth);
+				child.setPosition(0, childLeft);
 
-			child.setPosition(0, childLeft);
-			child.setWidth(columnWidth);
-			child.layout(graphics);
-			height = Math.max(height, child.getHeight());
-			columnIndex = endColumn + 1;
+				cellHeight = Math.max(cellHeight, cell.calculateNaturalHeight(graphics, columnWidth));
+				columnIndex = endColumn + 1;
+			}
+		}
+
+		height = 0;
+		for (int i = 0; i < children.size(); i += 1) {
+			final IStructuralBox child = children.get(i);
+			final TableCell cell = getContainedTableCell(child);
+			if (cell != null) {
+				cell.setHeight(cellHeight);
+				child.layout(graphics);
+				height = Math.max(height, child.getHeight());
+			}
 		}
 	}
 
@@ -188,41 +201,33 @@
 		return Math.round(width / columnLayout.getLastIndex());
 	}
 
-	private static int getStartColumn(final IStructuralBox box, final int defaultColumn) {
-		final int boxStartColumn = box.accept(new BaseBoxVisitorWithResult<Integer>(0) {
+	private static TableCell getContainedTableCell(final IStructuralBox parent) {
+		return parent.accept(new TableCellVisitor<TableCell>() {
 			@Override
-			public Integer visit(final TableCell box) {
-				return box.getStartColumnIndex();
+			public TableCell visit(final TableCell box) {
+				return box;
 			}
 		});
-		if (boxStartColumn > 0) {
-			return boxStartColumn;
-		}
-		return defaultColumn;
 	}
 
-	private static int getEndColumn(final IStructuralBox box, final int defaultColumn) {
-		final int boxEndColumn = box.accept(new BaseBoxVisitorWithResult<Integer>(0) {
-			@Override
-			public Integer visit(final TableCell box) {
-				return box.getEndColumnIndex();
-			}
-		});
-		if (boxEndColumn > 0) {
-			return boxEndColumn;
+	private static int getStartColumn(final TableCell cell, final int defaultColumn) {
+		if (cell == null || cell.getStartColumnIndex() <= defaultColumn) {
+			return defaultColumn;
 		}
-		return defaultColumn;
+		return cell.getStartColumnIndex();
+	}
+
+	private static int getEndColumn(final TableCell cell, final int defaultColumn) {
+		if (cell == null || cell.getEndColumnIndex() <= defaultColumn) {
+			return defaultColumn;
+		}
+		return cell.getEndColumnIndex();
 	}
 
 	@Override
 	public boolean reconcileLayout(final Graphics graphics) {
 		final int oldHeight = height;
-		height = 0;
-		for (int i = 0; i < children.size(); i += 1) {
-			final IStructuralBox child = children.get(i);
-			child.setPosition(height, 0);
-			height += child.getHeight();
-		}
+		layout(graphics);
 		return oldHeight != height;
 	}
 
@@ -230,4 +235,21 @@
 	public void paint(final Graphics graphics) {
 		ChildBoxPainter.paint(children, graphics);
 	}
+
+	private static class TableCellVisitor<T> extends DepthFirstBoxTraversal<T> {
+		@Override
+		public final T visit(final Table box) {
+			return null;
+		}
+
+		@Override
+		public final T visit(final TableRowGroup box) {
+			return null;
+		}
+
+		@Override
+		public final T visit(final TableRow box) {
+			return null;
+		}
+	};
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/visualization/CssBasedBoxModelBuilder.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/visualization/CssBasedBoxModelBuilder.java
index 3ccb5b2..d9e835d 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/visualization/CssBasedBoxModelBuilder.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/visualization/CssBasedBoxModelBuilder.java
@@ -314,8 +314,8 @@
 		return wrapUpStructuralElementContent(element, styles, childrenResults, row);
 	}
 
-	private TableCell visualizeAsTableCell(final IElement element, final Styles styles, final Collection<VisualizeResult> childrenResults) {
-		final TableCell cell = tableCell(visualizeAsBlock(element, styles, childrenResults));
+	private IStructuralBox visualizeAsTableCell(final IElement element, final Styles styles, final Collection<VisualizeResult> childrenResults) {
+		final TableCell cell = tableCell(visualizeStructuralElementContent(element, styles, childrenResults));
 
 		if ("entry".equals(element.getLocalName())) {
 			final IAttribute colName = element.getAttribute("colname");
@@ -336,7 +336,7 @@
 			// TODO HTML table
 		}
 
-		return cell;
+		return wrapUpStructuralElementContent(element, styles, childrenResults, cell);
 	}
 
 	private static int toInt(final IAttribute attribute) {