move calculations and layout for inside bullets to List

Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/List.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/List.java
index 82c8629..773bf34 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/List.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/List.java
@@ -142,6 +142,7 @@
 		}
 
 		for (final ListItem listItem : listItems) {
+			listItem.setBulletPosition(bulletStyle.position);
 			listItem.setBulletWidth(bulletWidth);
 		}
 	}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/ListItem.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/ListItem.java
index 0e0eef2..b93e59c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/ListItem.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/ListItem.java
@@ -10,9 +10,14 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.boxes;
 
+import static org.eclipse.vex.core.internal.boxes.BoxFactory.frame;
+
+import java.util.Iterator;
+
 import org.eclipse.vex.core.internal.core.Graphics;
 import org.eclipse.vex.core.internal.core.Rectangle;
 import org.eclipse.vex.core.internal.core.TextAlign;
+import org.eclipse.vex.core.internal.css.BulletStyle;
 
 public class ListItem extends BaseBox implements IStructuralBox, IDecoratorBox<IStructuralBox> {
 
@@ -25,6 +30,8 @@
 	private int height;
 
 	private IInlineBox bullet;
+
+	private BulletStyle.Position bulletPosition = BulletStyle.Position.OUTSIDE;
 	private int bulletWidth;
 	private TextAlign bulletAlign = TextAlign.RIGHT;
 
@@ -101,6 +108,19 @@
 		return visitor.visit(this);
 	}
 
+	public void setBulletPosition(final BulletStyle.Position bulletPosition) {
+		if (bulletPosition == this.bulletPosition) {
+			return;
+		}
+
+		this.bulletPosition = bulletPosition;
+		bulletContainer = null;
+	}
+
+	public BulletStyle.Position getBulletPosition() {
+		return bulletPosition;
+	}
+
 	public void setBulletWidth(final int bulletWidth) {
 		this.bulletWidth = bulletWidth;
 	}
@@ -138,7 +158,16 @@
 
 	@Override
 	public void layout(final Graphics graphics) {
-		layoutWithOutsideBullet(graphics);
+		switch (bulletPosition) {
+		case OUTSIDE:
+			layoutWithOutsideBullet(graphics);
+			break;
+		case INSIDE:
+			layoutWithInsideBullet(graphics);
+			break;
+		default:
+			throw new AssertionError("Unknown BulletStyle.Position " + bulletPosition);
+		}
 
 		height = Math.max(getBulletHeight(), getComponentHeight());
 	}
@@ -245,10 +274,61 @@
 		return result.intValue();
 	}
 
+	private void layoutWithInsideBullet(final Graphics graphics) {
+		if (component == null) {
+			return;
+		}
+
+		insertBulletIntoComponent();
+
+		component.setWidth(width);
+		component.setPosition(0, 0);
+		component.layout(graphics);
+	}
+
+	private void insertBulletIntoComponent() {
+		component.accept(new DepthFirstBoxTraversal<Object>() {
+			@Override
+			public Object visit(final Paragraph box) {
+				if (!isDecorated(box, bullet)) {
+					box.prependChild(frame(bullet, Margin.NULL, Border.NULL, new Padding(0, 0, 0, BULLET_SPACING), null));
+				}
+				return box;
+			}
+
+			private boolean isDecorated(final Paragraph box, final IInlineBox bullet) {
+				final IInlineBox firstChild = getFirstChild(box);
+				if (!(firstChild instanceof InlineFrame)) {
+					return false;
+				}
+				final InlineFrame frame = (InlineFrame) firstChild;
+
+				if (frame.getComponent().getClass().isAssignableFrom(bullet.getClass())) {
+					return true;
+				}
+
+				return false;
+			}
+
+			private IInlineBox getFirstChild(final Paragraph box) {
+				final Iterator<IInlineBox> iterator = box.getChildren().iterator();
+				if (iterator.hasNext()) {
+					return iterator.next();
+				}
+				return null;
+			}
+		});
+	}
+
 	@Override
 	public boolean reconcileLayout(final Graphics graphics) {
 		final int oldHeight = height;
 
+		if (bulletPosition == BulletStyle.Position.INSIDE && component != null) {
+			insertBulletIntoComponent();
+			component.layout(graphics);
+		}
+
 		height = Math.max(getBulletHeight(), getComponentHeight());
 
 		return oldHeight != height;
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 9a257bc..dac8733 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
@@ -10,7 +10,6 @@
  *******************************************************************************/
 package org.eclipse.vex.core.internal.visualization;
 
-import static org.eclipse.vex.core.internal.boxes.BoxFactory.frame;
 import static org.eclipse.vex.core.internal.boxes.BoxFactory.inlineContainer;
 import static org.eclipse.vex.core.internal.boxes.BoxFactory.listItem;
 import static org.eclipse.vex.core.internal.boxes.BoxFactory.nodeReference;
@@ -33,26 +32,18 @@
 import java.net.MalformedURLException;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
 import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.vex.core.internal.boxes.Border;
-import org.eclipse.vex.core.internal.boxes.DepthFirstBoxTraversal;
 import org.eclipse.vex.core.internal.boxes.IBulletFactory;
 import org.eclipse.vex.core.internal.boxes.IInlineBox;
 import org.eclipse.vex.core.internal.boxes.IParentBox;
 import org.eclipse.vex.core.internal.boxes.IStructuralBox;
-import org.eclipse.vex.core.internal.boxes.IVisualDecorator;
 import org.eclipse.vex.core.internal.boxes.Image;
 import org.eclipse.vex.core.internal.boxes.InlineContainer;
-import org.eclipse.vex.core.internal.boxes.InlineFrame;
 import org.eclipse.vex.core.internal.boxes.LineWrappingRule;
-import org.eclipse.vex.core.internal.boxes.ListItem;
-import org.eclipse.vex.core.internal.boxes.Margin;
-import org.eclipse.vex.core.internal.boxes.Padding;
 import org.eclipse.vex.core.internal.boxes.Paragraph;
 import org.eclipse.vex.core.internal.boxes.RootBox;
 import org.eclipse.vex.core.internal.boxes.TextContent;
@@ -225,28 +216,6 @@
 		return list(visualizeAsBlock(element, styles, childrenResults), styles, visualizeBullet(styles));
 	}
 
