Fix for Bug 341009 - Can't drag Outline view back to its original position. Implement the 'drag last tab == drag stack' metaphor.
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/cleanupaddon/CleanupAddon.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/cleanupaddon/CleanupAddon.java
index aa98678..63ac2a7 100644
--- a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/cleanupaddon/CleanupAddon.java
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/cleanupaddon/CleanupAddon.java
@@ -11,7 +11,6 @@
 
 package org.eclipse.e4.ui.workbench.addons.cleanupaddon;
 
-import java.util.List;
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
@@ -25,7 +24,6 @@
 import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
 import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
 import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
-import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
 import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
 import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
 import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
@@ -300,24 +298,6 @@
 	}
 
 	boolean isLastEditorStack(MUIElement element) {
-		if (!(element instanceof MPartStack))
-			return false;
-
-		// is it in the shared area?
-		MUIElement parent = element.getParent();
-		while (parent != null && !(parent instanceof MArea))
-			parent = parent.getParent();
-		if (parent == null)
-			return false;
-
-		// OK, it's in the area, is it the last TBR one ?
-		MArea area = (MArea) parent;
-		List<MPartStack> stacks = modelService.findElements(area, null, MPartStack.class, null);
-		int count = 0;
-		for (MPartStack stack : stacks) {
-			if (stack.isToBeRendered())
-				count++;
-		}
-		return count < 2;
+		return modelService.isLastEditorStack(element);
 	}
 }
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/PartDragAgent.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/PartDragAgent.java
index b860192..61f1dcf 100644
--- a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/PartDragAgent.java
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/PartDragAgent.java
@@ -12,10 +12,9 @@
 package org.eclipse.e4.ui.workbench.addons.dndaddon;
 
 import org.eclipse.e4.ui.model.application.ui.MUIElement;
-import org.eclipse.e4.ui.model.application.ui.advanced.MArea;
-import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
 import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MStackElement;
 import org.eclipse.e4.ui.widgets.CTabFolder;
 import org.eclipse.e4.ui.workbench.IPresentationEngine;
 import org.eclipse.e4.ui.workbench.modeling.EPartService;
