add support for bullet position INSIDE the listitem

Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/HorizontalBar.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/HorizontalBar.java
index 7c89188..394bb14 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/HorizontalBar.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/HorizontalBar.java
@@ -26,6 +26,7 @@
 	private int width;
 	private int height;
 	private Color color;
+	private IVisualDecorator<IStructuralBox> visualDecorator;
 
 	@Override
 	public void setParent(final IBox parent) {
@@ -127,4 +128,22 @@
 		graphics.setColor(colorResource);
 		graphics.fillRect(0, 0, width, height);
 	}
+
+	@Override
+	public void setVisualDecorator(final IVisualDecorator<IStructuralBox> visualDecorator) {
+		this.visualDecorator = visualDecorator;
+
+	}
+
+	@Override
+	public void resetVisualDecorator() {
+		visualDecorator = null;
+	}
+
+	@Override
+	public void applyVisualDecorator() {
+		if (visualDecorator != null) {
+			visualDecorator.decorate(this);
+		}
+	}
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/IStructuralBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/IStructuralBox.java
index 90c06f3..6234319 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/IStructuralBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/IStructuralBox.java
@@ -26,4 +26,9 @@
 	 */
 	Rectangle getBounds();
 
+	void setVisualDecorator(IVisualDecorator<IStructuralBox> visualDecorator);
+
+	void resetVisualDecorator();
+
+	void applyVisualDecorator();
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/IVisualDecorator.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/IVisualDecorator.java
new file mode 100644
index 0000000..31899fa
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/IVisualDecorator.java
@@ -0,0 +1,15 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Florian Thienel and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * 		Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.boxes;
+
+public interface IVisualDecorator<T extends IBox> {
+	void decorate(T box);
+}
\ No newline at end of file
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 37fbe84..97bd01a 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
@@ -15,7 +15,7 @@
 
 public class ListItem extends BaseBox implements IStructuralBox, IDecoratorBox<IStructuralBox> {
 
-	private static final int BULLET_SPACING = 10;
+	public static final int BULLET_SPACING = 5;
 
 	private IBox parent;
 	private int top;
@@ -27,6 +27,8 @@
 	private IStructuralBox bullet;
 	private IStructuralBox component;
 
+	private IVisualDecorator<IStructuralBox> visualDecorator;
+
 	@Override
 	public void setParent(final IBox parent) {
 		this.parent = parent;
@@ -255,4 +257,22 @@
 		ChildBoxPainter.paint(bullet, graphics);
 		ChildBoxPainter.paint(component, graphics);
 	}
+
+	@Override
+	public void setVisualDecorator(final IVisualDecorator<IStructuralBox> visualDecorator) {
+		this.visualDecorator = visualDecorator;
+
+	}
+
+	@Override
+	public void resetVisualDecorator() {
+		visualDecorator = null;
+	}
+
+	@Override
+	public void applyVisualDecorator() {
+		if (visualDecorator != null) {
+			visualDecorator.decorate(this);
+		}
+	}
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/Paragraph.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/Paragraph.java
index 4c67759..59d4ca5 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/Paragraph.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/Paragraph.java
@@ -32,6 +32,7 @@
 
 	private final LinkedList<IInlineBox> children = new LinkedList<IInlineBox>();
 	private final LineArrangement lines = new LineArrangement();
+	private IVisualDecorator<IStructuralBox> visualDecorator;
 
 	@Override
 	public void setParent(final IBox parent) {
@@ -208,4 +209,21 @@
 		}
 	}
 
+	@Override
+	public void setVisualDecorator(final IVisualDecorator<IStructuralBox> visualDecorator) {
+		this.visualDecorator = visualDecorator;
+
+	}
+
+	@Override
+	public void resetVisualDecorator() {
+		visualDecorator = null;
+	}
+
+	@Override
+	public void applyVisualDecorator() {
+		if (visualDecorator != null) {
+			visualDecorator.decorate(this);
+		}
+	}
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/StructuralFrame.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/StructuralFrame.java
index 8c05e4e..0ddec28 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/StructuralFrame.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/StructuralFrame.java
@@ -31,6 +31,7 @@
 	private Color backgroundColor = null;
 
 	private IStructuralBox component;
