Index: /trunk/src/org/apollo/ApolloGestureActions.java
===================================================================
--- /trunk/src/org/apollo/ApolloGestureActions.java	(revision 1522)
+++ /trunk/src/org/apollo/ApolloGestureActions.java	(revision 1523)
@@ -16,4 +16,5 @@
 import org.expeditee.core.Dimension;
 import org.expeditee.core.Point;
+import org.expeditee.core.bounds.AxisAlignedBoxBounds;
 import org.expeditee.gio.EcosystemManager;
 import org.expeditee.gio.gesture.Gesture;
@@ -203,5 +204,8 @@
 					@Override
 					public void exec(Gesture gesture) {
-						mouseMoved(gesture.getData().getPosition());
+						//mouseMoved(gesture.getData().getPosition());
+						if (isSnapOn()) {
+							snapFreeTracks(gesture.getData().getPosition());
+						}
 					}
 				});
@@ -481,123 +485,94 @@
 	private static final int COARSE_Y_PLACEMENT_TOLERANCE = 20;
 
-	public void mouseMoved(Point to) {
-		boolean forwareToExpeditee = true;
-
-		if (isYAxisRestictionOn() && !FreeItems.getInstance().isEmpty()) {
-
-			// Restrict movement of free items to Y-Axis only
-			forwareToExpeditee = false;
-
-			int smallestY = FreeItems.getInstance().get(0).getY();
-
-			for (Item i : FreeItems.getInstance()) {
-				if (i.getY() < smallestY) {
-					smallestY = i.getY();
-				}
-			}
-
-			for (Item i : FreeItems.getInstance()) {
-				i.setY(to.getY() + (i.getY() - smallestY));
-			}
-
-		} else if (isSnapOn() && !FreeItems.getInstance().isEmpty()) {
-
-			// Couse movement of free items: Restraining left-most pixel in items
-			// to the closest anchored track widgets x position.
-
-			Frame currentFrame = DisplayController.getCurrentFrame();
-			if (currentFrame != null) {
-
-				// Search all anchored track x positions for the current frame
-				List<Widget> widgets = currentFrame.getInteractiveWidgets();
-
-				int closestXPosition = -1;
-				int closestYPosition = -1;
-				int closestXDistance = -1;
-				int closestYDistance = -1;
-
-				for (Widget iw : widgets) {
-
-					if (iw instanceof SampledTrack || iw instanceof LinkedTrack) {
-
-						// Determine TOP-LEFT Snapping
-						int xDistance = Math.abs(to.getX() - iw.getX());
-						if (closestXDistance < 0 || xDistance < closestXDistance) {
-							closestXDistance = xDistance;
-							closestXPosition = iw.getX();
-						}
-
-						int yDistance = Math.abs(to.getY() - iw.getY());
-						if (closestYDistance < 0 || yDistance < closestYDistance) {
-							closestYDistance = yDistance;
-							closestYPosition = iw.getY();
-						}
-
-						// Determine BOTTOM-RIGHT Snapping
-						xDistance = Math.abs(to.getX() - (iw.getX() + iw.getWidth()));
-						if (closestXDistance < 0 || xDistance < closestXDistance) {
-							closestXDistance = xDistance;
-							closestXPosition = iw.getX() + iw.getWidth();
-						}
-
-						yDistance = Math.abs(to.getY() - (iw.getY() + iw.getHeight()));
-						if (closestYDistance < 0 || yDistance < closestYDistance) {
-							closestYDistance = yDistance;
-							closestYPosition = iw.getY() + iw.getHeight();
-						}
-					}
-
-				}
-
-				// Determine top-left position of free items
-				int smallestX = FreeItems.getInstance().get(0).getX();
-				int smallestY = FreeItems.getInstance().get(0).getY();
-				for (Item i : FreeItems.getInstance()) {
-					if (i.getX() < smallestX) {
-						smallestX = i.getX();
-					}
-					if (i.getY() < smallestY) {
-						smallestY = i.getY();
-					}
-				}
-
-				for (Item i : FreeItems.getInstance()) {
-
-					int x;
-					int y;
-
-					if (closestXDistance > 0 && closestXDistance < COARSE_X_PLACEMENT_TOLERANCE) {
-						x = closestXPosition + (i.getX() - smallestX);
-					} else {
-						x = to.getX() + (i.getX() - smallestX);
-					}
-
-					if (closestYDistance > 0 && closestYDistance < COARSE_Y_PLACEMENT_TOLERANCE) {
-						y = closestYPosition + (i.getY() - smallestY);
-					} else {
-						y = to.getY() + (i.getY() - smallestY);
-					}
-
-					i.setPosition(x, y);
-
-				}
-
-				forwareToExpeditee = false;
-
-			}
-
+	private void snapFreeTracks(Point position) {
+		// Get Apollo widgets that are attached to cursor
+		FreeItems freeItems = FreeItems.getInstance();
+		List<Widget> freeWidgets = ItemUtils.extractWidgets(freeItems);
+		List<Widget> freeApolloWidgets = new ArrayList<Widget>();
+		for (Widget w: freeWidgets) {
+			if (w instanceof SampledTrack || w instanceof LinkedTrack) { freeApolloWidgets.add(w); }
+		}
+		if (freeApolloWidgets.isEmpty()) { return; }
+		
+		// Get Apollo widgets that are on frame
+		Frame currentFrame = DisplayController.getCurrentFrame();
+		List<Widget> interactiveWidgets = currentFrame.getInteractiveWidgets();
+		List<Widget> anchoredApolloWidgets = new ArrayList<Widget>();
+		for (Widget w: interactiveWidgets) {
+			if (w instanceof SampledTrack || w instanceof LinkedTrack) { anchoredApolloWidgets.add(w); }
 		} 
-
-		// Expeditees frame mouse actions uses an offset and fights over free-item
-		// movement if it listens to the mouse event router... therefore add an extra
-		// layer to avoid this... otherwise auto-aligned items jitter like crazy while
-		// moving the cursus
-		// if (forwareToExpeditee) {
-		// FrameMouseActions.getInstance().mouseMoved(e);
-		// } else {
-		// FrameGraphics.refresh(true);
-		// }
-	}
-
+		if (anchoredApolloWidgets.isEmpty()) { return; }
+		
+		// Snap the first freeApolloWidget.
+		// Snap the freeApolloWidgets, using the first as a guidepost.
+		Widget toSnap = freeApolloWidgets.remove(0);
+		Point origin = new Point(0,0);
+		Point canditateDistance = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
+		Widget anchoredWidgetToSnapTo = null;
+		AxisAlignedBoxBounds freeWidgetBounds = toSnap.getBounds();
+		for (Widget anchoredWidget: anchoredApolloWidgets) {
+			AxisAlignedBoxBounds anchoredWidgetBounds = anchoredWidget.getBounds();
+			Point distance = freeWidgetBounds.distanceFrom(anchoredWidgetBounds);
+			if (distance.getDistanceTo(origin) < canditateDistance.getDistanceTo(origin)) {
+				canditateDistance = distance;
+				anchoredWidgetToSnapTo = anchoredWidget;
+			}
+		}
+		AxisAlignedBoxBounds anchoredWidgetToSnapToBounds = anchoredWidgetToSnapTo.getBounds();
+		
+		int xDist = anchoredWidgetToSnapToBounds.getCentreX() < freeWidgetBounds.getCentreX() ? canditateDistance.getX() : -canditateDistance.getX();
+		int yDist = anchoredWidgetToSnapToBounds.getCentreY() < freeWidgetBounds.getCentreY() ? canditateDistance.getY() : -canditateDistance.getY();
+
+		int direction = -1;
+		int tlX = toSnap.getX();
+		int tlY = toSnap.getY();
+		if ((xDist > 0 && yDist == 0) || (xDist == 0 && yDist == 0)) {
+			tlX = anchoredWidgetToSnapTo.getBounds().getMaxX();
+			tlY = anchoredWidgetToSnapTo.getBounds().getMinY();
+			direction = 0;
+		} else if (xDist < 0 && yDist == 0) {
+			tlX = anchoredWidgetToSnapTo.getBounds().getMinX() - toSnap.getWidth();
+			tlY = anchoredWidgetToSnapTo.getBounds().getMinY();
+			direction = 1;
+		} else if (yDist > 0 && xDist == 0) {
+			tlX = anchoredWidgetToSnapTo.getBounds().getMinX();
+			tlY = anchoredWidgetToSnapTo.getBounds().getMaxY();
+			direction = 2;
+		} else if (yDist < 0 && xDist == 0) {
+			tlX = anchoredWidgetToSnapTo.getBounds().getMinX();
+			tlY = anchoredWidgetToSnapTo.getBounds().getMinY() - toSnap.getHeight();
+			direction = 3;
+		}
+		toSnap.setPosition(tlX, tlY);
+		
+		for (Widget toSnapNext: freeApolloWidgets) {
+			switch (direction) {
+			case 0:
+				tlX = toSnap.getBounds().getMaxX();
+				tlY = toSnap.getBounds().getMinY();
+				toSnapNext.setPosition(tlX, tlY);
+				break;
+			case 1:
+				tlX = toSnap.getBounds().getMinX() - toSnapNext.getWidth();
+				tlY = toSnap.getBounds().getMinY();
+				toSnapNext.setPosition(tlX, tlY);
+				break;
+			case 2:
+				tlX = toSnap.getBounds().getMinX();
+				tlY = toSnap.getBounds().getMaxX();
+				toSnapNext.setPosition(tlX, tlY);
+				break;
+			case 3:
+				tlX = toSnap.getBounds().getMinX();
+				tlY = toSnap.getBounds().getMinY() - toSnapNext.getHeight();
+				toSnapNext.setPosition(tlX, tlY);
+				break;
+			default:
+				break;
+			}
+			toSnap = toSnapNext;
+		}
+	}
+	
 	/**
 	 * @return True if the user is restricting movement on the y-axis only
Index: /trunk/src/org/expeditee/core/bounds/AxisAlignedBoxBounds.java
===================================================================
--- /trunk/src/org/expeditee/core/bounds/AxisAlignedBoxBounds.java	(revision 1522)
+++ /trunk/src/org/expeditee/core/bounds/AxisAlignedBoxBounds.java	(revision 1523)
@@ -5,5 +5,4 @@
 import org.expeditee.core.Line;
 import org.expeditee.core.Point;
-import org.expeditee.gui.DisplayController;
 
 /**
@@ -347,5 +346,40 @@
 		}
 	}
-	
+
+	public Point distanceFrom(AxisAlignedBoxBounds other) {
+		boolean left = other.getMaxX() < this.getMinX();
+		boolean right = this.getMaxX() < other.getMinX();
+		boolean top = this.getMaxY() < other.getMinY();
+		boolean bottom = other.getMaxY() < this.getMinY();
+
+		if (top && left) {
+			Point thisP = new Point(this.getMinX(), this.getMaxY());
+			Point otherP = new Point(other.getMaxX(), other.getMinY());
+			return Point.difference(thisP, otherP);
+		} else if (left && bottom) {
+			Point thisP = new Point(this.getMinX(), this.getMinY());
+			Point otherP = new Point(other.getMaxX(), other.getMaxY());
+			return Point.difference(thisP, otherP);
+		} else if (bottom && right) {
+			Point thisP = new Point(this.getMaxX(), this.getMinY());
+			Point otherP = new Point(other.getMinX(), other.getMaxY());
+			return Point.difference(thisP, otherP);
+		} else if (right && top) {
+			Point thisP = new Point(this.getMaxX(), this.getMaxY());
+			Point otherP = new Point(other.getMinX(), other.getMinY());
+			return Point.difference(thisP, otherP);
+		} else if (left) {
+			return new Point(this.getMinX() - other.getMaxX(), 0);
+		} else if (right) {
+			return new Point(other.getMinX() - this.getMaxX(), 0);
+		} else if (top) {
+			return new Point(0, other.getMinY() - this.getMaxY());
+		} else if (bottom) {
+			return new Point(0, this.getMinY() - other.getMaxY());
+		} else {
+			return new Point(0, 0);
+		}
+	}
+
 	/** Gets the bounds that is linearly-interpolated between the two given bounds. */
 	public static AxisAlignedBoxBounds lerp(AxisAlignedBoxBounds a, AxisAlignedBoxBounds b, float t)