-	/*
-	 * Render as ListItem
-	 */
-
-	private IStructuralBox visualizeAsListItem(final IElement element, final Styles styles, final Collection<VisualizeResult> childrenResults) {
-		final BulletStyle bulletStyle = BulletStyle.fromStyles(styles);
-
-		final IStructuralBox content = visualizeStructuralElementContent(element, styles, childrenResults);
-
-		switch (bulletStyle.position) {
-		case OUTSIDE:
-			return wrapUpStructuralElementContent(element, styles, childrenResults, listItem(content));
-		case INSIDE:
-			final IInlineBox bullet = visualizeBullet(styles).createBullet(bulletStyle, 0, 1);
-			content.setVisualDecorator(insertBulletIntoContent(bullet));
-			content.applyVisualDecorator();
-			return wrapUpStructuralElementContent(element, styles, childrenResults, content);
-		default:
-			throw new AssertionError("Unknown BulletStyle.Position " + bulletStyle.position);
-		}
-	}
-
 	private static IBulletFactory visualizeBullet(final Styles styles) {
 		return new IBulletFactory() {
 			@Override
@@ -262,43 +231,13 @@
 		};
 	}
 
-	private static IVisualDecorator<IStructuralBox> insertBulletIntoContent(final IInlineBox bullet) {
-		return new IVisualDecorator<IStructuralBox>() {
-			@Override
-			public void decorate(final IStructuralBox decoratedBox) {
-				decoratedBox.accept(new DepthFirstBoxTraversal<Object>() {
-					@Override
-					public Object visit(final Paragraph box) {
-						if (!isDecorated(box, bullet)) {
-							box.prependChild(frame(bullet, Margin.NULL, Border.NULL, new Padding(0, 0, 0, ListItem.BULLET_SPACING), null));
-						}
-						return box;
-					}
+	/*
+	 * Render as ListItem
+	 */
 
-					private boolean isDecorated(final Paragraph box, final IInlineBox bullet) {
-						final IInlineBox firstChild = getFirstChild(box);
-						if (!(firstChild instanceof InlineFrame)) {
-							return false;
-						}
-						final InlineFrame frame = (InlineFrame) firstChild;
-
-						if (frame.getComponent().getClass().isAssignableFrom(bullet.getClass())) {
-							return true;
-						}
-
-						return false;
-					}
-
-					private IInlineBox getFirstChild(final Paragraph box) {
-						final Iterator<IInlineBox> iterator = box.getChildren().iterator();
-						if (iterator.hasNext()) {
-							return iterator.next();
-						}
-						return null;
-					}
-				});
-			}
-		};
+	private IStructuralBox visualizeAsListItem(final IElement element, final Styles styles, final Collection<VisualizeResult> childrenResults) {
+		final IStructuralBox content = visualizeStructuralElementContent(element, styles, childrenResults);
+		return wrapUpStructuralElementContent(element, styles, childrenResults, listItem(content));
 	}
 
 	/*