Index: /trunk/src/org/expeditee/gui/FrameKeyboardActions.java
===================================================================
--- /trunk/src/org/expeditee/gui/FrameKeyboardActions.java	(revision 942)
+++ /trunk/src/org/expeditee/gui/FrameKeyboardActions.java	(revision 943)
@@ -37,4 +37,7 @@
 import org.expeditee.actions.Navigation;
 import org.expeditee.actions.Simple;
+import org.expeditee.gui.indirect.keyboard.IndirectKeyboardActions;
+import org.expeditee.gui.indirect.keyboard.KeyboardAction;
+import org.expeditee.gui.indirect.keyboard.KeyboardAction.KeyboardInfo;
 import org.expeditee.io.ItemSelection;
 import org.expeditee.items.Circle;
@@ -60,4 +63,59 @@
 
 	protected FrameKeyboardActions() {
+		IndirectKeyboardActions.getInstance().setDropDownAction(new KeyboardAction() {
+			@Override
+			public void exec(KeyboardInfo info) {
+				// Get the last text item and drop from in
+				Item lastText = null;
+				for (Item i : info.enclosed) {
+					if (i instanceof Text) {
+						lastText = i;
+					}
+				}
+				// Drop from the item if there was a text item in the box
+				if (lastText != null) {
+					Drop(lastText, false);
+				} else {
+					// Move to the top of the box
+					Rectangle rect = info.firstConnected.getEnclosedShape()
+							.getBounds();
+					int newX = rect.x + Text.MARGIN_LEFT;
+					int newY = Text.MARGIN_LEFT
+							+ rect.y
+							+ DisplayIO.getCurrentFrame().getItemTemplate()
+									.getBoundsHeight();
+					moveCursorAndFreeItems(newX, newY);
+					// TODO can resetOffset be put inside
+					// moveCursorAndFreeItems
+					FrameMouseActions.resetOffset();
+				}
+			}  
+		});
+		IndirectKeyboardActions.getInstance().setSizeUpAction(new KeyboardAction() {
+			@Override
+			public void exec(final KeyboardInfo info) {
+				SetSize(info.firstConnected, info.repeat, false, true, info.isControlDown);
+			}		
+		});
+		IndirectKeyboardActions.getInstance().setSizeDownAction(new KeyboardAction() {
+			@Override
+			public void exec(final KeyboardInfo info) {
+				SetSize(info.firstConnected, -info.repeat, false, true, info.isControlDown);
+			}		
+		});
+		IndirectKeyboardActions.getInstance().setChangeColorAction(new KeyboardAction() {
+			@Override
+			public void exec(final KeyboardInfo info) {
+				if (info.connected.size() > 0) {
+					for (Item d : info.lineEnds) {
+						if (info.isControlDown)
+							SetGradientColor(d, info.isShiftDown);
+						else
+							SetFillColor(d, info.isShiftDown);
+						break;
+					}
+				}
+			} 
+		});
 	}
 
