Index: trunk/src/org/expeditee/gui/Frame.java
===================================================================
--- trunk/src/org/expeditee/gui/Frame.java	(revision 998)
+++ trunk/src/org/expeditee/gui/Frame.java	(revision 1102)
@@ -19,9 +19,4 @@
 package org.expeditee.gui;
 
-import java.awt.Color;
-import java.awt.Image;
-import java.awt.Polygon;
-import java.awt.image.ImageObserver;
-import java.awt.image.VolatileImage;
 import java.sql.Time;
 import java.util.ArrayList;
@@ -37,4 +32,10 @@
 
 import org.expeditee.actions.Simple;
+import org.expeditee.core.Colour;
+import org.expeditee.core.Image;
+import org.expeditee.core.bounds.PolygonBounds;
+import org.expeditee.gio.gesture.StandardGestureActions;
+import org.expeditee.gio.input.StandardInputEventListeners;
+import org.expeditee.gio.input.KBMInputEvent.Key;
 import org.expeditee.io.Conversion;
 import org.expeditee.items.Constraint;
@@ -50,5 +51,5 @@
 import org.expeditee.items.UserAppliedPermission;
 import org.expeditee.items.XRayable;
-import org.expeditee.items.widgets.InteractiveWidget;
+import org.expeditee.items.widgets.Widget;
 import org.expeditee.items.widgets.WidgetCorner;
 import org.expeditee.settings.UserSettings;
@@ -66,12 +67,21 @@
  * 
  */