@@ -38,43 +37,45 @@
 	 */
 	@Override
 	public MUIElement getElementToDrag(DnDInfo info) {
+		if (!(info.curElement instanceof MPartStack))
+			return null;
+
+		MPartStack stack = (MPartStack) info.curElement;
+
 		// Drag a part that is in a stack
-		if (info.curElement instanceof MPartStack
-				&& (info.itemElement instanceof MPlaceholder || info.itemElement instanceof MPart)) {
+		if (info.itemElement instanceof MStackElement) {
 			// Prevent dragging 'No Move' parts
 			if (info.itemElement.getTags().contains(IPresentationEngine.NO_MOVE))
 				return null;
 
-			dragElement = info.itemElement;
-			return info.itemElement;
+			int tbrCount = dndManager.getModelService().countRenderableChildren(stack);
+			if (tbrCount > 1 || dndManager.getModelService().isLastEditorStack(stack)) {
+				dragElement = info.itemElement;
+				return info.itemElement;
+			}
 		}
 
 		// Drag a complete stack
-		if (info.curElement instanceof MPartStack && info.itemElement == null) {
-			// Only allow a drag to start if we're a CTabFolder
-			if (!(info.curElement.getWidget() instanceof CTabFolder))
-				return null;
+		// Only allow a drag to start if we're a CTabFolder
+		if (!(stack.getWidget() instanceof CTabFolder))
+			return null;
 
-			// Only allow a drag to start if we're inside the 'tab area' of the CTF
-			CTabFolder ctf = (CTabFolder) info.curElement.getWidget();
-			Point ctfPos = ctf.getDisplay().map(null, ctf, info.cursorPos);
-			if (ctfPos.y > ctf.getTabHeight())
-				return null;
+		// Only allow a drag to start if we're inside the 'tab area' of the CTF
+		CTabFolder ctf = (CTabFolder) stack.getWidget();
+		Point ctfPos = ctf.getDisplay().map(null, ctf, info.cursorPos);
+		if (ctfPos.y > ctf.getTabHeight())
+			return null;
 
-			// Prevent dragging 'No Move' stacks
-			if (info.curElement.getTags().contains(IPresentationEngine.NO_MOVE))
-				return null;
+		// Prevent dragging 'No Move' stacks
+		if (stack.getTags().contains(IPresentationEngine.NO_MOVE))
+			return null;
 
-			// Prevent dragging the last stack out of the shared area
-			MUIElement parent = info.curElement.getParent();
-			if (parent instanceof MArea)
-				return null;
+		// Prevent dragging the last stack out of the shared area
+		if (dndManager.getModelService().isLastEditorStack(stack))
+			return null;
 
-			dragElement = info.curElement;
-			return info.curElement;
-		}
-
-		return null;
+		dragElement = info.curElement;
+		return info.curElement;
 	}
 
 	/*
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/SplitDropAgent.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/SplitDropAgent.java
index 5f9d3f8..cb3c8c2 100644
--- a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/SplitDropAgent.java
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/SplitDropAgent.java
@@ -59,20 +59,33 @@
 		if (!(dragElement instanceof MStackElement) && !(dragElement instanceof MPartStack))
 			return false;
 
-		if (!(info.curElement instanceof MStackElement))
-			return false;
+		dropStack = null;
 
-		// Detect placeholders
-		MUIElement parent = info.curElement.getParent();
-		if (info.curElement instanceof MPart && info.curElement.getCurSharedRef() != null)
-			parent = info.curElement.getCurSharedRef().getParent();
+		// Hack! allow splitting the 'empty' editor area stack
+		if (info.curElement instanceof MPartStack) {
+			MPartStack stack = (MPartStack) info.curElement;
+			if (dndManager.getModelService().isLastEditorStack(stack))
+				dropStack = stack;
+		}
 
-		if (!(parent instanceof MPartStack) || !(parent.getWidget() instanceof CTabFolder))
-			return false;
+		if (dropStack == null) {
+			if (!(info.curElement instanceof MStackElement)
+					&& !dndManager.getModelService().isLastEditorStack(info.curElement))
+				return false;
 
-		dropStack = (MPartStack) parent;
+			// Detect placeholders
+			MUIElement parent = info.curElement.getParent();
+			if (info.curElement instanceof MPart && info.curElement.getCurSharedRef() != null)
+				parent = info.curElement.getCurSharedRef().getParent();
+
+			if (!(parent instanceof MPartStack) || !(parent.getWidget() instanceof CTabFolder))
+				return false;
+
+			dropStack = (MPartStack) parent;
+		}
+
 		weight = dropStack.getContainerData();
-		dropCTF = (CTabFolder) parent.getWidget();
+		dropCTF = (CTabFolder) dropStack.getWidget();
 
 		return true;
 	}
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/StackDropAgent.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/StackDropAgent.java
index a5a34bf..9ea16ab 100644
--- a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/StackDropAgent.java
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/StackDropAgent.java
@@ -12,6 +12,7 @@
 package org.eclipse.e4.ui.workbench.addons.dndaddon;
 
 import java.util.ArrayList;
+import java.util.List;
 import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
 import org.eclipse.e4.ui.model.application.ui.MUIElement;
 import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
@@ -43,23 +44,34 @@
 
 	@Override
 	public boolean canDrop(MUIElement dragElement, DnDInfo info) {
-		if (!(dragElement instanceof MStackElement))
+		// We only except stack elements and whole stacks
+		if (!(dragElement instanceof MStackElement) && !(dragElement instanceof MPartStack))
 			return false;
 
-		if (info.curElement instanceof MPartStack
-				&& info.curElement.getWidget() instanceof CTabFolder) {
-			Rectangle areaRect = getTabAreaRect((CTabFolder) info.curElement.getWidget());
-			boolean inArea = areaRect.contains(info.cursorPos);
-			if (inArea) {
-				tabArea = areaRect;
-				dropStack = (MPartStack) info.curElement;
-				dropCTF = (CTabFolder) dropStack.getWidget();
-				createInsertRects();
-			}
-			return inArea;
-		}
+		// We have to be over a stack ourselves
+		if (!(info.curElement instanceof MPartStack))
+			return false;
 
-		return false;
+		MPartStack stack = (MPartStack) info.curElement;
+
+		// We only work for CTabFolders
+		if (!(stack.getWidget() instanceof CTabFolder))
+			return false;
+
+		// We can't drop stacks onto itself
+		if (stack == dragElement)
+			return false;
+
+		// only allow dropping into the the area
+		Rectangle areaRect = getTabAreaRect((CTabFolder) stack.getWidget());
+		boolean inArea = areaRect.contains(info.cursorPos);
+		if (inArea) {
+			tabArea = areaRect;
+			dropStack = (MPartStack) info.curElement;
+			dropCTF = (CTabFolder) dropStack.getWidget();
+			createInsertRects();
+		}
+		return inArea;
 	}
 
 	private Rectangle getTabAreaRect(CTabFolder theCTF) {
@@ -175,7 +187,7 @@
 				itemBounds = Display.getCurrent().map(dropCTF, null, itemBounds);
 				dndManager.frameRect(itemBounds);
 			} else {
-				Rectangle fr = tabArea;
+				Rectangle fr = new Rectangle(tabArea.x, tabArea.y, tabArea.width, tabArea.height);
 				fr.width = 2;
 				dndManager.frameRect(fr);
 			}
@@ -197,7 +209,7 @@
 	private void dock(MUIElement dragElement, int dropIndex) {
 		// Adjust the index if necessary
 		int elementIndex = dropStack.getChildren().indexOf(dragElement);
-		if (elementIndex != -1) {
+		if (elementIndex != -1 && !(dragElement instanceof MPartStack)) {
 			// Get the index of this CTF entry
 			Control dragCtrl = (Control) dragElement.getWidget();
 			for (CTabItem cti : dropCTF.getItems()) {
@@ -209,13 +221,31 @@
 			}
 		}
 
-		if (dragElement.getParent() != null)
-			dragElement.getParent().getChildren().remove(dragElement);
-		if (dropIndex >= 0 && dropIndex < dropStack.getChildren().size())
-			dropStack.getChildren().add(dropIndex, (MStackElement) dragElement);
-		else
-			dropStack.getChildren().add((MStackElement) dragElement);
-		dropStack.setSelectedElement((MStackElement) dragElement);
+		if (dragElement instanceof MStackElement) {
+			if (dragElement.getParent() != null)
+				dragElement.getParent().getChildren().remove(dragElement);
+			if (dropIndex >= 0 && dropIndex < dropStack.getChildren().size())
+				dropStack.getChildren().add(dropIndex, (MStackElement) dragElement);
+			else
+				dropStack.getChildren().add((MStackElement) dragElement);
+
+			// (Re)active the element being dropped
+			dropStack.setSelectedElement((MStackElement) dragElement);
+		} else {
+			MPartStack stack = (MPartStack) dragElement;
+			MStackElement curSel = stack.getSelectedElement();
+			List<MStackElement> kids = stack.getChildren();
+			while (kids.size() > 0) {
+				MStackElement lastChild = kids.remove(kids.size() - 1);
+				if (dropIndex >= 0 && dropIndex < dropStack.getChildren().size())
+					dropStack.getChildren().add(dropIndex, lastChild);
+				else
+					dropStack.getChildren().add(lastChild);
+			}
+
+			// (Re)active the element being dropped
+			dropStack.setSelectedElement(curSel);
+		}
 	}
 
 	/**
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SashRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SashRenderer.java
index 684ab92..d9b1239 100644
--- a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SashRenderer.java
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SashRenderer.java
@@ -33,7 +33,7 @@
 	private IEventBroker eventBroker;
 
 	private static final int UNDEFINED_WEIGHT = -1;
-	private static final int DEFAULT_WEIGHT = 100;
+	private static final int DEFAULT_WEIGHT = 5000;
 
 	private EventHandler sashOrientationHandler;
 	private EventHandler sashWeightHandler;
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java
index e5b2364..29712bf 100644
--- a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java
@@ -261,7 +261,7 @@
 						}
 					}
 				} else {
-					if (renderer != null)
+					if (renderer != null && added.isToBeRendered())
 						renderer.childRendered(changedElement, added);
 				}
 
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java
index e61d786..4ed4a70 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java
@@ -943,4 +943,33 @@
 		}
 		parent.setToBeRendered(false);
 	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.e4.ui.workbench.modeling.EModelService#isLastEditorStack(org.eclipse.e4.ui.model
+	 * .application.ui.MUIElement)
+	 */
+	public boolean isLastEditorStack(MUIElement stack) {
+		if (!(stack instanceof MPartStack))
+			return false;
+
+		// is it in the shared area?
+		MUIElement parent = stack.getParent();
+		while (parent != null && !(parent instanceof MArea))
+			parent = parent.getParent();
+		if (parent == null)
+			return false;
+
+		// OK, it's in the area, is it the last TBR one ?
+		MArea area = (MArea) parent;
+		List<MPartStack> stacks = findElements(area, null, MPartStack.class, null);
+		int count = 0;
+		for (MPartStack aStack : stacks) {
+			if (aStack.isToBeRendered())
+				count++;
+		}
+		return count < 2;
+	}
 }
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EModelService.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EModelService.java
index 8b25baf..66090cb 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EModelService.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EModelService.java
@@ -417,4 +417,15 @@
 	 *            perspectives in the window are checked
 	 */
 	public void hideLocalPlaceholders(MWindow window, MPerspective perspective);
+
+	/**
+	 * Returns <code>true</code> iff the supplied element represents the single visible element in
+	 * the shared area. This method is used to test for this condition since (by convention) there
+	 * must be at least one stack in the shared area at all times.
+	 * 
+	 * @param stack
+	 *            The element to test
+	 * @return <code>true</code> iff the element is the last visible stack
+	 */
+	public boolean isLastEditorStack(MUIElement stack);
 }