@@ -987,45 +1045,18 @@
 				switch (key) {
 				case DropDown:
-					// Get the last text item and drop from in
-					Item lastText = null;
-					for (Item i : enclosed) {
-						if (i instanceof Text) {
-							lastText = i;
-						}
-					}
-					// Drop from the item if there was a text item in the box
-					if (lastText != null) {
-						Drop(lastText, false);
-					} else {
-						// Move to the top of the box
-						Rectangle rect = firstConnected.getEnclosedShape()
-								.getBounds();
-						int newX = rect.x + Text.MARGIN_LEFT;
-						int newY = Text.MARGIN_LEFT
-								+ rect.y
-								+ DisplayIO.getCurrentFrame().getItemTemplate()
-										.getBoundsHeight();
-						moveCursorAndFreeItems(newX, newY);
-						// TODO can resetOffset be put inside
-						// moveCursorAndFreeItems
-						FrameMouseActions.resetOffset();
-					}
+					IndirectKeyboardActions.getInstance().getDropDownAction().exec(
+							new KeyboardInfo(key, repeat, isShiftDown, isControlDown, enclosed, firstConnected, connected, lineEnds));
 					break;
 				case SizeUp:
-					SetSize(firstConnected, repeat, false, true, isControlDown);
+					IndirectKeyboardActions.getInstance().getSizeUpAction().exec(
+							new KeyboardInfo(key, repeat, isShiftDown, isControlDown, enclosed, firstConnected, connected, lineEnds));
 					break;
 				case SizeDown:
-					SetSize(firstConnected, -repeat, false, true, isControlDown);
+					IndirectKeyboardActions.getInstance().getSizeDownAction().exec(
+							new KeyboardInfo(key, repeat, isShiftDown, isControlDown, enclosed, firstConnected, connected, lineEnds));
 					break;
 				case ChangeColor:
-					if (connected.size() > 0) {
-						for (Item d : lineEnds) {
-							if (isControlDown)
-								SetGradientColor(d, isShiftDown);
-							else
-								SetFillColor(d, isShiftDown);
-							break;
-						}
-					}
+					IndirectKeyboardActions.getInstance().getChangeColorAction().exec(
+							new KeyboardInfo(key, repeat, isShiftDown, isControlDown, enclosed, firstConnected, connected, lineEnds));
 					break;
 				case ToggleAnnotation:
Index: /trunk/src/org/expeditee/gui/FrameMouseActions.java
===================================================================
--- /trunk/src/org/expeditee/gui/FrameMouseActions.java	(revision 942)
+++ /trunk/src/org/expeditee/gui/FrameMouseActions.java	(revision 943)
@@ -87,5 +87,5 @@
 		IndirectMouseActions.getInstance().setBackAction(new MouseAction() {
 			@Override
-			public void exec(MouseInfo info) {
+			public List<Item> exec(MouseInfo info) {
 				//if user is not pointing at something,this is a back
 				if (info.isControlDown || info.isShiftDown)
@@ -93,5 +93,597 @@
 				else
 					back();
-			}
+				return null;
+			}
+		});
+		IndirectMouseActions.getInstance().setTDFCAction(new MouseAction() {
+			@Override
+			public List<Item> exec(final MouseInfo info) {
+				// check for TDFC permission
+				if (!info.clicked.hasPermission(UserAppliedPermission.createFrames)) {
+					MessageBay
+							.displayMessage("Insufficient permission to TDFC (Top Down Frame Creation) from that item");
+					return null;
+				}
+
+				if (info.clicked.isOldTag())
+					return null;
+
+				try {
+					tdfc(info.clicked);
+				} catch (RuntimeException e) {
+					e.printStackTrace();
+					MessageBay.errorMessage("Top Down Frame Creation (TDFC) error: " + e.getMessage());
+				}
+				return null;
+			}
+		});
+		IndirectMouseActions.getInstance().setRespondToFrameNameClickAction(new MouseAction() {
+			@Override
+			public List<Item> exec(MouseInfo info) {
+				if (info.isControlDown)
+					Navigation.PreviousFrame(false);
+				else
+					Navigation.NextFrame(false);
+				return null;
+			} 		
+		});
+		IndirectMouseActions.getInstance().setFollowLinkAction(new MouseAction() {
+			@Override
+			public List<Item> exec(MouseInfo info) {
+				/*
+				 * Dont save the frame if we are moving to an old version of
+				 * this frame because everytime we save with the old tag... the
+				 * frame is backed up
+				 */
+				if (!info.clicked.isOldTag())
+					FrameIO.SaveFrame(DisplayIO.getCurrentFrame());
+
+				Navigation.setLastNavigationItem(info.clicked);
+				load(info.clicked.getAbsoluteLink(), info.clicked.getLinkHistory());
+				// DisplayIO.UpdateTitle();
+				return null;
+			}
+		});
+		IndirectMouseActions.getInstance().setExecuteActionAction(new MouseAction() {
+			@Override
+			public List<Item> exec(MouseInfo info) {
+				info.clicked.performActions();
+				info.clicked.setHighlightMode(HighlightMode.None);
+				getInstance().refreshHighlights();
+				return null;
+			} 
+		});
+		IndirectMouseActions.getInstance().setCreateRectangleAction(new MouseAction() {
+			@Override
+			public List<Item> exec(MouseInfo info) {
+				final List<Item> copies = new ArrayList<Item>();
+				Item[] d = new Item[RECTANGLE_CORNERS];
+				// create dots
+				Frame current = DisplayIO.getCurrentFrame();
+				for (int i = 0; i < d.length; i++) {
+					d[i] = current.createDot();
+					copies.add(d[i]);
+				}
+
+				current.nextDot();
+
+				// create lines
+				copies.add(new Line(d[0], d[1], current.getNextItemID()));
+				copies.add(new Line(d[1], d[2], current.getNextItemID()));
+				copies.add(new Line(d[2], d[3], current.getNextItemID()));
+				copies.add(new Line(d[3], d[0], current.getNextItemID()));
+
+				new Constraint(d[0], d[1], current.getNextItemID(),
+						Constraint.HORIZONTAL);
+				new Constraint(d[2], d[3], current.getNextItemID(),
+						Constraint.HORIZONTAL);
+				new Constraint(d[1], d[2], current.getNextItemID(),
+						Constraint.VERTICAL);
+				new Constraint(d[3], d[0], current.getNextItemID(),
+						Constraint.VERTICAL);
+
+				anchor(new ArrayList<Item>(copies));
+				pickup(d[3]);
+				d[3].setHighlightMode(HighlightMode.Normal);
+
+				SessionStats.CreatedItems(copies);
+				copies.clear();
+				return copies;
+			} 
+		});
+		IndirectMouseActions.getInstance().setExtendLineAction(new MouseAction() {
+			@Override
+			public List<Item> exec(final MouseInfo info) {
+				Line onLine = (Line) info.clicked;
+				Line newLine = onLine.copy();
+				Item end = newLine.getEndItem();
+				Item start = newLine.getStartItem();
+				end.setPosition(MouseX, MouseY);
+				start.setPosition(MouseX, MouseY);
+				onLine.autoArrowheadLength();
+				// anchor the start
+				anchor(start);
+				// attach the line to the cursor
+				pickup(end);
+
+				List<Item> toMerge = new LinkedList<Item>();
+				toMerge.add(newLine.getStartItem());
+				toMerge.add(newLine);
+
+				// Make sure the highlighting is shown when the end is
+				// anchored
+				end.setHighlightMode(Item.HighlightMode.Normal);
+				merge(toMerge, info.clicked);
+				// anchor(left);
+				// FreeItems.getInstance().clear();
+				FrameGraphics.Repaint();
+				updateCursor();
+				return null;
+			} 
+		});
+		IndirectMouseActions.getInstance().setMakeGroupCopyAction(new MouseAction() {
+			@Override
+			public List<Item> exec(final MouseInfo info) {
+				List<Item> copies = new ArrayList<Item>();
+				// Set the selection mode for the items that were clicked in
+				Collection<Item> enclosed = getFullyEnclosedItems(info.clickedIn);
+				if (enclosed.size() == 0) {
+					MessageBay
+							.displayMessage("Insufficient permission to copy items");
+				} else {
+					copies = copy(enclosed);
+					clearParent(copies);
+					ItemUtils.Justify(copies);
+					pickup(copies);
+					for (Item i : info.clickedIn) {
+						i.setHighlightMode(HighlightMode.None);
+					}
+				}
+				return copies;
+			}
+		});
+		IndirectMouseActions.getInstance().setMakeCopyAction(new MouseAction() {
+			@Override
+			public List<Item> exec(MouseInfo info) {
+				List<Item> copies = ItemUtils.UnreelLine(info.clicked, _controlDown);
+				// Copies will NOT be null if the user right clicked on a point
+				if (copies == null) {
+					Collection<Item> originals = info.clicked.getConnected();
+					copies = ItemUtils.CopyItems(originals, _extrude);
+					// if this is the title of the frame, link it to the frame
+					if (originals.size() == 1 && copies.size() == 1) {
+						Item copy = copies.get(0);
+						Item original = originals.iterator().next();
+						if (original.getLink() == null
+								&& original.isFrameTitle()) {
+							// save the frame after copying
+							// i.getParent().setChanged(true);
+							copy.setLink(original.getParentOrCurrentFrame()
+									.getName());
+						}
+					}
+
+					FrameGraphics.changeHighlightMode(info.clicked,
+							HighlightMode.None);
+
+					if (!_extrude)
+						clearParent(copies);
+				}
+				
+				ItemUtils.Justify(copies);
+
+				pickup(copies);
+				return copies;
+			}	
+		});
+		IndirectMouseActions.getInstance().setExtrudeAction(new MouseAction() {
+			@Override
+			public List<Item> exec(MouseInfo info) {
+				List<Item> copies = null;
+				List<Item> originals = new ArrayList<Item>();
+				// remove any lines that dont have both endpoints
+				// floating
+				for (Item i : FreeItems.getInstance()) {
+					if (i.isFloating())
+						originals.add(i);
+				}
+				if (copies == null)
+					copies = ItemUtils.CopyItems(originals, _extrude);
+				for (Item i : copies)
+					i.setOffset(0, 0);
+				anchor(FreeItems.getInstance());
+				// Move isnt working right for extruding!!
+				// move(copies);
+				pickup(copies);
+				return copies;
+			} 	
+		});
+		IndirectMouseActions.getInstance().setRubberBandingCopyAction(new MouseAction() {
+			@Override
+			public List<Item> exec(MouseInfo info) {
+				List<Item> copies = new ArrayList<Item>();
+				if (info.clicked != null) {
+					Collection<Item> leftOver = merge(FreeItems
+							.getInstance(), info.clicked);
+					anchor(leftOver);
+				}
+				// This is executed when the user is putting down a line
+				// endpoint and unreeling. ie. Normal unreeling
+				copies = ItemUtils.UnreelLine(FreeItems.getInstance(),
+						_controlDown);
+
+				if (copies == null)
+					copies = copy(FreeItems.getInstance());
+				anchor(FreeItems.getInstance());
+				for (Item i : copies)
+					i.setOffset(0, 0);
+				// need to move to prevent cursor dislocation
+				move(copies);
+				pickup(copies);
+				return copies;
+			}		
+		});
+		IndirectMouseActions.getInstance().setRubberBandingCornerAction(new MouseAction() {
+			@Override
+			public List<Item> exec(final MouseInfo info) {
+				List<Item> copies = new ArrayList<Item>();
+				Item d = getFirstFreeLineEnd();
+				// anchor the points
+				anchor(FreeItems.getInstance());
+				FreeItems.getInstance().clear();
+				updateCursor();
+				// pick up a copy of all enclosed items
+				Collection<Item> enclosedItems = FrameUtils
+						.getItemsEnclosedBy(DisplayIO.getCurrentFrame(), d
+								.getEnclosedShape());
+				if (enclosedItems != null) {
+					enclosedItems.removeAll(d.getAllConnected());
+					Collection<Item> toCopy = getFullyEnclosedItems(enclosedItems);
+
+					if (toCopy.size() > 0) {
+						// Find the closest item to the mouse cursor
+						double currentX = DisplayIO.getMouseX();
+						double currentY = FrameMouseActions.getY();
+						Item closest = null;
+						double shortestDistance = Double.MAX_VALUE;
+						for (Item next : toCopy) {
+							if (next instanceof Line)
+								continue;
+							double distance = Point.distance(currentX,
+									currentY, next.getX(), next.getY());
+							if (distance < shortestDistance) {
+								shortestDistance = distance;
+								closest = next;
+							}
+						}
+						// Move the cursor to closest item
+						DisplayIO.setCursorPosition(closest.getPosition());
+						// Pickup copy of the stuff inside the rectange
+						copies = copy(toCopy);
+						pickup(copies);
+						// Remove the rectangle
+						d.getParentOrCurrentFrame().removeAllItems(
+								d.getAllConnected());
+					} else {
+						// Pick up a copy of the rectangle
+						copies = copy(d.getAllConnected());
+						pickup(copies);
+					}
+				}
+				return copies;
+			}		
+		});
+		IndirectMouseActions.getInstance().setStampAction(new MouseAction() {
+			@Override
+			public List<Item> exec(MouseInfo info) {
+				List<Item> copies = new ArrayList<Item>();
+				stampItemsOnCursor(true);
+				copies = FreeItems.getInstance();
+				return copies;
+			}	
+		});
+		IndirectMouseActions.getInstance().setMergeSingleItemAction(new MouseAction() {
+			@Override
+			public List<Item> exec(final MouseInfo info) {
+				List<Item> copies = new ArrayList<Item>();
+				copies = copy(FreeItems.getInstance());
+				Collection<Item> remain = merge(copies, info.clicked);
+
+				// ignore items that could not be merged.
+				anchor(remain);
+				return copies;
+			}  
+		});
+		IndirectMouseActions.getInstance().setMergeTwoItemsAction(new MouseAction() {
+			@Override
+			public List<Item> exec(MouseInfo info) {
+				List<Item> copies = new ArrayList<Item>();
+				copies = ItemUtils.UnreelLine(FreeItems.getInstance(),
+						_controlDown);
+				Collection<Item> leftOver = merge(FreeItems
+						.getInstance(), info.clicked);
+				anchor(leftOver);
+				if (copies == null)
+					copies = copy(FreeItems.getInstance());
+				FreeItems.getInstance().clear();
+				for (Item i : copies)
+					i.setOffset(0, 0);
+				// need to move to prevent cursor dislocation
+				move(copies);
+				pickup(copies);
+				// point onto point
+				return copies;
+			} 		
+		});
+		IndirectMouseActions.getInstance().setMergeGroupAction(new MouseAction() {
+			@Override
+			public List<Item> exec(final MouseInfo info) {
+				List<Item> copies = new ArrayList<Item>();
+				// Move the cursor so that the copy is exactly the
+				// same as the shape that was anchored
+				DisplayIO.setCursorPosition(info.clicked.getPosition());
+				Item d = getFirstFreeLineEnd();
+				// get a copy of all enclosed items before merging
+				// lineEnds
+				Collection<Item> items = FrameUtils.getItemsEnclosedBy(
+						DisplayIO.getCurrentFrame(), d
+								.getEnclosedShape());
+				// If its not an enclosed shape then pick up the
+				// connected shape
+				if (items == null || items.size() == 0) {
+					items = d.getAllConnected();
+				} else {
+					// For some reason the item that was clicked ends up
+					// in the enclosure and needs to be removed
+					items.removeAll(info.clicked.getConnected());
+					// the item that was the origin of the enclosed
+					// shape used to create the enclosure does not get
+					// returned from getItemsEnclosedBy to the enclosure
+					// so it must be added
+					items.addAll(d.getConnected());
+				}
+
+				Collection<Item> toCopy = new LinkedHashSet<Item>();
+
+				for (Item ip : items) {
+					if (ip.hasPermission(UserAppliedPermission.copy))
+						toCopy.add(ip);
+				}
+				copies = copy(toCopy);
+				// Now do the merging
+				Collection<Item> remain = merge(
+						FreeItems.getInstance(), info.clicked);
+				// anchor the points
+				anchor(remain);
+				FreeItems.getInstance().clear();
+				pickup(copies);
+				return copies;
+			}		
+		});
+		IndirectMouseActions.getInstance().setNewLineAction(new MouseAction() {
+			@Override
+			public List<Item> exec(MouseInfo info) {
+				List<Item> copies = new ArrayList<Item>();
+				Item on = FrameUtils.onItem(DisplayIO.getCurrentFrame(), Math
+						.round(MouseX), Math.round(MouseY), true);
+				// If we have permission to copy this item then pick it up
+				if (on != null && on.isLineEnd()
+						&& on.hasPermission(UserAppliedPermission.full)) {
+					on.removeAllConstraints();
+					pickup(on);
+					return copies;
+				}
+
+				if (on instanceof WidgetEdge) {
+					// Don't allow the user to break widget edges.
+					// Note: had to return here because random dots would
+					// appear otherwise... cannot understand code below
+					// with create line.
+					return copies;
+				}
+
+				// if its on a line then split the line and put a point on it and
+				// pick that point up. Only if it is not a widget line
+				if (on instanceof Line && on.hasPermission(UserAppliedPermission.full)) {
+					Frame current = DisplayIO.getCurrentFrame();
+					// create the two endpoints
+					Line oldLine = (Line) info.clicked;
+					Item newPoint = oldLine.getStartItem().copy();
+					newPoint.setPosition(MouseX, MouseY);
+
+					Item end = oldLine.getEndItem();
+					// create the Line
+					Line newLine = new Line(newPoint, end, current.getNextItemID());
+					oldLine.replaceLineEnd(end, newPoint);
+					newPoint.removeAllConstraints();
+					pickup(newPoint);
+					// Update the stats
+					Collection<Item> created = new LinkedList<Item>();
+					created.add(newPoint);
+					created.add(newLine);
+					SessionStats.CreatedItems(newLine.getAllConnected());
+					return copies;
+				}
+				Line newLine = createLine();
+				SessionStats.CreatedItems(newLine.getAllConnected());
+				return copies;
+			}
+		});
+		IndirectMouseActions.getInstance().setGroupPickupAction(new MouseAction() {
+			@Override
+			public List<Item> exec(final MouseInfo info) {
+				List<Item> copies = new ArrayList<Item>();
+				ArrayList<Item> toPickup = new ArrayList<Item>(info.clickedIn.size());
+				for (Item ip : info.clickedIn)
+					if (ip.hasPermission(UserAppliedPermission.full))
+						toPickup.add(ip);
+				pickup(toPickup);
+				// otherwise the user is creating a line
+				return copies;
+			} 
+		});
+		IndirectMouseActions.getInstance().setDetachLineAction(new MouseAction() {
+			@Override
+			public List<Item> exec(final MouseInfo info) {
+				List<Item> items = new ArrayList<Item>();
+				// BROOK: WIDGET RECTANGLES DONT ALLOW DISCONNECTION
+				if (info.clicked instanceof Line && !(info.clicked instanceof WidgetEdge)) {
+					// Check if within 20% of the end of the line
+					Line l = (Line) info.clicked;
+					Item toDisconnect = l.getEndPointToDisconnect(_lastMouseClick
+							.getX(), _lastMouseClick.getY());
+
+					if (toDisconnect == null) {
+						pickup(info.clicked);
+					} else {
+						if (toDisconnect.getHighlightMode() == Item.HighlightMode.Normal) {
+							DisplayIO.setCursorPosition(toDisconnect.getPosition(),
+									false);
+							pickup(toDisconnect);
+						} else {
+							List<Line> lines = toDisconnect.getLines();
+							// This is to remove constraints from single lines
+							// with constraints...
+							// ie. partially deleted rectangles
+							if (lines.size() == 1) {
+								toDisconnect.removeAllConstraints();
+
+								DisplayIO.setCursorPosition(toDisconnect
+										.getPosition(), false);
+								// This is to ensure the selected mode will be set
+								// to Normal rather than disconnect when the line is
+								// anchored
+								toDisconnect
+										.setHighlightMode(Item.HighlightMode.Normal);
+								pickup(toDisconnect);
+							} else {
+								// If we are then detatch the line and pick up its
+								// end point...
+								Frame currentFrame = DisplayIO.getCurrentFrame();
+								Item newPoint = null;
+
+								// If the point we are disconnecting is text...
+								// Then we want to leave the text behind
+								// And disconnect a point
+								if (toDisconnect instanceof Text) {
+									newPoint = new Dot(toDisconnect.getX(),
+											toDisconnect.getY(), -1);
+									Item.DuplicateItem(toDisconnect, newPoint);
+								} else {
+									newPoint = toDisconnect.copy();
+								}
+
+								currentFrame.addItem(newPoint);
+								// remove the current item from the connected
+								// list for this item
+								l.replaceLineEnd(toDisconnect, newPoint);
+								// remove unneeded constrains
+								newPoint.removeAllConstraints();
+
+								// Set the new points mode to normal before picking
+								// it up so it will be restored correctly when
+								// anchored
+								newPoint
+										.setHighlightMode(Item.HighlightMode.Normal);
+								toDisconnect
+										.setHighlightMode(Item.HighlightMode.None);
+								DisplayIO.setCursorPosition(toDisconnect
+										.getPosition(), false);
+								pickup(newPoint);
+								ItemUtils.EnclosedCheck(toDisconnect
+										.getParentOrCurrentFrame().getItems());
+							}
+						}
+					}
+				} else {
+					if (info.clicked.isLineEnd()) {
+						DisplayIO.setCursorPosition(info.clicked.getPosition(), false);
+					}
+					pickup(info.clicked);
+				}
+				return items;
+			}
+		});
+		IndirectMouseActions.getInstance().setAnchorFreeItemsAction(new MouseAction() {
+			@Override
+			public List<Item> exec(MouseInfo info) {
+				List<Item> items = new ArrayList<Item>();
+				if (info.clickedIn != null && FreeItems.getInstance().size() == 1) {
+					Item item = FreeItems.getItemAttachedToCursor();
+					if (item instanceof Text) {
+						Text text = (Text) item;
+						if (AttributeUtils.setAttribute(text, text, 2)) {
+							info.clickedIn.removeAll(FrameUtils
+									.getEnclosingLineEnds().iterator().next()
+									.getAllConnected());
+							for (Item i : info.clickedIn) {
+								AttributeUtils.setAttribute(i, text);
+							}
+							FreeItems.getInstance().clear();
+						}
+					}
+				}
+
+				// if a line is being rubber-banded, check for auto
+				// straightening
+				anchor(FreeItems.getInstance());
+				FreeItems.getInstance().clear();
+				updateCursor();
+				_offX = _offY = 0;
+				return items;
+			}  
+		});
+		IndirectMouseActions.getInstance().setDeleteItemsAction(new MouseAction() {
+			@Override
+			public List<Item> exec(final MouseInfo info) {
+				List<Item> items = new ArrayList<Item>();
+				// check permissions
+				if (!info.clicked.hasPermission(UserAppliedPermission.full)) {
+					//Items on the message box have parent == null
+					if (info.clicked.getParent() != null) {
+						if (!info.clicked.isFrameName()) {
+							Item editTarget = info.clicked.getEditTarget();
+							if (editTarget != info.clicked
+									&& editTarget
+											.hasPermission(UserAppliedPermission.full)) {
+								info.clicked = editTarget;
+							} else {
+								MessageBay
+										.displayMessage("Insufficient permission");
+								return items;
+							}
+						}
+						
+					} else /*Its in the message area*/ {
+						MessageBay.displayMessage("Insufficient permission");
+						return items;
+					}
+				}
+				Item merger = FreeItems.getItemAttachedToCursor();
+				assert (merger != null);
+				Collection<Item> left = null;
+				// when anchoring a line end onto a text line end, holding shift
+				// prevents the line ends from being merged
+				if (info.isShiftDown) {
+					left = FreeItems.getInstance();
+				} else {
+					left = merge(FreeItems.getInstance(), info.clicked);
+				}
+				Collection<Item> toDelete = new LinkedList<Item>();
+				toDelete.addAll(FreeItems.getInstance());
+				toDelete.removeAll(left);
+				anchor(left);
+				FreeItems.getInstance().clear();
+				DisplayIO.getCurrentFrame().removeAllItems(toDelete);
+				updateCursor();
+				// Make sure the dot goes away when anchoring a line end behind
+				// a text line end
+				if (info.isShiftDown) {
+					refreshHighlights();
+				}
+				FrameGraphics.requestRefresh(true);
+				return items;
+				// otherwise, anchor the items
+			}		
 		});
 	}