+	private IVisualDecorator<IStructuralBox> visualDecorator;
 
 	@Override
 	public void setParent(final IBox parent) {
@@ -230,4 +231,22 @@
 	private void paintComponent(final Graphics graphics) {
 		ChildBoxPainter.paint(component, graphics);
 	}
+
+	@Override
+	public void setVisualDecorator(final IVisualDecorator<IStructuralBox> visualDecorator) {
+		this.visualDecorator = visualDecorator;
+
+	}
+
+	@Override
+	public void resetVisualDecorator() {
+		visualDecorator = null;
+	}
+
+	@Override
+	public void applyVisualDecorator() {
+		if (visualDecorator != null) {
+			visualDecorator.decorate(this);
+		}
+	}
 }
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/StructuralNodeReference.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/StructuralNodeReference.java
index a9a8ba2..134453c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/StructuralNodeReference.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/StructuralNodeReference.java
@@ -38,6 +38,7 @@
 	private INode node;
 	private boolean canContainText;
 	private boolean containsInlineContent;
+	private IVisualDecorator<IStructuralBox> visualDecorator;
 
 	@Override
 	public void setParent(final IBox parent) {
@@ -321,6 +322,24 @@
 	}
 
 	@Override
+	public void setVisualDecorator(final IVisualDecorator<IStructuralBox> visualDecorator) {
+		this.visualDecorator = visualDecorator;
+
+	}
+
+	@Override
+	public void resetVisualDecorator() {
+		visualDecorator = null;
+	}
+
+	@Override
+	public void applyVisualDecorator() {
+		if (visualDecorator != null) {
+			visualDecorator.decorate(this);
+		}
+	}
+
+	@Override
 	public String toString() {
 		String result = "StructuralNodeReference{ ";
 		result += "x: " + left + ", y: " + top + ", width: " + width + ", height: " + height;
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/VerticalBlock.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/VerticalBlock.java
index 43c6324..f4da57c 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/VerticalBlock.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/VerticalBlock.java
@@ -31,6 +31,7 @@
 	private int width;
 	private int height;
 	private final ArrayList<IStructuralBox> children = new ArrayList<IStructuralBox>();
+	private IVisualDecorator<IStructuralBox> visualDecorator;
 
 	@Override
 	public void setParent(final IBox parent) {
@@ -168,4 +169,22 @@
 	public void paint(final Graphics graphics) {
 		ChildBoxPainter.paint(children, graphics);
 	}
+
+	@Override
+	public void setVisualDecorator(final IVisualDecorator<IStructuralBox> visualDecorator) {
+		this.visualDecorator = visualDecorator;
+
+	}
+
+	@Override
+	public void resetVisualDecorator() {
+		visualDecorator = null;
+	}
+
+	@Override
+	public void applyVisualDecorator() {
+		if (visualDecorator != null) {
+			visualDecorator.decorate(this);
+		}
+	}
 }
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 63e285d..5997350 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,6 +10,7 @@
  *******************************************************************************/
 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;
@@ -32,17 +33,25 @@
 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.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;
@@ -221,7 +230,7 @@
 	 */
 
 	private IStructuralBox visualizeAsListItem(final IElement element, final Styles styles, final Collection<VisualizeResult> childrenResults) {
-		final BulletStyle bulletStyle = new BulletStyle(BulletStyle.Type.SQUARE, BulletStyle.Position.OUTSIDE, null, '\0');
+		final BulletStyle bulletStyle = new BulletStyle(BulletStyle.Type.SQUARE, BulletStyle.Position.INSIDE, null, '\0');
 		final int bulletWidth = 20;
 		final int itemIndex = 0;
 		final int itemCount = 1;
@@ -234,8 +243,56 @@
 		}
 		final IStructuralBox content = visualizeStructuralElementContent(element, styles, childrenResults);
 
-		final IStructuralBox listItem = listItem(bulletWidth, paragraph(TextAlign.RIGHT, bullet), content);
-		return wrapUpStructuralElementContent(element, styles, childrenResults, listItem);
+		switch (bulletStyle.position) {
+		case OUTSIDE:
+			final IStructuralBox listItem = listItem(bulletWidth, paragraph(TextAlign.RIGHT, bullet), content);
+			return wrapUpStructuralElementContent(element, styles, childrenResults, listItem);
+		case INSIDE:
+			content.setVisualDecorator(insertBulletIntoContent(bullet));
+			content.applyVisualDecorator();
+			return wrapUpStructuralElementContent(element, styles, childrenResults, content);
+		default:
+			throw new AssertionError("Unknown BulletStyle.Position " + bulletStyle.position);
+		}
+	}
+
+	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;
+					}
+
+					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;
+					}
+				});
+			}
+		};
 	}
 
 	/*
@@ -287,15 +344,13 @@
 	}
 
 	private IStructuralBox visualizeStructuralElementContent(final IElement element, final Styles styles, final Collection<VisualizeResult> childrenResults) {
-		final IStructuralBox content;
 		if (isElementWithNoContentAllowed(element)) {
-			content = visualizeStructuralElementWithNoContentAllowed(styles, element);
+			return visualizeStructuralElementWithNoContentAllowed(styles, element);
 		} else if (element.isEmpty()) {
-			content = placeholderForEmptyNode(element, styles, paragraph(styles));
+			return placeholderForEmptyNode(element, styles, paragraph(styles));
 		} else {
-			content = visualizeChildrenAsStructure(element, styles, childrenResults, verticalBlock());
+			return visualizeChildrenAsStructure(element, styles, childrenResults, verticalBlock());
 		}
-		return content;
 	}
 
 	private static IStructuralBox visualizeStructuralElementWithNoContentAllowed(final Styles styles, final IElement element) {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/DOMVisualization.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/DOMVisualization.java
index f40ef6d..a87e173 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/DOMVisualization.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/DOMVisualization.java
@@ -21,6 +21,7 @@
 import org.eclipse.vex.core.internal.boxes.InlineContainer;
 import org.eclipse.vex.core.internal.boxes.InlineFrame;
 import org.eclipse.vex.core.internal.boxes.InlineNodeReference;
+import org.eclipse.vex.core.internal.boxes.ListItem;
 import org.eclipse.vex.core.internal.boxes.NodeEndOffsetPlaceholder;
 import org.eclipse.vex.core.internal.boxes.Paragraph;
 import org.eclipse.vex.core.internal.boxes.RootBox;
@@ -112,26 +113,31 @@
 			@Override
 			public void visit(final VerticalBlock box) {
 				box.replaceChildren(modifiedBoxes, boxModelBuilder.visualizeStructure(node));
+				box.applyVisualDecorator();
 			}
 
 			@Override
 			public void visit(final StructuralFrame box) {
 				box.setComponent(boxModelBuilder.visualizeStructure(node));
+				box.applyVisualDecorator();
 			}
 
 			@Override
 			public void visit(final StructuralNodeReference box) {
 				box.setComponent(boxModelBuilder.visualizeStructure(node));
+				box.applyVisualDecorator();
 			}
 
 			@Override
-			public void visit(final org.eclipse.vex.core.internal.boxes.ListItem box) {
+			public void visit(final ListItem box) {
 				box.setComponent(boxModelBuilder.visualizeStructure(node));
+				box.applyVisualDecorator();
 			}
 
 			@Override
 			public void visit(final Paragraph box) {
 				box.replaceChildren(modifiedBoxes, boxModelBuilder.visualizeInline(node));
+				box.applyVisualDecorator();
 			}
 
 			@Override