-public class Frame implements ImageObserver {
+public class Frame {
+	
+	/** The frame number to indicate this is a virtual frame. */
+	public static final int VIRTUAL_FRAME_NUMBER = -1;
+	
+	/** The background colour the frame name should take if the frame has user permission level 'none'. */
+	public static final Colour FRAME_NAME_BACKGROUND_COLOUR_FOR_PERMISSION_NONE = Colour.FromRGB255(255, 220, 220);
+	/** The background colour the frame name should take if the frame has user permission level 'followLinks'. */
+	public static final Colour FRAME_NAME_BACKGROUND_COLOUR_FOR_PERMISSION_FOLLOW_LINKS = Colour.FromRGB255(255, 230, 135);
+	/** The background colour the frame name should take if the frame has user permission level 'copy'. */
+	public static final Colour FRAME_NAME_BACKGROUND_COLOUR_FOR_PERMISSION_COPY = Colour.FromRGB255(255, 255, 155);
+	/** The background colour the frame name should take if the frame has user permission level 'createFrames'. */
+	public static final Colour FRAME_NAME_BACKGROUND_COLOUR_FOR_PERMISSION_CREATE_FRAMES = Colour.FromRGB255(220, 255, 220);
+	/** The background colour the frame name should take if the frame has user permission level 'full'. */
+	public static final Colour FRAME_NAME_BACKGROUND_COLOUR_FOR_PERMISSION_FULL = null;
 
 	private boolean _protectionChanged = false;
-
-	public boolean isReadOnly() {
-		return !_frameName.hasPermission(UserAppliedPermission.full)
-				&& !_protectionChanged;
-	}
 
 	// The various attributes of this Frame
@@ -95,8 +105,8 @@
 
 	// Background color is clear
-	private Color _background = null;
+	private Colour _background = null;
 
 	// Foreground color is automatic by default
-	private Color _foreground = null;
+	private Colour _foreground = null;
 
 	private String path;
@@ -105,29 +115,10 @@
 
 	private boolean _sorted = true;
-
-	// The items contained in this Frame
-	// records whether a change has been made to this Frame (for saving
-	// purposes).
+	
+	/** Whether the frame has changed and therefore needs saving. */
 	private boolean _change = false;
 
+	/** Whether the frame has been saved. */
 	private boolean _saved = false;
-
-	private static final class History {
-		public enum Type {
-			deletion,
-			movement
-		}
-		public final List<Item> items;
-		public final Type type;
-		
-		public History(Collection<Item> items, Type type) {
-			this.items = new LinkedList<Item>(items);
-			this.type = type;
-		}
-		
-		public String toString() {
-			return this.type.toString() + ":\n" + this.items.toString();
-		}
-	}
 	
 	// list of deleted items that can be restored
@@ -141,5 +132,5 @@
 
 	// for drawing purposes
-	private List<InteractiveWidget> _iWidgets = new ArrayList<InteractiveWidget>();
+	private List<Widget> _iWidgets = new ArrayList<Widget>();
 
 	private int _lineCount = 0;
@@ -170,64 +161,74 @@
 	private Text _dotTemplate = TemplateSettings.DotTemplate.get().copy();
 
-	/**
-	 * Default constructor, nothing is set.
-	 */
-	public Frame() {
-	}
-
-	public void reset() {
+	Map<String, Text> _annotations = null;
+
+	private Collection<FrameObserver> _observers = new HashSet<FrameObserver>();
+
+	/** Default constructor, nothing is set. */
+	public Frame()
+	{
+	}
+
+	public boolean isReadOnly()
+	{
+		return !_frameName.hasPermission(UserAppliedPermission.full) && !_protectionChanged;
+	}
+
+	public void reset()
+	{
 		refreshItemPermissions(UserAppliedPermission.full);
-		//System.out.println("Reset");
 		resetDot();
 		SessionStats.NewFrameSession();
 	}
 
-	private void resetDot() {
+	private void resetDot()
+	{
 	    _dotTemplate.setColor(TemplateSettings.ColorWheel.getSafe(1));
 	    _dotTemplate.setFillColor(TemplateSettings.FillColorWheel.getSafe(0));
 	}
 
-	public void nextDot() {
-		_dotTemplate.setFillColor(ColorUtils.getNextColor(_dotTemplate
-				.getFillColor(), TemplateSettings.FillColorWheel.get(), null));
-		_dotTemplate.setColor(ColorUtils.getNextColor(_dotTemplate.getColor(),
-				TemplateSettings.ColorWheel.get(), null));
-
-		if (_dotTemplate.getColor() == null || _dotTemplate.getColor().equals(Color.white)) {
-			resetDot();
-		}
-	}
-
-	public Image getBuffer() {
+	public void nextDot()
+	{
+		_dotTemplate.setFillColor(ColorUtils.getNextColor(_dotTemplate.getFillColor(), TemplateSettings.FillColorWheel.get(), null));
+		_dotTemplate.setColor(ColorUtils.getNextColor(_dotTemplate.getColor(), TemplateSettings.ColorWheel.get(), null));
+		if (_dotTemplate.getColor() == null || _dotTemplate.getColor().equals(Colour.WHITE)) resetDot();
+	}
+
+	public Image getBuffer()
+	{
 		return _buffer;
 	}
 
-	public void setBuffer(Image newBuffer) {
+	public void setBuffer(Image newBuffer)
+	{
 		_buffer = newBuffer;
 	}
 
-	public boolean isBufferValid() {
-		if (_buffer == null
-				|| (_buffer instanceof VolatileImage && ((VolatileImage) _buffer)
-						.contentsLost()))
-			return false;
+	public boolean isBufferValid()
+	{
+		if (_buffer == null) return false;
 
 		return _validBuffer;
 	}
 
-	private void setBufferValid(boolean newValue) {
+	private void setBufferValid(boolean newValue)
+	{
 		_validBuffer = newValue;
 	}
 
-	public int getNextItemID() {
+	public int getNextItemID()
+	{
 		return ++_itemCount;
 	}
 
-	public void updateIDs(List<Item> items) {
-		for (Item i : items)
-			if (!(i instanceof Line))
+	public void updateIDs(List<Item> items)
+	{
+		for (Item i : items) {
+			if (!(i instanceof Line)) {
 				i.setID(getNextItemID());
-			else
+			} else {
 				i.setID(++_lineCount);
+			}
+		}
 	}
 
@@ -237,6 +238,7 @@
 	 *         Hence it excludes free-widgets. Returns a copy
 	 */
-	public List<InteractiveWidget> getInteractiveWidgets() {
-		LinkedList<InteractiveWidget> clone = new LinkedList<InteractiveWidget>();
+	public List<Widget> getInteractiveWidgets()
+	{
+		LinkedList<Widget> clone = new LinkedList<Widget>();
 		clone.addAll(this._iWidgets);
 		return clone;
@@ -248,8 +250,8 @@
 	 * @return True if this Frame has been altered, false otherwise.
 	 */
-	public boolean hasChanged() {
+	public boolean hasChanged()
+	{
 		// virtual frames are never saved
-		if (_number == -1)
-			return false;
+		if (_number == VIRTUAL_FRAME_NUMBER) return false;
 
 		return _change;
@@ -260,16 +262,9 @@
 	 * 
 	 * @param value
-	 *            False if this Frame should be saved to disk, False otherwise.
-	 */
-	public void setChanged(boolean value) {
-		// System.out.println(getName() + " " + value);
-		boolean oldValue = _change;
-
-		// if (value) {
-		// notifyObservers();
-		// }
-
-		if (oldValue == value)
-			return;
+	 *            True if this Frame should be saved to disk, False otherwise.
+	 */
+	public void setChanged(boolean value)
+	{
+		if (_change == value) return;
 
 		_change = value;
@@ -281,6 +276,4 @@
 	}
 
-	// private static int updateCount = 0;
-
 	/**
 	 * Notify items observing the data on this frame that the frame content has
@@ -290,8 +283,7 @@
 	 *            true if the frame should be recalculated first.
 	 */
-	public void notifyObservers(boolean bRecalculate) {
-		if (bRecalculate) {
-			recalculate();
-		}
+	public void notifyObservers(boolean bRecalculate)
+	{
+		if (bRecalculate) recalculate();
 		// Notify the frame listeners that the frame has changed
 		/*
@@ -301,16 +293,15 @@
 		 * changing this frames observer list.
 		 */
-		Collection<FrameObserver> observersCopy = new LinkedList<FrameObserver>(
-				_observers);
+		Collection<FrameObserver> observersCopy = new LinkedList<FrameObserver>(_observers);
 		// System.out.println(++updateCount + " update");
 
 		for (FrameObserver fl : observersCopy) {
-			if (/* !Item.isLocked(fl) && */fl.isVisible())
-				fl.update();
+			if (fl.isVisible()) fl.update();
 		}
 	}
 
 	// indicates the frame has changed
-	public void change() {
+	public void change()
+	{
 		setChanged(true);
 		_interactableItems.clear();
@@ -323,9 +314,14 @@
 	 * @return The list of Item objects that are on this Frame.
 	 */
-	public List<Item> getItems(boolean visible) {
+	public List<Item> getItems(boolean visible)
+	{
 		if (!_sorted) {
-			for(int i = 0; i < _body.size();)
-				if(_body.get(i) == null) _body.remove(i);
-				else i++;
+			for(int i = 0; i < _body.size();) {
+				if(_body.get(i) == null) {
+					_body.remove(i);
+				} else {
+					i++;
+				}
+			}
 			Collections.sort(_body);
 			_sorted = true;
@@ -335,6 +331,6 @@
 
 		for (Item i : _body) {
-			if (i == null)
-				continue;
+			if (i == null) continue;
+			
 			if (i.isVisible() || (!visible && !i.isDeleted())) {
 				items.add(i);
@@ -345,5 +341,7 @@
 	}
 
-	public List<Item> getItems() {
+	/** TODO: Comment. cts16 */
+	public List<Item> getItems()
+	{
 		return getItems(false);
 	}
@@ -354,7 +352,8 @@
 	 * @return True if this frame contains i.
 	 */
-	public boolean containsItem(Item i) {
-		if (i == null)
-			throw new NullPointerException("i");
+	public boolean containsItem(Item i)
+	{
+		if (i == null) throw new NullPointerException("i");
+		
 		return _body.contains(i);
 	}
@@ -372,15 +371,15 @@
 	 * @return the list of body text items.
 	 */
-	public List<Text> getBodyTextItems(boolean includeAnnotations) {
+	public List<Text> getBodyTextItems(boolean includeAnnotations)
+	{
 		List<Text> bodyTextItems = new ArrayList<Text>();
+		
 		for (Item i : getItems(true)) {
 			// only add up normal body text items
-			if ((i instanceof Text)
-					&& ((includeAnnotations && !((Text) i)
-							.isSpecialAnnotation()) || !i.isAnnotation())
-					&& !i.isLineEnd()) {
+			if ((i instanceof Text) && ((includeAnnotations && !((Text) i).isSpecialAnnotation()) || !i.isAnnotation()) && !i.isLineEnd()) {
 				bodyTextItems.add((Text) i);
 			}
 		}
+		
 		bodyTextItems.remove(getTitleItem());
 
@@ -388,15 +387,16 @@
 	}
 
-	public Collection<Item> getNonAnnotationItems(boolean removeTitle) {
+	public Collection<Item> getNonAnnotationItems(boolean removeTitle)
+	{
 		Collection<Item> items = new ArrayList<Item>();
 		for (Item i : getItems(true)) {
 			// only add up normal body text items
-			if (!i.isAnnotation()) {
-				items.add(i);
-			}
-		}
+			if (!i.isAnnotation()) items.add(i);
+		}
+		
 		if (removeTitle) {
 			items.remove(getTitleItem());
 		}
+		
 		return items;
 	}
@@ -408,5 +408,6 @@
 	 * @return the last non annotation text item.
 	 */
-	public Item getLastNonAnnotationTextItem() {
+	public Item getLastNonAnnotationTextItem()
+	{
 		List<Item> items = getItems();
 
@@ -431,9 +432,11 @@
 	 *         found.
 	 */
-	public Item getItemWithID(int id) {
-		for (Item i : _body)
-			if (i.getID() == id)
+	public Item getItemWithID(int id)
+	{
+		for (Item i : _body) {
+			if (i.getID() == id) {
 				return i;
-
+			}
+		}
 		return null;
 	}
@@ -445,7 +448,7 @@
 	 *            The title to assign to this Frame
 	 */
-	public void setTitle(String title) {
-		if (title == null || title.equals(""))
-			return;
+	public void setTitle(String title)
+	{
+		if (title == null || title.equals("")) return;
 
 		boolean oldchange = _change;
@@ -476,7 +479,6 @@
 			// title = ItemUtils.StripTagSymbol(title);
 			frameTitle.setText(title);
-			// If the @ symbol is followed by numbering or a bullet remove that
-			// too
-			String autoBulletText = FrameKeyboardActions.getAutoBullet(title);
+			// If the @ symbol is followed by numbering or a bullet remove that too
+			String autoBulletText = StandardGestureActions.getAutoBullet(title);
 			if (autoBulletText.length() > 0)
 				frameTitle.stripFirstWord();
@@ -485,6 +487,5 @@
 		// Brook: Cannot figure what is going on above... widget annot titles
 		// should be stripped always
-		if (ItemUtils.startsWithTag(frameTitle, ItemUtils
-				.GetTag(ItemUtils.TAG_IWIDGET))) {
+		if (ItemUtils.startsWithTag(frameTitle, ItemUtils.GetTag(ItemUtils.TAG_IWIDGET))) {
 			frameTitle.stripFirstWord();
 		}
@@ -496,10 +497,12 @@
 	}
 
-	public Text getTitleItem() {
+	public Text getTitleItem()
+	{
 		List<Item> items = getVisibleItems();
+		
 		for (Item i : items) {
-			if (i instanceof Text && i.getX() < UserSettings.TitlePosition.get()
-					&& i.getY() < UserSettings.TitlePosition.get())
+			if (i instanceof Text && i.getX() < UserSettings.TitlePosition.get() && i.getY() < UserSettings.TitlePosition.get()) {
 				return (Text) i;
+			}
 		}
 
@@ -507,24 +510,25 @@
 	}
 
-	public String getTitle() {
+	public String getTitle()
+	{
 		Text title = getTitleItem();
-		if (title == null)
-			return getName();
+		if (title == null) return getName();
 
 		return title.getFirstLine();
 	}
 
-	public Item getNameItem() {
+	public Item getNameItem()
+	{
 		return _frameName;
 	}
 
-	public Text getItemTemplate() {
-		return getTemplate(TemplateSettings.ItemTemplate.get(),
-				ItemUtils.TAG_ITEM_TEMPLATE);
-	}
-
-	public Text getAnnotationTemplate() {
-		Text t = getTemplate(TemplateSettings.AnnotationTemplate.get(),
-				ItemUtils.TAG_ANNOTATION_TEMPLATE);
+	public Text getItemTemplate()
+	{
+		return getTemplate(TemplateSettings.ItemTemplate.get(), ItemUtils.TAG_ITEM_TEMPLATE);
+	}
+
+	public Text getAnnotationTemplate()
+	{
+		Text t = getTemplate(TemplateSettings.AnnotationTemplate.get(), ItemUtils.TAG_ANNOTATION_TEMPLATE);
 
 		if (t == null) {
@@ -535,8 +539,8 @@
 	}
 
-	public Text getStatTemplate() {
+	public Text getStatTemplate()
+	{
 		SessionStats.CreatedText();
-		Text t = getTemplate(TemplateSettings.StatTemplate.get(),
-				ItemUtils.TAG_STAT_TEMPLATE);
+		Text t = getTemplate(TemplateSettings.StatTemplate.get(), ItemUtils.TAG_STAT_TEMPLATE);
 
 		if (t == null) {
@@ -547,21 +551,25 @@
 	}
 	
-	public Item getTooltipTextItem(String tooltipText) {
+	public Item getTooltipTextItem(String tooltipText)
+	{
 		return getTextItem(tooltipText, TemplateSettings.TooltipTemplate.get().copy());
 	}
 
-	public Item getStatsTextItem(String itemText) {
+	public Item getStatsTextItem(String itemText)
+	{
 		return getTextItem(itemText, getStatTemplate());
 	}
 
-	public Item getTextItem(String itemText) {
+	public Item getTextItem(String itemText)
+	{
 		return getTextItem(itemText, getItemTemplate());
 	}
 
-	private Item getTextItem(String itemText, Text template) {
+	private Item getTextItem(String itemText, Text template)
+	{
 		Text t = template;
 		// We dont want the stats to wrap at all
 		// t.setMaxWidth(Integer.MAX_VALUE);
-		t.setPosition(DisplayIO.getMouseX(), FrameMouseActions.getY());
+		t.setPosition(DisplayController.getMousePosition());
 		// The next line is needed to make sure the item is removed from the
 		// frame when picked up
@@ -571,7 +579,7 @@
 	}
 
-	public Text getCodeCommentTemplate() {
-		Text t = getTemplate(TemplateSettings.CommentTemplate.get(), 
-				ItemUtils.TAG_CODE_COMMENT_TEMPLATE);
+	public Text getCodeCommentTemplate()
+	{
+		Text t = getTemplate(TemplateSettings.CommentTemplate.get(), ItemUtils.TAG_CODE_COMMENT_TEMPLATE);
 
 		if (t == null) {
@@ -592,5 +600,6 @@
 	 *         Item.intersects(shape) return true.
 	 */
-	public Collection<Item> getItemsWithin(Polygon poly) {
+	public Collection<Item> getItemsWithin(PolygonBounds poly)
+	{
 		Collection<Item> results = new LinkedHashSet<Item>();
 		for (Item i : getVisibleItems()) {
@@ -606,7 +615,8 @@
 		}
 
-		for (Overlay o : _overlays.keySet())
+		for (Overlay o : _overlays.keySet()) {
 			results.addAll(o.Frame.getItemsWithin(poly));
-
+		}
+		
 		for (Item i : getVectorItems()) {
 			if (i.intersects(poly)) {
@@ -626,9 +636,11 @@
 	 *            The name to use for this Frame.
 	 */
-	public void setFrameset(String name) {
+	public void setFrameset(String name)
+	{
 		_frameset = name;
 	}
 
-	public void setName(String framename) {
+	public void setName(String framename)
+	{
 		int num = Conversion.getFrameNumber(framename);
 		String frameset = Conversion.getFramesetName(framename, false);
@@ -643,9 +655,9 @@
 	 *            The number to set as the frame number
 	 */
-	public void setFrameNumber(int number) {
+	public void setFrameNumber(int number)
+	{
 		assert (number >= 0);
 
-		if (_number == number)
-			return;
+		if (_number == number) return;
 
 		_number = number;
@@ -659,4 +671,5 @@
 			id = -1 * getNextItemID();
 		}
+		
 		_frameName = new Text(id);
 		_frameName.setParent(this);
@@ -671,5 +684,6 @@
 	 * @return The Frame number of this Frame or -1 if it is not set.
 	 */
-	public int getNumber() {
+	public int getNumber()
+	{
 		return _number;
 	}
@@ -681,5 +695,6 @@
 	 *            The version to use for this Frame.
 	 */
-	public void setVersion(int version) {
+	public void setVersion(int version)
+	{
 		_version = version;
 	}
@@ -691,12 +706,13 @@
 	 *            The protection to use for this Frame.
 	 */
-	public void setPermission(PermissionPair permission) {
-		if (_permissionPair != null && _permissionPair.getPermission(this._owner).equals(permission))
+	public void setPermission(PermissionPair permission)
+	{
+		if (_permissionPair != null && _permissionPair.getPermission(this._owner).equals(permission)) {
 			_protectionChanged = true;
+		}
 
 		_permissionPair = new PermissionPair(permission);
 
-		if (_body.size() > 0)
-			refreshItemPermissions(permission.getPermission(_owner));
+		if (_body.size() > 0) refreshItemPermissions(permission.getPermission(_owner));
 	}
 
@@ -707,5 +723,6 @@
 	 *            The owner to use for this Frame.
 	 */
-	public void setOwner(String owner) {
+	public void setOwner(String owner)
+	{
 		_owner = owner;
 	}
@@ -717,5 +734,6 @@
 	 *            The date to use for this Frame.
 	 */
-	public void setDateCreated(String date) {
+	public void setDateCreated(String date)
+	{
 		_creationDate = date;
 		_modifiedDate = date;
@@ -729,5 +747,6 @@
 	 * 
 	 */
-	public void resetDateCreated() {
+	public void resetDateCreated()
+	{
 		setDateCreated(Formatter.getDateTime());
 		resetTimes();
@@ -735,5 +754,6 @@
 	}
 
-	private void resetTimes() {
+	private void resetTimes()
+	{
 		setActiveTime(new Time(0));
 		setDarkTime(new Time(0));
@@ -746,5 +766,6 @@
 	 *            The user to set as the last modifying user.
 	 */
-	public void setLastModifyUser(String user) {
+	public void setLastModifyUser(String user)
+	{
 		_modifiedUser = user;
 	}
@@ -756,5 +777,6 @@
 	 *            The date to set as the last modified date.
 	 */
-	public void setLastModifyDate(String date) {
+	public void setLastModifyDate(String date)
+	{
 		_modifiedDate = date;
 	}
@@ -766,9 +788,11 @@
 	 *            The date to set as the last frozen date.
 	 */
-	public void setFrozenDate(String date) {
+	public void setFrozenDate(String date)
+	{
 		_frozenDate = date;
 	}
 
-	public void setResort(boolean value) {
+	public void setResort(boolean value)
+	{
 		_sorted = !value;
 	}
@@ -780,11 +804,12 @@
 	 *            The Item to add to this Frame.
 	 */
-	public void addItem(Item item) {
+	public void addItem(Item item)
+	{
 		addItem(item, true);
 	}
 
-	public void addItem(Item item, boolean recalculate) {
-		if (item == null || item.equals(_frameName) || _body.contains(item))
-			return;
+	public void addItem(Item item, boolean recalculate)
+	{
+		if (item == null || item.equals(_frameName) || _body.contains(item)) return;
 
 		// When an annotation item is anchored the annotation list must be
@@ -794,6 +819,5 @@
 		}
 
-		if (item instanceof Line)
-			_lineCount++;
+		if (item instanceof Line) _lineCount++;
 
 		_itemCount = Math.max(_itemCount, item.getID());
@@ -816,15 +840,15 @@
 		// add widget items to the list of widgets
 		if (item instanceof WidgetCorner) {
-			InteractiveWidget iw = ((WidgetCorner) item).getWidgetSource();
+			Widget iw = ((WidgetCorner) item).getWidgetSource();
 			if (!this._iWidgets.contains(iw)) { // A set would have been
-				if (FrameMouseActions.isControlDown())
+				if (StandardInputEventListeners.kbmStateListener.isKeyDown(Key.CTRL)) {
 					_iWidgets.add(iw);
-				else
+				} else {
 					_iWidgets.add(0, iw);
-			}
-		}
-
-		item.onParentStateChanged(new ItemParentStateChangedEvent(this,
-				ItemParentStateChangedEvent.EVENT_TYPE_ADDED));
+				}
+			}
+		}
+
+		item.onParentStateChanged(new ItemParentStateChangedEvent(this, ItemParentStateChangedEvent.EVENT_TYPE_ADDED));
 
 		// if (recalculate && item.recalculateWhenChanged())
@@ -834,12 +858,13 @@
 	}
 
-	public void refreshSize() {
-		// assert (size != null);
+	public void refreshSize()
+	{
 		boolean bReparse = false;
+		
 		for (Item i : getItems()) {
-			Float anchorLeft   = i.getAnchorLeft();
-			Float anchorRight  = i.getAnchorRight();
-			Float anchorTop    = i.getAnchorTop();
-			Float anchorBottom = i.getAnchorBottom();
+			Integer anchorLeft   = i.getAnchorLeft();
+			Integer anchorRight  = i.getAnchorRight();
+			Integer anchorTop    = i.getAnchorTop();
+			Integer anchorBottom = i.getAnchorBottom();
 	
 			
@@ -885,9 +910,9 @@
 	}
 
-	public void addAllItems(Collection<Item> toAdd) {
+	public void addAllItems(Collection<Item> toAdd)
+	{
 		for (Item i : toAdd) {
 			// If an annotation is being deleted clear the annotation list
-			if (i.isAnnotation())
-				i.getParentOrCurrentFrame().clearAnnotations();
+			if (i.isAnnotation()) i.getParentOrCurrentFrame().clearAnnotations();
 			// TODO Improve efficiency when addAll is called
 			addItem(i);
@@ -895,21 +920,22 @@
 	}
 
-	public void removeAllItems(Collection<Item> toRemove) {
+	public void removeAllItems(Collection<Item> toRemove)
+	{
 		for (Item i : toRemove) {
 			// If an annotation is being deleted clear the annotation list
-			if (i.isAnnotation())
-				i.getParentOrCurrentFrame().clearAnnotations();
+			if (i.isAnnotation()) i.getParentOrCurrentFrame().clearAnnotations();
 			removeItem(i);
 		}
 	}
 
-	public void removeItem(Item item) {
+	public void removeItem(Item item)
+	{
 		removeItem(item, true);
 	}
 
-	public void removeItem(Item item, boolean recalculate) {
+	public void removeItem(Item item, boolean recalculate)
+	{
 		// If an annotation is being deleted clear the annotation list
-		if (item.isAnnotation())
-			item.getParentOrCurrentFrame().clearAnnotations();
+		if (item.isAnnotation()) item.getParentOrCurrentFrame().clearAnnotations();
 
 		if (_body.remove(item)) {
@@ -917,9 +943,10 @@
 			// Remove widgets from the widget list
 			if (item != null) {
-				item.onParentStateChanged(new ItemParentStateChangedEvent(this,
-						ItemParentStateChangedEvent.EVENT_TYPE_REMOVED));
+				item.onParentStateChanged(new ItemParentStateChangedEvent(this, ItemParentStateChangedEvent.EVENT_TYPE_REMOVED));
+				
 				if (item instanceof WidgetCorner) {
 					_iWidgets.remove(((WidgetCorner) item).getWidgetSource());
 				}
+				
 				item.invalidateCommonTrait(ItemAppearence.Removed);
 			}
@@ -937,26 +964,27 @@
 	 * @param type  The type of event that occurred
 	 */
-	private void addToUndo(Collection<Item> items, History.Type type) {
-		if (items.size() < 1)
-			return;
-		
-		// System.out.println("Added: " + items);
+	private void addToUndo(Collection<Item> items, History.Type type)
+	{
+		if (items.size() < 1) return;
 
 		_undo.push(new History(items, type));
 	}
 	
-	public void addToUndoDelete(Collection<Item> items) {
+	public void addToUndoDelete(Collection<Item> items)
+	{
 		addToUndo(items, History.Type.deletion);
 	}
-	public void addToUndoMove(Collection<Item> items) {
+	
+	public void addToUndoMove(Collection<Item> items)
+	{
 		addToUndo(items, History.Type.movement);
 	}
 
-	public void undo() {
+	public void undo()
+	{
 		boolean bReparse = false;
 		boolean bRecalculate = false;
 
-		if (_undo.size() <= 0)
-			return;
+		if (_undo.size() <= 0) return;
 
 		History undo = _undo.pop();
@@ -992,6 +1020,9 @@
 			break;
 		}
+		
 		change();
-		FrameMouseActions.getInstance().refreshHighlights();
+		
+		StandardGestureActions.refreshHighlights();
+		
 		if (bReparse) {
 			FrameUtils.Parse(this, false, false);
@@ -999,19 +1030,19 @@
 			notifyObservers(bRecalculate);
 		}
+		
 		// always request a refresh otherwise filled shapes
 		// that were broken by a deletion and then reconnected by the undo
 		// don't get filled until the user otherwise causes them to redraw
-		FrameGraphics.requestRefresh(false);
-		FrameGraphics.Repaint();
+		DisplayController.requestRefresh(false);
 		// ItemUtils.EnclosedCheck(_body);
 		ItemUtils.Justify(this);
 	}
 	
-	public void redo() {
+	public void redo()
+	{
 		boolean bReparse = false;
 		boolean bRecalculate = false;
 
-		if (_redo.size() <= 0)
-			return;
+		if (_redo.size() <= 0) return;
 
 		History redo = _redo.pop();
@@ -1047,6 +1078,9 @@
 			break;
 		}
+		
 		change();
-		FrameMouseActions.getInstance().refreshHighlights();
+		
+		StandardGestureActions.refreshHighlights();
+		
 		if (bReparse) {
 			FrameUtils.Parse(this, false, false);
@@ -1054,9 +1088,9 @@
 			notifyObservers(bRecalculate);
 		}
+		
 		// always request a refresh otherwise filled shapes
 		// that were broken by a deletion and then reconnected by the undo
 		// don't get filled until the user otherwise causes them to redraw
-		FrameGraphics.requestRefresh(false);
-		FrameGraphics.Repaint();
+		DisplayController.requestRefresh(false);
 		// ItemUtils.EnclosedCheck(_body);
 		ItemUtils.Justify(this);
@@ -1068,9 +1102,11 @@
 	 * @return The name of this Frame's frameset.
 	 */
-	public String getFramesetName() {
+	public String getFramesetName()
+	{
 		return _frameset;
 	}
 
-	public String getName() {
+	public String getName()
+	{
 		return getFramesetName() + _number;
 	}
@@ -1081,58 +1117,69 @@
 	 * @return The version of this Frame.
 	 */
-	public int getVersion() {
+	public int getVersion()
+	{
 		return _version;
 	}
 
-	public PermissionPair getPermission() {
+	public PermissionPair getPermission()
+	{
 		return _permissionPair;
 	}
 	
-	public UserAppliedPermission getUserAppliedPermission() {
+	public UserAppliedPermission getUserAppliedPermission()
+	{
 		return getUserAppliedPermission(UserAppliedPermission.full);
 	}
 
-	public UserAppliedPermission getUserAppliedPermission(UserAppliedPermission defaultPermission) {
-		if (_permissionPair == null)
-			return defaultPermission;
+	public UserAppliedPermission getUserAppliedPermission(UserAppliedPermission defaultPermission)
+	{
+		if (_permissionPair == null) return defaultPermission;
 
 		return _permissionPair.getPermission(_owner);
 	}
 
-	
-	public String getOwner() {
+	public String getOwner()
+	{
 		return _owner;
 	}
 
-	public String getDateCreated() {
+	public String getDateCreated()
+	{
 		return _creationDate;
 	}
 
-	public String getLastModifyUser() {
+	public String getLastModifyUser()
+	{
 		return _modifiedUser;
 	}
 
-	public String getLastModifyDate() {
+	public String getLastModifyDate()
+	{
 		return _modifiedDate;
 	}
 
-	public String getFrozenDate() {
+	public String getFrozenDate()
+	{
 		return _frozenDate;
 	}
 
-	public void setBackgroundColor(Color back) {
+	public void setBackgroundColor(Colour back)
+	{
 		_background = back;
+		
 		change();
 
-		if (this == DisplayIO.getCurrentFrame()) {
-			FrameGraphics.refresh(false);
-		}
-	}
-
-	public Color getBackgroundColor() {
+		if (this == DisplayController.getCurrentFrame()) {
+			DisplayController.requestRefresh(false);
+		}
+	}
+
+	public Colour getBackgroundColor()
+	{
 		return _background;
 	}
 
-	public Color getPaintBackgroundColor() {
+	public Colour getPaintBackgroundColor()
+	{
 		// If null... return white
 		if (_background == null) {
@@ -1143,29 +1190,32 @@
 	}
 
-	public void setForegroundColor(Color front) {
+	public void setForegroundColor(Colour front)
+	{
 		_foreground = front;
+		
 		change();
-		// FrameGraphics.Repaint();
-	}
-
-	public Color getForegroundColor() {
+	}
+
+	public Colour getForegroundColor()
+	{
 		return _foreground;
 	}
 
-	public Color getPaintForegroundColor() {
-		final int GRAY = Color.gray.getBlue();
-		final int THRESHOLD = 10;
+	public Colour getPaintForegroundColor()
+	{
+		final int GRAY = Colour.GREY.getBlue();
+		final int THRESHOLD = Colour.FromComponent255(10);
 
 		if (_foreground == null) {
-			Color back = getPaintBackgroundColor();
+			Colour back = getPaintBackgroundColor();
 			if (Math.abs(back.getRed() - GRAY) < THRESHOLD
 					&& Math.abs(back.getBlue() - GRAY) < THRESHOLD
 					&& Math.abs(back.getGreen() - GRAY) < THRESHOLD)
-				return Color.WHITE;
-
-			Color fore = new Color(
-					Math.abs(Conversion.RGB_MAX - back.getRed()), Math
-							.abs(Conversion.RGB_MAX - back.getGreen()), Math
-							.abs(Conversion.RGB_MAX - back.getBlue()));
+			{
+				return Colour.WHITE;
+			}
+			
+			Colour fore = back.inverse();
+			
 			return fore;
 		}
@@ -1174,5 +1224,6 @@
 	}
 
-	public String toString() {
+	public String toString()
+	{
 		StringBuilder s = new StringBuilder();
 		s.append(String.format("Name: %s%d%n", _frameset, _number));
@@ -1187,7 +1238,9 @@
 	}
 
-	public Text getTextAbove(Text current) {
+	public Text getTextAbove(Text current)
+	{
 		Collection<Text> currentTextItems = FrameUtils.getCurrentTextItems();
 		List<Text> toCheck = new ArrayList<Text>();
+		
 		if (currentTextItems.contains(current)) {
 			toCheck.addAll(currentTextItems);
@@ -1195,35 +1248,20 @@
 			toCheck.addAll(getTextItems());
 		}
+		
 		// Make sure the items are sorted
 		Collections.sort(toCheck);
 
 		int ind = toCheck.indexOf(current);
-		if (ind == -1)
-			return null;
+		if (ind == -1) return null;
 
 		// loop through all items above this one, return the first match
 		for (int i = ind - 1; i >= 0; i--) {
 			Text check = toCheck.get(i);
-			if (FrameUtils.inSameColumn(check, current))
-				return check;
+			if (FrameUtils.inSameColumn(check, current)) return check;
 		}
 
 		return null;
 	}
-
-	/**
-	 * Updates any Images that require it from their ImageObserver (Principally
-	 * Animated GIFs)
-	 */
-	public boolean imageUpdate(Image img, int infoflags, int x, int y,
-			int width, int height) {
-		FrameGraphics.ForceRepaint();
-
-		if (DisplayIO.getCurrentFrame() == this)
-			return true;
-
-		return false;
-	}
-
+	
 	/**
 	 * Gets the text items that are in the same column and below a specified
@@ -1233,8 +1271,8 @@
 	 *            The Item to get the column for.
 	 */
-	public List<Text> getColumn(Item from) {
+	public List<Text> getColumn(Item from)
+	{
 		// Check that this item is on the current frame
-		if (!_body.contains(from))
-			return null;
+		if (!_body.contains(from)) return null;
 
 		if (from == null) {
@@ -1242,10 +1280,10 @@
 		}
 
-		if (from == null)
-			return null;
+		if (from == null) return null;
 
 		// Get the enclosedItems
 		Collection<Text> enclosed = FrameUtils.getCurrentTextItems();
 		List<Text> toCheck = null;
+		
 		if (enclosed.contains(from)) {
 			toCheck = new ArrayList<Text>();
@@ -1256,6 +1294,6 @@
 
 		List<Text> column = new ArrayList<Text>();
+		
 		if (toCheck.size() > 0) {
-
 			// Make sure the items are sorted
 			Collections.sort(toCheck);
@@ -1266,11 +1304,9 @@
 
 			// If its the title index will be 0
-			if (index < 0)
-				index = 0;
+			if (index < 0) index = 0;
 
 			for (int i = index; i < toCheck.size(); i++) {
 				Text item = toCheck.get(i);
-				if (FrameUtils.inSameColumn(from, item))
-					column.add(item);
+				if (FrameUtils.inSameColumn(from, item)) column.add(item);
 			}
 		}
@@ -1289,39 +1325,44 @@
 	 *             If overlay is null.
 	 */
-	protected boolean addVector(Vector toAdd) {
+	protected boolean addVector(Vector toAdd)
+	{
 		// make sure we dont add this frame as an overlay of itself
-		if (toAdd.Frame == this)
-			return false;
+		if (toAdd.Frame == this) return false;
+		
 		_vectors.add(toAdd);
+		
 		// Items must be notified that they have been added or removed from this
 		// frame via the vector...
 		int maxX = 0;
 		int maxY = 0;
+		
 		HighlightMode mode = toAdd.Source.getHighlightMode();
-		if (mode != HighlightMode.None)
-			mode = HighlightMode.Connected;
-		Color highlightColor = toAdd.Source.getHighlightColor();
+		if (mode != HighlightMode.None) mode = HighlightMode.Connected;
+		
+		Colour highlightColor = toAdd.Source.getHighlightColor();
+		
 		for (Item i : ItemUtils.CopyItems(toAdd.Frame.getVectorItems(), toAdd)) {
-			i.onParentStateChanged(new ItemParentStateChangedEvent(this,
-					ItemParentStateChangedEvent.EVENT_TYPE_ADDED_VIA_OVERLAY,
-					toAdd.permission));
+			i.onParentStateChanged(new ItemParentStateChangedEvent(this, ItemParentStateChangedEvent.EVENT_TYPE_ADDED_VIA_OVERLAY, toAdd.permission));
 			i.setEditTarget(toAdd.Source);
-			i.setHighlightMode(mode, highlightColor);
+			i.setHighlightModeAndColour(mode, highlightColor);
 			_vectorItems.add(i);
 			i.invalidateAll();
 			i.invalidateFill();
+			
 			// Get the right most x and bottom most y pos
 			int itemRight = i.getX() + i.getBoundsWidth();
-			if (itemRight > maxX)
-				maxX = itemRight;
+			if (itemRight > maxX) maxX = itemRight;
+			
 			int itemBottom = i.getY() + i.getBoundsHeight();
-			if (itemBottom > maxY)
-				maxY = itemBottom;
-		}
+			if (itemBottom > maxY) maxY = itemBottom;
+		}
+		
 		toAdd.setSize(maxX, maxY);
+		
 		return true;
 	}
 
-	public Collection<Vector> getVectors() {
+	public Collection<Vector> getVectors()
+	{
 		Collection<Vector> l = new LinkedList<Vector>();
 		l.addAll(_vectors);
@@ -1329,12 +1370,14 @@
 	}
 
-	public Collection<Overlay> getOverlays() {
+	public Collection<Overlay> getOverlays()
+	{
 		return new LinkedList<Overlay>(_overlays.keySet());
 	}
 
 	/**
-	 * @return All vectosr seen by this frame (including its vector's vectors).
-	 */
-	public List<Vector> getVectorsDeep() {
+	 * @return All vectors seen by this frame (including its vector's vectors).
+	 */
+	public List<Vector> getVectorsDeep()
+	{
 		List<Vector> l = new LinkedList<Vector>();
 		getVectorsDeep(l, this, new LinkedList<Frame>());
@@ -1342,15 +1385,13 @@
 	}
 
-	private boolean getVectorsDeep(List<Vector> vectors, Frame vector,
-			List<Frame> seenVectors) {
-
-		if (seenVectors.contains(vector))
-			return false;
+	private boolean getVectorsDeep(List<Vector> vectors, Frame vector, List<Frame> seenVectors)
+	{
+		if (seenVectors.contains(vector)) return false;
 
 		seenVectors.add(vector);
 
-		for (Vector o : vector.getVectors()) {
-			if (getVectorsDeep(vectors, o.Frame, seenVectors)) {
-				vectors.add(o);
+		for (Vector v : vector.getVectors()) {
+			if (getVectorsDeep(vectors, v.Frame, seenVectors)) {
+				vectors.add(v);
 			}
 		}
@@ -1359,20 +1400,46 @@
 	}
 
-	// private boolean getOverlaysDeep(List<Overlay> overlays, Frame overlay,
-	// List<Frame> seenOverlays) {
-	//
-	// if (seenOverlays.contains(overlay))
-	// return false;
-	//
-	// seenOverlays.add(overlay);
-	//
-	// for (Overlay o : overlay.getOverlays()) {
-	// if (getOverlaysDeep(overlays, o.Frame, seenOverlays)) {
-	// overlays.add(o);
-	// }
-	// }
-	//
-	// return true;
-	// }
+	public List<Overlay> getOverlaysDeep()
+	{
+		List<Overlay> ret = new LinkedList<Overlay>();
+		
+		getOverlaysDeep(ret, new LinkedList<Frame>());
+		
+		return ret;
+	}
+	
+	private boolean getOverlaysDeep(List<Overlay> overlays, List<Frame> seenOverlays)
+	{
+		if (seenOverlays.contains(this)) return false;
+		
+		seenOverlays.add(this);
+		
+		for (Overlay o : this.getOverlays()) {
+			if (o.Frame.getOverlaysDeep(overlays, seenOverlays)) {
+				overlays.add(o);
+			}
+		}
+		return true;
+	}
+	
+	/**
+	 * Recursive function similar to AddAllOverlayItems.
+	 * 
+	 * @param widgets
+	 *            The collection the widgets will be added to
+	 * @param overlay
+	 *            An "overlay" frame - this initially will be the parent frame
+	 * @param seenOverlays
+	 *            Used for state in the recursion stack. Pass as an empty
+	 *            (non-null) list.
+	 */
+	public List<Widget> getAllOverlayWidgets()
+	{
+		List<Widget> widgets = new LinkedList<Widget>();
+		
+		for (Overlay o : getOverlaysDeep()) widgets.addAll(o.Frame.getInteractiveWidgets());
+		
+		return widgets;
+	}
 
 	/**
@@ -1381,21 +1448,19 @@
 	 * @param item
 	 *            The item - must not be null.
-	 * @return The overlay that contains the itm. Null if no overlay owns the
+	 * @return The overlay that contains the item. Null if no overlay owns the
 	 *         item.
 	 */
-	public Overlay getOverlayOwner(Item item) {
-		if (item == null)
-			throw new NullPointerException("item");
+	public Overlay getOverlayOwner(Item item)
+	{
+		if (item == null) throw new NullPointerException("item");
 
 		for (Overlay l : getOverlays()) {
-			if (item.getParent() == l.Frame)
-				return l;
+			if (item.getParent() == l.Frame) return l;
 		}
 
 		// TODO return the correct vector... not just the first vector matching
-		// the vectorFrame
+		// the vector frame
 		for (Vector v : getVectors()) {
-			if (item.getParent() == v.Frame)
-				return v;
+			if (item.getParent() == v.Frame) return v;
 		}
 
@@ -1403,5 +1468,6 @@
 	}
 
-	public void clearVectors() {
+	public void clearVectors()
+	{
 		_vectors.clear();
 
@@ -1414,7 +1480,8 @@
 	}
 
-	protected boolean removeVector(Vector toRemove) {
-		if (!_vectors.remove(toRemove))
-			return false;
+	protected boolean removeVector(Vector toRemove)
+	{
+		if (!_vectors.remove(toRemove)) return false;
+		
 		for (Item i : toRemove.Frame.getVectorItems()) {
 			i.invalidateAll();
@@ -1426,12 +1493,13 @@
 
 		}
+		
 		return true;
 	}
 
-	public void clearOverlays() {
+	public void clearOverlays()
+	{
 		for (Overlay o : _overlays.keySet()) {
 			for (Item i : o.Frame.getItems()) {
-				i
-						.onParentStateChanged(new ItemParentStateChangedEvent(
+				i.onParentStateChanged(new ItemParentStateChangedEvent(
 								this,
 								ItemParentStateChangedEvent.EVENT_TYPE_REMOVED_VIA_OVERLAY,
@@ -1444,23 +1512,27 @@
 	}
 
-	protected boolean removeOverlay(Frame f) {
+	protected boolean removeOverlay(Frame f)
+	{
 		for (Overlay o : _overlays.keySet()) {
 			if (o.Frame == f) {
 				_overlays.remove(o);
+				
 				for (Item i : f.getItems()) {
 					_overlayItems.remove(i);
-					i
-							.onParentStateChanged(new ItemParentStateChangedEvent(
+					i.onParentStateChanged(new ItemParentStateChangedEvent(
 									this,
 									ItemParentStateChangedEvent.EVENT_TYPE_REMOVED_VIA_OVERLAY,
 									o.permission));
 				}
+				
 				return true;
 			}
 		}
+		
 		return false;
 	}
 
-	public void addAllVectors(List<Vector> vectors) {
+	public void addAllVectors(List<Vector> vectors)
+	{
 		for (Vector v : vectors) {
 			addVector(v);
@@ -1468,5 +1540,6 @@
 	}
 
-	public void addAllOverlays(Collection<Overlay> overlays) {
+	public void addAllOverlays(Collection<Overlay> overlays)
+	{
 		for (Overlay o : overlays) {
 			addOverlay(o);
@@ -1474,31 +1547,29 @@
 	}
 
-	protected boolean addOverlay(Overlay toAdd) {
+	protected boolean addOverlay(Overlay toAdd)
+	{
 		// make sure we dont add this frame as an overlay of itself
-		if (toAdd.Frame == this)
-			return false;
+		if (toAdd.Frame == this) return false;
+		
 		// Dont add the overlay if there is already one for this frame
-		if (_overlays.values().contains(toAdd.Frame))
-			return false;
+		if (_overlays.values().contains(toAdd.Frame)) return false;
+		
 		// Add the overlay to the map of overlays on this frame
 		_overlays.put(toAdd, toAdd.Frame);
+		
 		// Add all the overlays from the overlay frame to this frame
-		for (Overlay o : toAdd.Frame.getOverlays())
-			addOverlay(o);
+		// TODO: Can this cause a recursion loop? If A and B are overlays of each other? cts16
+		for (Overlay o : toAdd.Frame.getOverlays()) addOverlay(o);
 
 		// Add all the vectors from the overlay frame to this frame
-		for (Vector v : toAdd.Frame.getVectors())
-			addVector(v);
+		for (Vector v : toAdd.Frame.getVectors()) addVector(v);
 
 		// Now add the items for this overlay
-		UserAppliedPermission permission = UserAppliedPermission.min(toAdd.Frame.getUserAppliedPermission(),toAdd.permission);
+		UserAppliedPermission permission = UserAppliedPermission.min(toAdd.Frame.getUserAppliedPermission(), toAdd.permission);
 
 		// Items must be notified that they have been added or removed from this
 		// frame via the overlay...
 		for (Item i : toAdd.Frame.getVisibleItems()) {
-			i.onParentStateChanged(new ItemParentStateChangedEvent(this,
-					ItemParentStateChangedEvent.EVENT_TYPE_ADDED_VIA_OVERLAY,
-					permission));
-			// i.setPermission(permission);
+			i.onParentStateChanged(new ItemParentStateChangedEvent(this, ItemParentStateChangedEvent.EVENT_TYPE_ADDED_VIA_OVERLAY, permission));
 			_overlayItems.add(i);
 		}
@@ -1508,8 +1579,8 @@
 
 	@Override
-	public boolean equals(Object o) {
+	public boolean equals(Object o)
+	{
 		if (o instanceof String) {
-			return (String.CASE_INSENSITIVE_ORDER
-					.compare((String) o, getName()) == 0);
+			return (String.CASE_INSENSITIVE_ORDER.compare((String) o, getName()) == 0);
 		}
 
@@ -1526,7 +1597,7 @@
 	 * @param toMergeWith
 	 */
-	private void merge(Frame toMergeWith) {
-		if (toMergeWith == null)
-			return;
+	private void merge(Frame toMergeWith)
+	{
+		if (toMergeWith == null) return;
 
 		List<Item> copies = ItemUtils.CopyItems(toMergeWith.getItems());
@@ -1548,16 +1619,16 @@
 	 * @return the items that cant be merged
 	 */
-	public List<Item> merge(List<Item> toMerge) {
+	public List<Item> merge(List<Item> toMerge)
+	{
 		ArrayList<Item> remain = new ArrayList<Item>(0);
 
 		for (Item i : toMerge) {
-			if (!(i instanceof Text))
+			if (!(i instanceof Text)) {
 				remain.add(i);
-			else {
+			} else {
 				if (!AttributeUtils.setAttribute(this, (Text) i)) {
-					if (i.getLink() != null)
+					if (i.getLink() != null) {
 						merge(FrameIO.LoadFrame(i.getAbsoluteLink()));
-					else if (FrameIO
-							.isValidFrameName(((Text) i).getFirstLine())) {
+					} else if (FrameIO.isValidFrameName(((Text) i).getFirstLine())) {
 						// If we get hear we are merging frames
 						merge(FrameIO.LoadFrame(((Text) i).getFirstLine()));
@@ -1574,17 +1645,21 @@
 	 * items are added to the backup-stack.
 	 */
-	public void clear(boolean keepAnnotations) {
+	public void clear(boolean keepAnnotations)
+	{
 		List<Item> newBody = new ArrayList<Item>(0);
+		
 		Item title = getTitleItem();
+		
 		if (title != null) {
 			newBody.add(title);
 			_body.remove(title);
 		}
+		
 		if (keepAnnotations) {
 			for (Item i : _body) {
-				if (i.isAnnotation())
-					newBody.add(i);
-			}
-		}
+				if (i.isAnnotation()) newBody.add(i);
+			}
+		}
+		
 		_body.removeAll(newBody);
 		addToUndoDelete(_body);
@@ -1592,6 +1667,5 @@
 		change();
 
-		if (!keepAnnotations && _annotations != null)
-			_annotations.clear();
+		if (!keepAnnotations && _annotations != null) _annotations.clear();
 	}
 
@@ -1602,5 +1676,6 @@
 	 * @return
 	 */
-	public Text createNewText(String text) {
+	public Text createNewText(String text)
+	{
 		Text t = createBlankText(text);
 		t.setText(text);
@@ -1615,15 +1690,18 @@
 	 * @return The newly created Text Item
 	 */
-	public Text createBlankText(String templateType) {
+	public Text createBlankText(String templateType)
+	{
 		SessionStats.CreatedText();
 		Text t;
-		if (templateType.length() == 0)
+		
+		if (templateType.length() == 0) {
 			t = getItemTemplate().copy();
-		else
+		} else {
 			t = getItemTemplate(templateType.charAt(0));
-
+		}
+		
 		// reset attributes
 		t.setID(getNextItemID());
-		t.setPosition(DisplayIO.getMouseX(), FrameMouseActions.getY());
+		t.setPosition(DisplayController.getMousePosition());
 		t.setText("");
 		t.setParent(this);
@@ -1648,14 +1726,12 @@
 	}
 
-	public Item createDot() {
-		Item dot = new Dot(DisplayIO.getMouseX(), FrameMouseActions.getY(),
-				getNextItemID());
+	public Item createDot()
+	{
+		Item dot = new Dot(DisplayController.getMouseX(), DisplayController.getMouseY(), getNextItemID());
 
 		Item template = getTemplate(_dotTemplate, ItemUtils.TAG_DOT_TEMPLATE);
 		float thickness = template.getThickness();
-		if (thickness > 0)
-			dot.setThickness(template.getThickness());
-		if (template.getLinePattern() != null)
-			dot.setLinePattern(template.getLinePattern());
+		if (thickness > 0) dot.setThickness(template.getThickness());
+		if (template.getLinePattern() != null) dot.setLinePattern(template.getLinePattern());
 		dot.setColor(template.getColor());
 		dot.setFillColor(template.getFillColor());
@@ -1665,5 +1741,6 @@
 	}
 
-	private Text getTemplate(Text defaultTemplate, int templateTag) {
+	private Text getTemplate(Text defaultTemplate, int templateTag)
+	{
 		Text t = null;
 
@@ -1677,7 +1754,6 @@
 
 		if (t == null) {
-			if (defaultTemplate == null) {
-				return null;
-			}
+			if (defaultTemplate == null) return null;
+			
 			t = defaultTemplate;
 		}
@@ -1685,4 +1761,5 @@
 		// If the item is linked apply any attribute pairs on the child frame
 		String link = t.getAbsoluteLink();
+		
 		// need to get link first because copy doesnt copy the link
 		t = t.copy();
@@ -1701,21 +1778,28 @@
 	}
 
-	public Text getItemTemplate(char firstChar) {
+	/**
+	 * TODO: Comment. cts16
+	 * TODO: Remove magic constants. cts16 
+	 */
+	public Text getItemTemplate(char firstChar)
+	{
 		switch (firstChar) {
-		case '@':
-			return getAnnotationTemplate();
-		case '/':
-		case '#':
-			return getCodeCommentTemplate();
-		default:
-			return getItemTemplate();
-		}
-	}
-
-	public Text createNewText() {
+			case '@':
+				return getAnnotationTemplate();
+			case '/':
+			case '#':
+				return getCodeCommentTemplate();
+			default:
+				return getItemTemplate();
+		}
+	}
+
+	public Text createNewText()
+	{
 		return createNewText("");
 	}
 
-	public Text addText(int x, int y, String text, String action) {
+	public Text addText(int x, int y, String text, String action)
+	{
 		Text t = createNewText(text);
 		t.setPosition(x, y);
@@ -1724,12 +1808,14 @@
 	}
 
-	public Item addText(int x, int y, String text, String action, String link) {
-		Item t = addText(x, y, text, action);
+	public Text addText(int x, int y, String text, String action, String link)
+	{
+		Text t = addText(x, y, text, action);
 		t.setLink(link);
 		return t;
 	}
 
-	public Item addDot(int x, int y) {
-		Item d = new Dot(x, y, getNextItemID());
+	public Dot addDot(int x, int y)
+	{
+		Dot d = new Dot(x, y, getNextItemID());
 		addItem(d);
 		return d;
@@ -1754,5 +1840,6 @@
 	 *            Color to fill the rectangle with
 	 */
-	public List<Item> addRectangle(int x, int y, int width, int height, float borderThickness, Color borderColor, Color fillColor) {
+	public List<Item> addRectangle(int x, int y, int width, int height, float borderThickness, Colour borderColor, Colour fillColor)
+	{
 		List<Item> rectComponents = new ArrayList<Item>();
 		Item[] corners = new Item[4];
@@ -1796,23 +1883,23 @@
 		List<Item> rect = new ArrayList<Item>(rectComponents);
 		this.addAllItems(rectComponents);
-		FrameMouseActions.anchor(rectComponents);
+		StandardGestureActions.anchor(rectComponents);
 		return rect;
-		// rectComponents.clear();
-	}
-
-	public boolean isSaved() {
+	}
+
+	public boolean isSaved()
+	{
 		return _saved;
 	}
 
-	public void setSaved() {
-		// System.out.println(getName() + " saved");
+	public void setSaved()
+	{
 		_saved = true;
 		_change = false;
 	}
 
-	public static boolean rubberbandingLine() {
-		return FreeItems.getInstance().size() == 2
-				&& (FreeItems.getInstance().get(0) instanceof Line || FreeItems
-						.getInstance().get(1) instanceof Line);
+	public static boolean rubberbandingLine()
+	{
+		return 	FreeItems.getInstance().size() == 2 &&
+				(FreeItems.getInstance().get(0) instanceof Line || FreeItems.getInstance().get(1) instanceof Line);
 	}
 
@@ -1825,7 +1912,7 @@
 	 * @return true if the item is a normal text item
 	 */
-	public boolean isNormalTextItem(Item it) {
-		if (it instanceof Text && it != getTitleItem() && it != _frameName
-				&& !((Text) it).isSpecialAnnotation()) {
+	public boolean isNormalTextItem(Item it)
+	{
+		if (it instanceof Text && it != getTitleItem() && it != _frameName && !((Text) it).isSpecialAnnotation()) {
 			return true;
 		}
@@ -1839,16 +1926,15 @@
 	 * @param index
 	 */
-	public boolean moveMouseToTextItem(int index) {
+	public boolean moveMouseToTextItem(int index)
+	{
 		List<Item> items = getItems();
 		int itemsFound = 0;
 		for (int i = 0; i < items.size(); i++) {
 			Item it = items.get(i);
-			if (isNormalTextItem(it))
-				itemsFound++;
+			if (isNormalTextItem(it)) itemsFound++;
 			if (itemsFound > index) {
-				DisplayIO.setCursorPosition(((Text) it)
-						.getParagraphEndPosition().x, it.getY());
-				DisplayIO.resetCursorOffset();
-				FrameGraphics.Repaint();
+				DisplayController.setCursorPosition(((Text) it).getParagraphEndPosition().x, it.getY());
+				DisplayController.resetCursorOffset();
+				DisplayController.requestRefresh(true);
 				return true;
 			}
@@ -1857,22 +1943,13 @@
 		return false;
 	}
-
-	/*
-	 * public boolean moveMouseToNextTextItem(int index) { List<Item> items =
-	 * getItems(); int itemsFound = 0; for (int i = 0; i < items.size(); i++) {
-	 * Item it = items.get(i); if ( isNormalTextItem(it)) itemsFound++; if
-	 * (itemsFound > index) {
-	 * DisplayIO.setCursorPosition(((Text)it).getEndParagraphPosition().x,
-	 * it.getY()); DisplayIO.resetCursorOffset(); FrameGraphics.Repaint();
-	 * return true; } }
-	 * 
-	 * return false; }
-	 */
 
 	/**
 	 * Searches for an annotation item called start to be used as the default
 	 * cursor location when TDFC occurs.
-	 */
-	public boolean moveMouseToDefaultLocation() {
+	 * 
+	 * TODO: Remove magic constants. cts16
+	 */
+	public boolean moveMouseToDefaultLocation()
+	{
 		List<Item> items = getItems();
 
@@ -1880,6 +1957,5 @@
 			if (it instanceof Text) {
 				Text t = (Text) it;
-				if (t.getText().toLowerCase().startsWith("@start")
-						|| t.getText().toLowerCase().equals("@start:")) {
+				if (t.getText().toLowerCase().startsWith("@start") || t.getText().toLowerCase().equals("@start:")) {
 					// Used to allow users the option of putting an initial
 					// bullet after the @start
@@ -1888,12 +1964,13 @@
 					t.setText("");
 
-					if (t.getText().equals(""))
-						DisplayIO.getCurrentFrame().removeItem(t);
-					if (!FreeItems.itemsAttachedToCursor()) {
-						DisplayIO.setCursorPosition(((Text) it)
-								.getParagraphEndPosition());
-						DisplayIO.resetCursorOffset();
+					if (t.getText().equals("")) DisplayController.getCurrentFrame().removeItem(t);
+					
+					if (!FreeItems.hasItemsAttachedToCursor()) {
+						DisplayController.setCursorPosition(((Text) it).getParagraphEndPosition());
+						DisplayController.resetCursorOffset();
 					}
-					FrameGraphics.Repaint();
+					
+					DisplayController.requestRefresh(true);
+					
 					return true;
 				}
@@ -1911,5 +1988,6 @@
 	 *         name of the frame if the tag isnt on the frame.
 	 */
-	public String getExportFileName() {
+	public String getExportFileName()
+	{
 		String fileName = getExportFileTagValue();
 
@@ -1925,10 +2003,11 @@
 	}
 
-	public void toggleBackgroundColor() {
-		setBackgroundColor(ColorUtils.getNextColor(_background,
-				TemplateSettings.BackgroundColorWheel.get(), null));
-	}
-
-	public void setName(String frameset, int i) {
+	public void toggleBackgroundColor()
+	{
+		setBackgroundColor(ColorUtils.getNextColor(_background, TemplateSettings.BackgroundColorWheel.get(), null));
+	}
+
+	public void setName(String frameset, int i)
+	{
 		setFrameset(frameset);
 		setFrameNumber(i);
@@ -1940,7 +2019,7 @@
 	 * 
 	 */
-	public void refreshItemPermissions(UserAppliedPermission maxPermission) {
-		if(_frameName == null)
-			return;
+	public void refreshItemPermissions(UserAppliedPermission maxPermission)
+	{
+		if(_frameName == null) return;
 		
 		UserAppliedPermission permission = UserAppliedPermission.min(maxPermission, getUserAppliedPermission());
@@ -1948,17 +2027,17 @@
 		switch (permission) {
 		case none:
-			_frameName.setBackgroundColor(new Color(255, 220, 220));
+			_frameName.setBackgroundColor(FRAME_NAME_BACKGROUND_COLOUR_FOR_PERMISSION_NONE);
 			break;
 		case followLinks:
-			_frameName.setBackgroundColor(new Color(255, 230, 135));
+			_frameName.setBackgroundColor(FRAME_NAME_BACKGROUND_COLOUR_FOR_PERMISSION_FOLLOW_LINKS);
 			break;
 		case copy:
-			_frameName.setBackgroundColor(new Color(255, 255, 155));
+			_frameName.setBackgroundColor(FRAME_NAME_BACKGROUND_COLOUR_FOR_PERMISSION_COPY);
 			break;
 		case createFrames:
-			_frameName.setBackgroundColor(new Color(220, 255, 220));
+			_frameName.setBackgroundColor(FRAME_NAME_BACKGROUND_COLOUR_FOR_PERMISSION_CREATE_FRAMES);
 			break;
 		case full:
-			_frameName.setBackgroundColor(null);
+			_frameName.setBackgroundColor(FRAME_NAME_BACKGROUND_COLOUR_FOR_PERMISSION_FULL);
 			break;
 		default:
@@ -1975,20 +2054,18 @@
 	}
 
-	public boolean isTestFrame() {
+	public boolean isTestFrame()
+	{
 		Text title = getTitleItem();
-		if (title == null)
-			return false;
+		if (title == null) return false;
 		String action = title.getFirstAction();
-		if (action == null)
-			return false;
+		if (action == null) return false;
 		action = action.toLowerCase();
-		return action.startsWith(Simple.RUN_FRAME_ACTION)
-				|| action.startsWith(Simple.DEBUG_FRAME_ACTION);
-	}
-
-	public void setActiveTime(String activeTime) {
+		return action.startsWith(Simple.RUN_FRAME_ACTION) || action.startsWith(Simple.DEBUG_FRAME_ACTION);
+	}
+
+	public void setActiveTime(String activeTime)
+	{
 		try {
-			_activeTime = new Time(Time.valueOf(activeTime).getTime() + 12 * 60
-					* 60 * 1000);
+			_activeTime = new Time(Time.valueOf(activeTime).getTime() + 12 * 60 * 60 * 1000);
 		} catch (Exception e) {
 			_activeTime = new Time(0);
@@ -1996,16 +2073,18 @@
 	}
 
-	public void setActiveTime(Time activeTime) {
+	public void setActiveTime(Time activeTime)
+	{
 		_activeTime = activeTime;
 	}
 
-	public void setDarkTime(Time darkTime) {
+	public void setDarkTime(Time darkTime)
+	{
 		_darkTime = darkTime;
 	}
 
-	public void setDarkTime(String darkTime) {
+	public void setDarkTime(String darkTime)
+	{
 		try {
-			_darkTime = new Time(Time.valueOf(darkTime).getTime() + 12 * 60
-					* 60 * 1000);
+			_darkTime = new Time(Time.valueOf(darkTime).getTime() + 12 * 60 * 60 * 1000);
 		} catch (Exception e) {
 			_darkTime = new Time(0);
@@ -2018,8 +2097,9 @@
 	 * @return the backup frame for this frame
 	 */
-	public Frame getBackupFrame() {
+	public Frame getBackupFrame()
+	{
 		Text backupTag = _annotations.get("old");
-		if (backupTag == null)
-			return null;
+		if (backupTag == null) return null;
+		
 		// TODO want another way to deal with updating of annotations items
 		// without F12 refresh
@@ -2031,8 +2111,8 @@
 			return getBackupFrame();
 		}
+		
 		// Now return the name of the backed up frame
 		String link = backupTag.getAbsoluteLink();
-		if (link == null || link.equalsIgnoreCase(getName()))
-			return null;
+		if (link == null || link.equalsIgnoreCase(getName())) return null;
 
 		Frame backup = FrameIO.LoadFrame(link);
@@ -2040,9 +2120,11 @@
 	}
 
-	public Time getDarkTime() {
+	public Time getDarkTime()
+	{
 		return _darkTime;
 	}
 
-	public Time getActiveTime() {
+	public Time getActiveTime()
+	{
 		return _activeTime;
 	}
@@ -2054,13 +2136,16 @@
 	 * @return the number of frames in the backed up comet
 	 */
-	public int getCometLength() {
+	public int getCometLength()
+	{
 		Frame backup = getBackupFrame();
 		return 1 + (backup == null ? 0 : backup.getCometLength());
 	}
 
-	public void addAnnotation(Text item) {
+	public void addAnnotation(Text item)
+	{
 		if (_annotations == null) {
 			_annotations = new HashMap<String, Text>();
 		}
+		
 		// Check if this item has already been processed
 		String[] tokens = item.getProcessedText();
@@ -2074,4 +2159,5 @@
 		String text = item.getText().trim();
 		assert (text.charAt(0) == '@');
+		
 		// Ignore annotations with spaces after the tag symbol
 		if (text.length() < 2 || !Character.isLetter(text.charAt(1))) {
@@ -2079,4 +2165,5 @@
 			return;
 		}
+		
 		// The separator char must come before the first non letter otherwise we
 		// ignore the annotation item
@@ -2101,4 +2188,5 @@
 			}
 		}
+		
 		// If it was nothing but letters and digits save the tag
 		String lowerCaseText = text.substring(1).toLowerCase();
@@ -2107,7 +2195,8 @@
 	}
 
-	public boolean hasAnnotation(String annotation) {
-		if (_annotations == null)
-			refreshAnnotationList();
+	public boolean hasAnnotation(String annotation)
+	{
+		if (_annotations == null) refreshAnnotationList();
+		
 		return _annotations.containsKey(annotation.toLowerCase());
 	}
@@ -2121,35 +2210,36 @@
 	 *         is not on the frame or has no value.
 	 */
-	public String getAnnotationValue(String annotation) {
-		if (_annotations == null)
-			refreshAnnotationList();
+	public String getAnnotationValue(String annotation)
+	{
+		if (_annotations == null) refreshAnnotationList();
 
 		Text text = _annotations.get(annotation.toLowerCase());
-		if (text == null)
-			return null;
+		if (text == null) return null;
 
 		String[] tokens = text.getProcessedText();
-		if (tokens != null && tokens.length > 1)
-			return tokens[1];
+		
+		if (tokens != null && tokens.length > 1) return tokens[1];
+		
 		return null;
 	}
 
-	Map<String, Text> _annotations = null;
-
-	private Collection<FrameObserver> _observers = new HashSet<FrameObserver>();
-
-	public void clearAnnotations() {
+	public void clearAnnotations()
+	{
 		_annotations = null;
 	}
 
-	public List<Item> getVisibleItems() {
+	public List<Item> getVisibleItems()
+	{
 		return getItems(true);
 	}
 
-	private void refreshAnnotationList() {
-		if (_annotations == null)
+	private void refreshAnnotationList()
+	{
+		if (_annotations == null) {
 			_annotations = new HashMap<String, Text>();
-		else
+		} else {
 			_annotations.clear();
+		}
+		
 		for (Text text : getTextItems()) {
 			if (text.isAnnotation()) {
@@ -2159,8 +2249,10 @@
 	}
 
-	public Collection<Text> getAnnotationItems() {
+	public Collection<Text> getAnnotationItems()
+	{
 		if (_annotations == null) {
 			refreshAnnotationList();
 		}
+		
 		return _annotations.values();
 	}
@@ -2171,6 +2263,6 @@
 	 * @return the list of items to be saved to a text file
 	 */
-	public List<Item> getItemsToSave() {
-
+	public List<Item> getItemsToSave()
+	{
 		if (!_sorted) {
 			Collections.sort(_body);
@@ -2179,18 +2271,15 @@
 
 		// iWidgets are handled specially since 8 items are written as one
-		Collection<InteractiveWidget> seenWidgets = new LinkedHashSet<InteractiveWidget>();
+		Collection<Widget> seenWidgets = new LinkedHashSet<Widget>();
 
 		List<Item> toSave = new ArrayList<Item>();
 
 		for (Item i : _body) {
-			if (i == null || i.dontSave()) {
-				continue;
-			}
+			if (i == null || i.dontSave()) continue;
 
 			// Ensure only one of the WidgetCorners represent a single widget
 			if (i instanceof WidgetCorner) {
-				InteractiveWidget iw = ((WidgetCorner) i).getWidgetSource();
-				if (seenWidgets.contains(iw))
-					continue;
+				Widget iw = ((WidgetCorner) i).getWidgetSource();
+				if (seenWidgets.contains(iw)) continue;
 				seenWidgets.add(iw);
 				toSave.add(iw.getSource());
@@ -2198,6 +2287,6 @@
 				XRayable x = (XRayable) i;
 				toSave.addAll(x.getItemsToSave());
-			}// Circle centers are items with attached enclosures
-			else if (i.hasEnclosures()) {
+			// Circle centers are items with attached enclosures
+			} else if (i.hasEnclosures()) {
 				continue;
 			} else {
@@ -2213,5 +2302,6 @@
 	}
 
-	public Collection<Item> getOverlayItems() {
+	public Collection<Item> getOverlayItems()
+	{
 		return _overlayItems;
 	}
@@ -2223,9 +2313,11 @@
 	 * @return
 	 */
-	public boolean hasOverlay(Frame frame) {
+	public boolean hasOverlay(Frame frame)
+	{
 		return _overlays.containsValue(frame);
 	}
 
-	public Collection<Item> getAllItems() {
+	public Collection<Item> getAllItems()
+	{
 		Collection<Item> allItems = new LinkedHashSet<Item>(_body);
 		allItems.addAll(_overlayItems);
@@ -2234,5 +2326,6 @@
 	}
 
-	public Collection<Item> getVectorItems() {
+	public Collection<Item> getVectorItems()
+	{
 		Collection<Item> vectorItems = new LinkedHashSet<Item>(_vectorItems);
 		vectorItems.addAll(getNonAnnotationItems(false));
@@ -2245,6 +2338,8 @@
 	 * @return
 	 */
-	public Collection<Text> getTextItems() {
+	public Collection<Text> getTextItems()
+	{
 		Collection<Text> textItems = new ArrayList<Text>();
+		
 		for (Item i : getItems(true)) {
 			// only add up normal body text items
@@ -2253,16 +2348,17 @@
 			}
 		}
+		
 		return textItems;
 	}
 
-	public Text getAnnotation(String annotation) {
-		if (_annotations == null)
-			refreshAnnotationList();
+	public Text getAnnotation(String annotation)
+	{
+		if (_annotations == null) refreshAnnotationList();
 
 		return _annotations.get(annotation.toLowerCase());
 	}
 
-	public void recalculate() {
-
+	public void recalculate()
+	{
 		for (Item i : getItems()) {
 			if (i.hasFormula() && !i.isAnnotation()) {
@@ -2272,22 +2368,28 @@
 	}
 
-	public void removeObserver(FrameObserver observer) {
+	public void removeObserver(FrameObserver observer)
+	{
 		_observers.remove(observer);
 	}
 
-	public void addObserver(FrameObserver observer) {
+	public void addObserver(FrameObserver observer)
+	{
 		_observers.add(observer);
 	}
 
-	public void clearObservers() {
+	public void clearObservers()
+	{
 		for (FrameObserver fl : _observers) {
 			fl.removeSubject(this);
 		}
+		
 		// The frame listener will call the frames removeListener method
 		assert (_observers.size() == 0);
 	}
 
-	public Collection<Text> getNonAnnotationText(boolean removeTitle) {
+	public Collection<Text> getNonAnnotationText(boolean removeTitle)
+	{
 		Collection<Text> items = new LinkedHashSet<Text>();
+		
 		for (Item i : getItems(true)) {
 			// only add up normal body text items
@@ -2296,15 +2398,20 @@
 			}
 		}
+		
 		if (removeTitle) {
 			items.remove(getTitleItem());
 		}
+		
 		return items;
 	}
 
-	public void dispose() {
+	public void dispose()
+	{
 		clearObservers();
+		
 		for (Item i : _body) {
 			i.dispose();
 		}
+		
 		_frameName.dispose();
 		_body = null;
@@ -2312,40 +2419,47 @@
 	}
 
-	public void parse() {
+	public void parse()
+	{
 		for (Overlay o : getOverlays()) {
 			o.Frame.parse();
 		}
+		
 		// Must parse the frame AFTER the overlays
 		FrameUtils.Parse(this);
 	}
 
-	public void setPath(String path) {
+	public void setPath(String path)
+	{
 		this.path = path;
 	}
 
-	public String getPath() {
+	public String getPath()
+	{
 		return path;
 	}
 
-	public void setLocal(boolean isLocal) {
+	public void setLocal(boolean isLocal)
+	{
 		this._isLocal = isLocal;
 	}
 
-	public boolean isLocal() {
+	public boolean isLocal()
+	{
 		return _isLocal;
 	}
 
-	public String getExportFileTagValue() {
+	public String getExportFileTagValue()
+	{
 		return getAnnotationValue("file");
 	}
 
-	public void assertEquals(Frame frame2) {
+	public void assertEquals(Frame frame2)
+	{
 		// Check that all the items on the frame are the same
 		List<Item> items1 = getVisibleItems();
 		List<Item> items2 = frame2.getVisibleItems();
+		
 		if (items1.size() != items2.size()) {
-			throw new UnitTestFailedException(items1.size() + " items", items2
-					.size()
-					+ " items");
+			throw new UnitTestFailedException(items1.size() + " items", items2.size() + " items");
 		} else {
 			for (int i = 0; i < items1.size(); i++) {
@@ -2361,20 +2475,19 @@
 	}
 
-	public boolean hasObservers() {
+	public boolean hasObservers()
+	{
 		return _observers != null && _observers.size() > 0;
 	}
 
-	public Collection<? extends Item> getInteractableItems() {
+	public Collection<? extends Item> getInteractableItems()
+	{
 		/*
 		 * TODO: Cache the interactableItems list so we dont have to recreate it
 		 * every time this method is called
 		 */
-		if (_interactableItems.size() > 0)
-			return _interactableItems;
+		if (_interactableItems.size() > 0) return _interactableItems;
 
 		for (Item i : _body) {
-			if (i == null) {
-				continue;
-			}
+			if (i == null) continue;
 			if (i.isVisible()) {
 				_interactableItems.add(i);
@@ -2386,6 +2499,4 @@
 				_interactableItems.add(i);	
 			}
-			
-			
 		}
 
@@ -2398,3 +2509,26 @@
 		return _interactableItems;
 	}
+
+	private static final class History {
+		
+		public enum Type {
+			deletion,
+			movement
+		}
+		
+		public final List<Item> items;
+		
+		public final Type type;
+		
+		public History(Collection<Item> items, Type type)
+		{
+			this.items = new LinkedList<Item>(items);
+			this.type = type;
+		}
+		
+		public String toString()
+		{
+			return this.type.toString() + ":\n" + this.items.toString();
+		}
+	}
 }