@@ -854,21 +1446,7 @@
 			if (_lastMouseClick != null && !_lastMouseClick.isControlDown()
 					&& clickedOn.hasAction()) {
-				clickedOn.performActions();
-				clickedOn.setHighlightMode(HighlightMode.None);
-				getInstance().refreshHighlights();
-				return;
+				IndirectMouseActions.getInstance().getExecuteActionAction().exec(new MouseInfo(clicked, clickedIn, isShiftDown, isControlDown));
 			} else if (clickedOn.getLink() != null) {
-				/*
-				 * Dont save the frame if we are moving to an old version of
-				 * this frame because everytime we save with the old tag... the
-				 * frame is backed up
-				 */
-				if (!clickedOn.isOldTag())
-					FrameIO.SaveFrame(DisplayIO.getCurrentFrame());
-
-				Navigation.setLastNavigationItem(clickedOn);
-				load(clickedOn.getAbsoluteLink(), clickedOn.getLinkHistory());
-				// DisplayIO.UpdateTitle();
-				return;
+				IndirectMouseActions.getInstance().getFollowLinkAction().exec(new MouseInfo(clicked, clickedIn, isShiftDown, isControlDown));
 				// no link is found, perform TDFC
 			} else {
@@ -879,37 +1457,12 @@
 				 */
 				if (clickedOn.isFrameName()) {
-					if (isControlDown)
-						Navigation.PreviousFrame(false);
-					else
-						Navigation.NextFrame(false);
-					return;
-				}
-
-				// check for TDFC permission
-				if (!clicked.hasPermission(UserAppliedPermission.createFrames)) {
-					MessageBay
-							.displayMessage("Insufficient permission to TDFC (Top Down Frame Creation) from that item");
-					return;
-				}
-
-				if (clickedOn.isOldTag())
-					return;
-
-				try {
-					tdfc(clickedOn);
-				} catch (RuntimeException e) {
-					e.printStackTrace();
-					MessageBay.errorMessage("Top Down Frame Creation (TDFC) error: " + e.getMessage());
-				}
-				return;
+					IndirectMouseActions.getInstance().getRespondToFrameNameClickAction().exec(new MouseInfo(clicked, clickedIn, isShiftDown, isControlDown));
+				}
+				
+				IndirectMouseActions.getInstance().getTDFCAction().exec(new MouseInfo(clicked, clickedIn, isShiftDown, isControlDown));
 			}
 
 		} else {
 			IndirectMouseActions.getInstance().getBackAction().exec(new MouseInfo(clicked, clickedIn, isShiftDown, isControlDown));
-			// if user is not pointing at something,this is a back
-//			if (isShiftDown || isControlDown)
-//				forward();
-//			else
-//				back();
 		}
 	}
@@ -1008,75 +1561,7 @@
 			// possible)
 			if (doMerging(clicked)) {
-				// check permissions
-				if (!clicked.hasPermission(UserAppliedPermission.full)) {
-					//Items on the message box have parent == null
-					if (clicked.getParent() != null) {
-						if (!clicked.isFrameName()) {
-							Item editTarget = clicked.getEditTarget();
-							if (editTarget != clicked
-									&& editTarget
-											.hasPermission(UserAppliedPermission.full)) {
-								clicked = editTarget;
-							} else {
-								MessageBay
-										.displayMessage("Insufficient permission");
-								return;
-							}
-						}
-						
-					} else /*Its in the message area*/ {
-						MessageBay.displayMessage("Insufficient permission");
-						return;
-					}
-				}
-				Item merger = FreeItems.getItemAttachedToCursor();
-				assert (merger != null);
-				Collection<Item> left = null;
-				// when anchoring a line end onto a text line end, holding shift
-				// prevents the line ends from being merged
-				if (isShiftDown) {
-					left = FreeItems.getInstance();
-				} else {
-					left = merge(FreeItems.getInstance(), clicked);
-				}
-				Collection<Item> toDelete = new LinkedList<Item>();
-				toDelete.addAll(FreeItems.getInstance());
-				toDelete.removeAll(left);
-				anchor(left);
-				FreeItems.getInstance().clear();
-				DisplayIO.getCurrentFrame().removeAllItems(toDelete);
-				updateCursor();
-				// Make sure the dot goes away when anchoring a line end behind
-				// a text line end
-				if (isShiftDown) {
-					refreshHighlights();
-				}
-				FrameGraphics.requestRefresh(true);
-				return;
-				// otherwise, anchor the items
+				IndirectMouseActions.getInstance().getDeleteItemsAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 			} else {
-				if (clickedIn != null && FreeItems.getInstance().size() == 1) {
-					Item item = FreeItems.getItemAttachedToCursor();
-					if (item instanceof Text) {
-						Text text = (Text) item;
-						if (AttributeUtils.setAttribute(text, text, 2)) {
-							clickedIn.removeAll(FrameUtils
-									.getEnclosingLineEnds().iterator().next()
-									.getAllConnected());
-							for (Item i : clickedIn) {
-								AttributeUtils.setAttribute(i, text);
-							}
-							FreeItems.getInstance().clear();
-						}
-					}
-				}
-
-				// if a line is being rubber-banded, check for auto
-				// straightening
-				anchor(FreeItems.getInstance());
-				FreeItems.getInstance().clear();
-				updateCursor();
-				_offX = _offY = 0;
-				return;
+				IndirectMouseActions.getInstance().getAnchorFreeItemsAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 			}
 			// otherwise if the user is pointing at something, pick it up unless shift is down
@@ -1095,132 +1580,10 @@
 				}
 			}
-
-			// BROOK: WIDGET RECTANGLES DONT ALLOW DISCONNECTION
-			if (clicked instanceof Line && !(clicked instanceof WidgetEdge)) {
-				// Check if within 20% of the end of the line
-				Line l = (Line) clicked;
-				Item toDisconnect = l.getEndPointToDisconnect(_lastMouseClick
-						.getX(), _lastMouseClick.getY());
-
-				if (toDisconnect == null) {
-					pickup(clicked);
-				} else {
-					if (toDisconnect.getHighlightMode() == Item.HighlightMode.Normal) {
-						DisplayIO.setCursorPosition(toDisconnect.getPosition(),
-								false);
-						pickup(toDisconnect);
-					} else {
-						List<Line> lines = toDisconnect.getLines();
-						// This is to remove constraints from single lines
-						// with constraints...
-						// ie. partially deleted rectangles
-						if (lines.size() == 1) {
-							toDisconnect.removeAllConstraints();
-
-							DisplayIO.setCursorPosition(toDisconnect
-									.getPosition(), false);
-							// This is to ensure the selected mode will be set
-							// to Normal rather than disconnect when the line is
-							// anchored
-							toDisconnect
-									.setHighlightMode(Item.HighlightMode.Normal);
-							pickup(toDisconnect);
-						} else {
-							// If we are then detatch the line and pick up its
-							// end point...
-							Frame currentFrame = DisplayIO.getCurrentFrame();
-							Item newPoint = null;
-
-							// If the point we are disconnecting is text...
-							// Then we want to leave the text behind
-							// And disconnect a point
-							if (toDisconnect instanceof Text) {
-								newPoint = new Dot(toDisconnect.getX(),
-										toDisconnect.getY(), -1);
-								Item.DuplicateItem(toDisconnect, newPoint);
-							} else {
-								newPoint = toDisconnect.copy();
-							}
-
-							currentFrame.addItem(newPoint);
-							// remove the current item from the connected
-							// list for this item
-							l.replaceLineEnd(toDisconnect, newPoint);
-							// remove unneeded constrains
-							newPoint.removeAllConstraints();
-
-							// Set the new points mode to normal before picking
-							// it up so it will be restored correctly when
-							// anchored
-							newPoint
-									.setHighlightMode(Item.HighlightMode.Normal);
-							toDisconnect
-									.setHighlightMode(Item.HighlightMode.None);
-							DisplayIO.setCursorPosition(toDisconnect
-									.getPosition(), false);
-							pickup(newPoint);
-							ItemUtils.EnclosedCheck(toDisconnect
-									.getParentOrCurrentFrame().getItems());
-						}
-					}
-				}
-			} else {
-				if (clicked.isLineEnd()) {
-					DisplayIO.setCursorPosition(clicked.getPosition(), false);
-				}
-				pickup(clicked);
-			}
+			IndirectMouseActions.getInstance().getDetachLineAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 			// if we're inside a shape, pick it up unless shift is down
 		} else if (clickedIn != null && !isShiftDown) {
-			ArrayList<Item> toPickup = new ArrayList<Item>(clickedIn.size());
-			for (Item ip : clickedIn)
-				if (ip.hasPermission(UserAppliedPermission.full))
-					toPickup.add(ip);
-			pickup(toPickup);
-			// otherwise the user is creating a line
+			IndirectMouseActions.getInstance().getGroupPickupAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 		} else {
-			Item on = FrameUtils.onItem(DisplayIO.getCurrentFrame(), Math
-					.round(MouseX), Math.round(MouseY), true);
-			// If we have permission to copy this item then pick it up
-			if (on != null && on.isLineEnd()
-					&& on.hasPermission(UserAppliedPermission.full)) {
-				on.removeAllConstraints();
-				pickup(on);
-				return;
-			}
-
-			if (on instanceof WidgetEdge) {
-				// Don't allow the user to break widget edges.
-				// Note: had to return here because random dots would
-				// appear otherwise... cannot understand code below
-				// with create line.
-				return;
-			}
-
-			// if its on a line then split the line and put a point on it and
-			// pick that point up. Only if it is not a widget line
-			if (on instanceof Line && on.hasPermission(UserAppliedPermission.full)) {
-				Frame current = DisplayIO.getCurrentFrame();
-				// create the two endpoints
-				Line oldLine = (Line) on;
-				Item newPoint = oldLine.getStartItem().copy();
-				newPoint.setPosition(MouseX, MouseY);
-
-				Item end = oldLine.getEndItem();
-				// create the Line
-				Line newLine = new Line(newPoint, end, current.getNextItemID());
-				oldLine.replaceLineEnd(end, newPoint);
-				newPoint.removeAllConstraints();
-				pickup(newPoint);
-				// Update the stats
-				Collection<Item> created = new LinkedList<Item>();
-				created.add(newPoint);
-				created.add(newLine);
-				SessionStats.CreatedItems(newLine.getAllConnected());
-				return;
-			}
-			Line newLine = createLine();
-			SessionStats.CreatedItems(newLine.getAllConnected());
-			return;
+			IndirectMouseActions.getInstance().getNewLineAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 		}
 		SessionStats.MovedItems(FreeItems.getInstance());
@@ -1329,68 +1692,13 @@
 						|| clicked instanceof XRayable) {
 					if (isRubberBandingCorner()) {
-						// Move the cursor so that the copy is exactly the
-						// same as the shape that was anchored
-						DisplayIO.setCursorPosition(clicked.getPosition());
-						Item d = getFirstFreeLineEnd();
-						// get a copy of all enclosed items before merging
-						// lineEnds
-						Collection<Item> items = FrameUtils.getItemsEnclosedBy(
-								DisplayIO.getCurrentFrame(), d
-										.getEnclosedShape());
-						// If its not an enclosed shape then pick up the
-						// connected shape
-						if (items == null || items.size() == 0) {
-							items = d.getAllConnected();
-						} else {
-							// For some reason the item that was clicked ends up
-							// in the enclosure and needs to be removed
-							items.removeAll(clicked.getConnected());
-							// the item that was the origin of the enclosed
-							// shape used to create the enclosure does not get
-							// returned from getItemsEnclosedBy to the enclosure
-							// so it must be added
-							items.addAll(d.getConnected());
-						}
-
-						Collection<Item> toCopy = new LinkedHashSet<Item>();
-
-						for (Item ip : items) {
-							if (ip.hasPermission(UserAppliedPermission.copy))
-								toCopy.add(ip);
-						}
-						copies = copy(toCopy);
-						// Now do the merging
-						Collection<Item> remain = merge(
-								FreeItems.getInstance(), clicked);
-						// anchor the points
-						anchor(remain);
-						FreeItems.getInstance().clear();
-						pickup(copies);
+						copies = IndirectMouseActions.getInstance().getMergeGroupAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 						// line onto something
 					} else if (FreeItems.getInstance().size() == 2
 					/* && clicked instanceof XRayable */) {
-						copies = ItemUtils.UnreelLine(FreeItems.getInstance(),
-								_controlDown);
-						Collection<Item> leftOver = merge(FreeItems
-								.getInstance(), clicked);
-						anchor(leftOver);
-						if (copies == null)
-							copies = copy(FreeItems.getInstance());
-						FreeItems.getInstance().clear();
-						for (Item i : copies)
-							i.setOffset(0, 0);
-						// need to move to prevent cursor dislocation
-						move(copies);
-						pickup(copies);
-						// point onto point
+						copies = IndirectMouseActions.getInstance().getMergeTwoItemsAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 					} else if (FreeItems.getInstance().size() == 1) {
-						copies = copy(FreeItems.getInstance());
-						Collection<Item> remain = merge(copies, clicked);
-
-						// ignore items that could not be merged.
-						anchor(remain);
+						copies = IndirectMouseActions.getInstance().getMergeSingleItemAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 					} else {
-						stampItemsOnCursor(true);
-						copies = FreeItems.getInstance();
+						copies = IndirectMouseActions.getInstance().getStampAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 					}
 				} else {
@@ -1410,83 +1718,10 @@
 				// check if this is anchoring a rectangle
 				if (isRubberBandingCorner()) {
-					Item d = getFirstFreeLineEnd();
-					// anchor the points
-					anchor(FreeItems.getInstance());
-					FreeItems.getInstance().clear();
-					updateCursor();
-					// pick up a copy of all enclosed items
-					Collection<Item> enclosedItems = FrameUtils
-							.getItemsEnclosedBy(DisplayIO.getCurrentFrame(), d
-									.getEnclosedShape());
-					if (enclosedItems != null) {
-						enclosedItems.removeAll(d.getAllConnected());
-						Collection<Item> toCopy = getFullyEnclosedItems(enclosedItems);
-
-						if (toCopy.size() > 0) {
-							// Find the closest item to the mouse cursor
-							double currentX = DisplayIO.getMouseX();
-							double currentY = FrameMouseActions.getY();
-							Item closest = null;
-							double shortestDistance = Double.MAX_VALUE;
-							for (Item next : toCopy) {
-								if (next instanceof Line)
-									continue;
-								double distance = Point.distance(currentX,
-										currentY, next.getX(), next.getY());
-								if (distance < shortestDistance) {
-									shortestDistance = distance;
-									closest = next;
-								}
-							}
-							// Move the cursor to closest item
-							DisplayIO.setCursorPosition(closest.getPosition());
-							// Pickup copy of the stuff inside the rectange
-							copies = copy(toCopy);
-							pickup(copies);
-							// Remove the rectangle
-							d.getParentOrCurrentFrame().removeAllItems(
-									d.getAllConnected());
-						} else {
-							// Pick up a copy of the rectangle
-							copies = copy(d.getAllConnected());
-							pickup(copies);
-						}
-					}
+					copies = IndirectMouseActions.getInstance().getRubberBandingCornerAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 				} else {
 					if (rubberBanding()) {
-						if (clicked != null) {
-							Collection<Item> leftOver = merge(FreeItems
-									.getInstance(), clicked);
-							anchor(leftOver);
-						}
-						// This is executed when the user is putting down a line
-						// endpoint and unreeling. ie. Normal unreeling
-						copies = ItemUtils.UnreelLine(FreeItems.getInstance(),
-								_controlDown);
-
-						if (copies == null)
-							copies = copy(FreeItems.getInstance());
-						anchor(FreeItems.getInstance());
-						for (Item i : copies)
-							i.setOffset(0, 0);
-						// need to move to prevent cursor dislocation
-						move(copies);
-						pickup(copies);
+						copies = IndirectMouseActions.getInstance().getRubberBandingCopyAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 					} else if (_extrude) {
-						List<Item> originals = new ArrayList<Item>();
-						// remove any lines that dont have both endpoints
-						// floating
-						for (Item i : FreeItems.getInstance()) {
-							if (i.isFloating())
-								originals.add(i);
-						}
-						if (copies == null)
-							copies = ItemUtils.CopyItems(originals, _extrude);
-						for (Item i : copies)
-							i.setOffset(0, 0);
-						anchor(FreeItems.getInstance());
-						// Move isnt working right for extruding!!
-						// move(copies);
-						pickup(copies);
+						copies = IndirectMouseActions.getInstance().getExtrudeAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 					} else {
 						stampItemsOnCursor(true);
@@ -1516,50 +1751,10 @@
 					}
 				}
-
-				copies = ItemUtils.UnreelLine(clicked, _controlDown);
-				// Copies will NOT be null if the user right clicked on a point
-				if (copies == null) {
-					Collection<Item> originals = clicked.getConnected();
-					copies = ItemUtils.CopyItems(originals, _extrude);
-					// if this is the title of the frame, link it to the frame
-					if (originals.size() == 1 && copies.size() == 1) {
-						Item copy = copies.get(0);
-						Item original = originals.iterator().next();
-						if (original.getLink() == null
-								&& original.isFrameTitle()) {
-							// save the frame after copying
-							// i.getParent().setChanged(true);
-							copy.setLink(original.getParentOrCurrentFrame()
-									.getName());
-						}
-					}
-
-					FrameGraphics.changeHighlightMode(clicked,
-							HighlightMode.None);
-
-					if (!_extrude)
-						clearParent(copies);
-				}
 				
-				ItemUtils.Justify(copies);
-
-				pickup(copies);
+				copies = IndirectMouseActions.getInstance().getMakeCopyAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 			} else {
 				// if user is pointing in a closed shape and shift isn't down, make a copy of the items inside
 				if (clickedIn != null && !isShiftDown()) {
-					// Set the selection mode for the items that were clicked in
-					Collection<Item> enclosed = getFullyEnclosedItems(clickedIn);
-					if (enclosed.size() == 0) {
-						MessageBay
-								.displayMessage("Insufficient permission to copy items");
-					} else {
-						copies = copy(enclosed);
-						clearParent(copies);
-						ItemUtils.Justify(copies);
-						pickup(copies);
-						for (Item i : clickedIn) {
-							i.setHighlightMode(HighlightMode.None);
-						}
-					}
+					IndirectMouseActions.getInstance().getMakeGroupCopyAction().exec(new MouseInfo(clicked, clickedIn, false, false));
 					// otherwise, create a rectangle
 				} else {
@@ -1568,64 +1763,7 @@
 					// if its on a line then create a line from that line
 					if (on instanceof Line && on.hasPermission(UserAppliedPermission.full)) {
-
-						Line onLine = (Line) on;
-						Line newLine = onLine.copy();
-						Item end = newLine.getEndItem();
-						Item start = newLine.getStartItem();
-						end.setPosition(MouseX, MouseY);
-						start.setPosition(MouseX, MouseY);
-						onLine.autoArrowheadLength();
-						// anchor the start
-						anchor(start);
-						// attach the line to the cursor
-						pickup(end);
-
-						List<Item> toMerge = new LinkedList<Item>();
-						toMerge.add(newLine.getStartItem());
-						toMerge.add(newLine);
-
-						// Make sure the highlighting is shown when the end is
-						// anchored
-						end.setHighlightMode(Item.HighlightMode.Normal);
-						merge(toMerge, on);
-						// anchor(left);
-						// FreeItems.getInstance().clear();
-						FrameGraphics.Repaint();
-						updateCursor();
-						return;
+						IndirectMouseActions.getInstance().getExtendLineAction().exec(new MouseInfo(on, clickedIn, false, false));
 					}
-
-					copies = new ArrayList<Item>();
-					Item[] d = new Item[RECTANGLE_CORNERS];
-					// create dots
-					Frame current = DisplayIO.getCurrentFrame();
-					for (int i = 0; i < d.length; i++) {
-						d[i] = current.createDot();
-						copies.add(d[i]);
-					}
-
-					current.nextDot();
-
-					// create lines
-					copies.add(new Line(d[0], d[1], current.getNextItemID()));
-					copies.add(new Line(d[1], d[2], current.getNextItemID()));
-					copies.add(new Line(d[2], d[3], current.getNextItemID()));
-					copies.add(new Line(d[3], d[0], current.getNextItemID()));
-
-					new Constraint(d[0], d[1], current.getNextItemID(),
-							Constraint.HORIZONTAL);
-					new Constraint(d[2], d[3], current.getNextItemID(),
-							Constraint.HORIZONTAL);
-					new Constraint(d[1], d[2], current.getNextItemID(),
-							Constraint.VERTICAL);
-					new Constraint(d[3], d[0], current.getNextItemID(),
-							Constraint.VERTICAL);
-
-					anchor(new ArrayList<Item>(copies));
-					pickup(d[3]);
-					d[3].setHighlightMode(HighlightMode.Normal);
-
-					SessionStats.CreatedItems(copies);
-					copies.clear();
+					copies = IndirectMouseActions.getInstance().getCreateRectangleAction().exec(new MouseInfo(clicked, clickedIn, false, false));					
 				}
 			}
Index: /trunk/src/org/expeditee/gui/indirect/keyboard/IndirectKeyboardActions.java
===================================================================
--- /trunk/src/org/expeditee/gui/indirect/keyboard/IndirectKeyboardActions.java	(revision 943)
+++ /trunk/src/org/expeditee/gui/indirect/keyboard/IndirectKeyboardActions.java	(revision 943)
@@ -0,0 +1,59 @@
+package org.expeditee.gui.indirect.keyboard;
+
+public class IndirectKeyboardActions {
+
+	private enum Action {
+		//Function Keys
+		DropDown, SizeUp, SizeDown, ChangeColor, ToggleAnnotation, InsertDate, NewFrameset, ChangeFontStyle, ChangeFontFamily,
+		AudienceMode, XRayMode, Save, Refresh
+	}
+	
+	private static final int ACTIONQUANTITY = Action.values().length;
+	
+	private static IndirectKeyboardActions instance = new IndirectKeyboardActions();
+	
+	private IndirectKeyboardActions() { }
+	
+	public static IndirectKeyboardActions getInstance() { return instance; }
+	
+	public KeyboardAction[] actions = new KeyboardAction[ACTIONQUANTITY];
+	
+	public KeyboardAction getDropDownAction() { return actions[Action.DropDown.ordinal()]; }
+	public KeyboardAction setDropDownAction(final KeyboardAction action) { actions[Action.DropDown.ordinal()] = action; return action; }
+	
+	public KeyboardAction getSizeUpAction() { return actions[Action.SizeUp.ordinal()]; }
+	public KeyboardAction setSizeUpAction(final KeyboardAction action) { actions[Action.SizeUp.ordinal()] = action; return action; }
+	
+	public KeyboardAction getSizeDownAction() { return actions[Action.SizeDown.ordinal()]; }
+	public KeyboardAction setSizeDownAction(final KeyboardAction action) { actions[Action.SizeDown.ordinal()] = action; return action; }
+	
+	public KeyboardAction getChangeColorAction() { return actions[Action.ChangeColor.ordinal()]; }
+	public KeyboardAction setChangeColorAction(final KeyboardAction action) { actions[Action.ChangeColor.ordinal()] = action; return action; }
+	
+	public KeyboardAction getToggleAnnotationAction() { return actions[Action.ToggleAnnotation.ordinal()]; }
+	public KeyboardAction setToggleAnnotationAction(final KeyboardAction action) { actions[Action.ToggleAnnotation.ordinal()] = action; return action; }
+	
+	public KeyboardAction getInsertDateAction() { return actions[Action.InsertDate.ordinal()]; }
+	public KeyboardAction setInsertDateAction(final KeyboardAction action) { actions[Action.InsertDate.ordinal()] = action; return action; }
+	
+	public KeyboardAction getNewFramesetAction() { return actions[Action.NewFrameset.ordinal()]; }
+	public KeyboardAction setNewFramesetAction(final KeyboardAction action) { actions[Action.NewFrameset.ordinal()] = action; return action; }
+	
+	public KeyboardAction getChangeFontStyleAction() { return actions[Action.ChangeFontStyle.ordinal()]; }
+	public KeyboardAction setChangeFontStyleAction(final KeyboardAction action) { actions[Action.ChangeFontStyle.ordinal()] = action; return action; }
+
+	public KeyboardAction getChangeFontFamilyAction() { return actions[Action.ChangeFontFamily.ordinal()]; }
+	public KeyboardAction setChangeFontFamilyAction(final KeyboardAction action) { actions[Action.ChangeFontFamily.ordinal()] = action; return action; }
+	
+	public KeyboardAction getAudienceModeAction() { return actions[Action.AudienceMode.ordinal()]; }
+	public KeyboardAction setAudienceModeAction(final KeyboardAction action) { actions[Action.AudienceMode.ordinal()] = action; return action; }
+	
+	public KeyboardAction getXRayModeAction() { return actions[Action.XRayMode.ordinal()]; }
+	public KeyboardAction setXRayModeAction(final KeyboardAction action) { actions[Action.XRayMode.ordinal()] = action; return action; }
+	
+	public KeyboardAction getSaveAction() { return actions[Action.Save.ordinal()]; }
+	public KeyboardAction setSaveAction(final KeyboardAction action) { actions[Action.Save.ordinal()] = action; return action; }
+	
+	public KeyboardAction getRefreshAction() { return actions[Action.Refresh.ordinal()]; }
+	public KeyboardAction setRefreshAction(final KeyboardAction action) { actions[Action.Refresh.ordinal()] = action; return action; }
+}
Index: /trunk/src/org/expeditee/gui/indirect/keyboard/KeyboardAction.java
===================================================================
--- /trunk/src/org/expeditee/gui/indirect/keyboard/KeyboardAction.java	(revision 943)
+++ /trunk/src/org/expeditee/gui/indirect/keyboard/KeyboardAction.java	(revision 943)
@@ -0,0 +1,35 @@
+package org.expeditee.gui.indirect.keyboard;
+
+import java.util.Collection;
+
+import org.expeditee.gui.FunctionKey;
+import org.expeditee.items.Item;
+
+public interface KeyboardAction {
+	public void exec(final KeyboardInfo info);
+
+	public class KeyboardInfo {
+		public FunctionKey key;
+		public int repeat;
+		public boolean isShiftDown;
+		public boolean isControlDown;
+		public Collection<Item> enclosed;
+		public Item firstConnected;
+		public Collection<Item> connected;
+		public Collection<Item> lineEnds;
+
+		public KeyboardInfo(final FunctionKey key, final int repeat,
+				final boolean isShiftDown, final boolean isControlDown, final Collection<Item> enclosed, 
+				final Item firstConnected, Collection<Item> connected, Collection<Item> lineEnds) {
+			this.key = key;
+			this.repeat = repeat;
+			this.isShiftDown = isShiftDown;
+			this.isControlDown = isControlDown;
+			this.enclosed = enclosed;
+			this.firstConnected = firstConnected;
+			this.connected = connected;
+			this.lineEnds = lineEnds;
+		}
+
+	}
+}
Index: /trunk/src/org/expeditee/gui/indirect/mouse/IndirectMouseActions.java
===================================================================
--- /trunk/src/org/expeditee/gui/indirect/mouse/IndirectMouseActions.java	(revision 942)
+++ /trunk/src/org/expeditee/gui/indirect/mouse/IndirectMouseActions.java	(revision 943)
@@ -2,5 +2,16 @@
 
 public class IndirectMouseActions {
-	private static final int ACTIONQUANTITY = 100;
+	
+	private enum Action {
+		//Left Mouse
+		BACK, TDFC, FRAMENAMECLICK, FOLLOWLINK, EXECUTEACTION,
+		//Right Mouse
+		CREATERECTANGLE, EXTENDLINE, MAKEGROUPCOPY, MAKECOPY, EXTRUDE, RUBBERBANDCOPY, 
+		RUBBERBANDCORNERCOPY, STAMP, MERGESINGLE, MERGETWO, MERGEGROUP,
+		//Middle Mouse
+		NEWLINE, GROUPPICKUP, DETACHLINE, ANCHORFREEITEMS, DELETEITEMS
+	}
+	
+	private static final int ACTIONQUANTITY = Action.values().length;
 	
 	private static IndirectMouseActions instance = new IndirectMouseActions();
@@ -12,6 +23,65 @@
 	public MouseAction[] actions = new MouseAction[ACTIONQUANTITY];
 	
-	private int back = 0;
-	public MouseAction getBackAction() { return actions[back]; }
-	public MouseAction setBackAction(final MouseAction action) { actions[back] = action; return action; }
+	public MouseAction getBackAction() { return actions[Action.BACK.ordinal()]; }
+	public MouseAction setBackAction(final MouseAction action) { actions[Action.BACK.ordinal()] = action; return action; }
+
+	public MouseAction getTDFCAction() { return actions[Action.TDFC.ordinal()]; }
+	public MouseAction setTDFCAction(final MouseAction action) { actions[Action.TDFC.ordinal()] = action; return action; }
+
+	public MouseAction getRespondToFrameNameClickAction() { return actions[Action.FRAMENAMECLICK.ordinal()]; }
+	public MouseAction setRespondToFrameNameClickAction(final MouseAction action) { actions[Action.FRAMENAMECLICK.ordinal()] = action; return action; }
+
+	public MouseAction getFollowLinkAction() { return actions[Action.FOLLOWLINK.ordinal()]; }
+	public MouseAction setFollowLinkAction(final MouseAction action) { actions[Action.FOLLOWLINK.ordinal()] = action; return action; }
+
+	public MouseAction getExecuteActionAction() { return actions[Action.EXECUTEACTION.ordinal()]; }
+	public MouseAction setExecuteActionAction(final MouseAction action) { actions[Action.EXECUTEACTION.ordinal()] = action; return action; }
+
+	public MouseAction getCreateRectangleAction() { return actions[Action.CREATERECTANGLE.ordinal()]; }
+	public MouseAction setCreateRectangleAction(final MouseAction action) { actions[Action.CREATERECTANGLE.ordinal()] = action; return action; }
+
+	public MouseAction getExtendLineAction() { return actions[Action.EXTENDLINE.ordinal()]; }
+	public MouseAction setExtendLineAction(final MouseAction action) { actions[Action.EXTENDLINE.ordinal()] = action; return action; }
+
+	public MouseAction getMakeGroupCopyAction() { return actions[Action.MAKEGROUPCOPY.ordinal()]; }
+	public MouseAction setMakeGroupCopyAction(final MouseAction action) { actions[Action.MAKEGROUPCOPY.ordinal()] = action; return action; }
+
+	public MouseAction getMakeCopyAction() { return actions[Action.MAKECOPY.ordinal()]; }
+	public MouseAction setMakeCopyAction(final MouseAction action) { actions[Action.MAKECOPY.ordinal()] = action; return action; }
+	
+	public MouseAction getExtrudeAction() { return actions[Action.EXTRUDE.ordinal()]; }
+	public MouseAction setExtrudeAction(final MouseAction action) { actions[Action.EXTRUDE.ordinal()] = action; return action; }
+
+	public MouseAction getRubberBandingCopyAction() { return actions[Action.RUBBERBANDCOPY.ordinal()]; }
+	public MouseAction setRubberBandingCopyAction(final MouseAction action) { actions[Action.RUBBERBANDCOPY.ordinal()] = action; return action; }
+
+	public MouseAction getRubberBandingCornerAction() { return actions[Action.RUBBERBANDCORNERCOPY.ordinal()]; }
+	public MouseAction setRubberBandingCornerAction(final MouseAction action) { actions[Action.RUBBERBANDCORNERCOPY.ordinal()] = action; return action; }
+
+	public MouseAction getStampAction() { return actions[Action.STAMP.ordinal()]; }
+	public MouseAction setStampAction(final MouseAction action) { actions[Action.STAMP.ordinal()] = action; return action; }
+
+	public MouseAction getMergeSingleItemAction() { return actions[Action.MERGESINGLE.ordinal()]; }
+	public MouseAction setMergeSingleItemAction(final MouseAction action) { actions[Action.MERGESINGLE.ordinal()] = action; return action; }
+
+	public MouseAction getMergeTwoItemsAction() { return actions[Action.MERGETWO.ordinal()]; }
+	public MouseAction setMergeTwoItemsAction(final MouseAction action) { actions[Action.MERGETWO.ordinal()] = action; return action; }
+
+	public MouseAction getMergeGroupAction() { return actions[Action.MERGEGROUP.ordinal()]; }
+	public MouseAction setMergeGroupAction(final MouseAction action) { actions[Action.MERGEGROUP.ordinal()] = action; return action; }
+
+	public MouseAction getNewLineAction() { return actions[Action.NEWLINE.ordinal()]; }
+	public MouseAction setNewLineAction(final MouseAction action) { actions[Action.NEWLINE.ordinal()] = action; return action; }
+
+	public MouseAction getGroupPickupAction() { return actions[Action.GROUPPICKUP.ordinal()]; }
+	public MouseAction setGroupPickupAction(final MouseAction action) { actions[Action.GROUPPICKUP.ordinal()] = action; return action; }
+
+	public MouseAction getDetachLineAction() { return actions[Action.DETACHLINE.ordinal()]; }
+	public MouseAction setDetachLineAction(final MouseAction action) { actions[Action.DETACHLINE.ordinal()] = action; return action; }
+	
+	public MouseAction getAnchorFreeItemsAction() { return actions[Action.ANCHORFREEITEMS.ordinal()]; }
+	public MouseAction setAnchorFreeItemsAction(final MouseAction action) { actions[Action.ANCHORFREEITEMS.ordinal()] = action; return action; }
+
+	public MouseAction getDeleteItemsAction() { return actions[Action.DELETEITEMS.ordinal()]; }
+	public MouseAction setDeleteItemsAction(final MouseAction action) { actions[Action.DELETEITEMS.ordinal()] = action; return action; }
 }
Index: /trunk/src/org/expeditee/gui/indirect/mouse/MouseAction.java
===================================================================
--- /trunk/src/org/expeditee/gui/indirect/mouse/MouseAction.java	(revision 942)
+++ /trunk/src/org/expeditee/gui/indirect/mouse/MouseAction.java	(revision 943)
@@ -2,4 +2,5 @@
 
 import java.util.Collection;
+import java.util.List;
 
 import org.expeditee.items.Item;
@@ -7,5 +8,5 @@
 public interface MouseAction {
 	
-	public void exec(MouseInfo info);
+	public List<Item> exec(MouseInfo info);
 	
 	
