Fix for Bug 351366 - Allow the hosting of Views and Editors
independent of the presentation
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Application.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Application.java
index 7c625f3..ff74f98 100644
--- a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Application.java
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Application.java
@@ -46,6 +46,7 @@
 import org.eclipse.e4.ui.internal.workbench.DefaultLoggerProvider;
 import org.eclipse.e4.ui.internal.workbench.E4Workbench;
 import org.eclipse.e4.ui.internal.workbench.ExceptionHandler;
+import org.eclipse.e4.ui.internal.workbench.ModelServiceImpl;
 import org.eclipse.e4.ui.internal.workbench.PlaceholderResolver;
 import org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory;
 import org.eclipse.e4.ui.internal.workbench.ResourceHandler;
@@ -468,6 +469,8 @@
 				.set(Logger.class.getName(), ContextInjectionFactory.make(
 						WorkbenchLogger.class, appContext));
 
+		appContext.set(EModelService.class, new ModelServiceImpl(appContext));
+
 		appContext.set(EPlaceholderResolver.class, new PlaceholderResolver());
 
 		// translation
diff --git a/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF
index 30b1814..7e7aa9b 100644
--- a/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF
@@ -41,7 +41,7 @@
    org.eclipse.e4.ui.workbench.renderers.swt,
    org.eclipse.ui.workbench"
 Bundle-Activator: org.eclipse.e4.ui.internal.workbench.Activator
-Service-Component: OSGI-INF/progress.xml, OSGI-INF/partService.xml, OSGI-INF/modelService.xml, OSGI-INF/selectionLookup.xml, OSGI-INF/selectionService.xml
+Service-Component: OSGI-INF/progress.xml, OSGI-INF/partService.xml, OSGI-INF/selectionLookup.xml, OSGI-INF/selectionService.xml
 Import-Package: com.ibm.icu.text;version="3.8.1",
  javax.annotation;version="1.0.0",
  javax.inject;version="1.0.0"
diff --git a/bundles/org.eclipse.e4.ui.workbench/OSGI-INF/modelService.xml b/bundles/org.eclipse.e4.ui.workbench/OSGI-INF/modelService.xml
deleted file mode 100644
index 4fe21da..0000000
--- a/bundles/org.eclipse.e4.ui.workbench/OSGI-INF/modelService.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.e4.ui.workbench.modelService">
-   <implementation class="org.eclipse.e4.ui.internal.workbench.ModelServiceCreationFunction"/>
-   <service>
-      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
-   </service>
-   <property name="service.context.key" type="String" value="org.eclipse.e4.ui.workbench.modeling.EModelService"/>
-</scr:component>
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceCreationFunction.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceCreationFunction.java
deleted file mode 100644
index a5ed9ba..0000000
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceCreationFunction.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- ******************************************************************************/
-
-package org.eclipse.e4.ui.internal.workbench;
-
-import org.eclipse.e4.core.contexts.ContextFunction;
-import org.eclipse.e4.core.contexts.ContextInjectionFactory;
-import org.eclipse.e4.core.contexts.IEclipseContext;
-
-/**
- *
- */
-public class ModelServiceCreationFunction extends ContextFunction {
-
-	@Override
-	public Object compute(IEclipseContext context) {
-		return ContextInjectionFactory.make(ModelServiceImpl.class, context);
-	}
-
-}
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 bd41c8b..316a9de 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
@@ -15,6 +15,7 @@
 import java.util.List;
 import org.eclipse.core.runtime.Assert;
 import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.events.IEventBroker;
 import org.eclipse.e4.ui.model.application.MApplication;
 import org.eclipse.e4.ui.model.application.MApplicationElement;
 import org.eclipse.e4.ui.model.application.ui.MElementContainer;
@@ -41,16 +42,56 @@
 import org.eclipse.e4.ui.model.internal.ModelUtils;
 import org.eclipse.e4.ui.workbench.IPresentationEngine;
 import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
 import org.eclipse.e4.ui.workbench.modeling.EModelService;
 import org.eclipse.e4.ui.workbench.modeling.EPartService;
 import org.eclipse.e4.ui.workbench.modeling.EPlaceholderResolver;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
 
 /**
  *
  */
 public class ModelServiceImpl implements EModelService {
+	private static String HOSTED_ELEMENT = "HostedElement"; //$NON-NLS-1$
+
+	// Cleans up after a hosted element is disposed
+	private EventHandler hostedElementHandler = new EventHandler() {
+
+		public void handleEvent(Event event) {
+			final MUIElement changedElement = (MUIElement) event.getProperty(EventTags.ELEMENT);
+			if (!changedElement.getTags().contains(HOSTED_ELEMENT))
+				return;
+
+			if (changedElement.getWidget() != null)
+				return;
+
+			EObject eObj = (EObject) changedElement;
+			if (!(eObj.eContainer() instanceof MWindow))
+				return;
+
+			MWindow hostingWindow = (MWindow) eObj.eContainer();
+			hostingWindow.getSharedElements().remove(changedElement);
+			changedElement.getTags().remove(HOSTED_ELEMENT);
+		}
+	};
+
+	/**
+	 * This is a singleton service. One instance is used throughout the running application
+	 * 
+	 * @param appContext
+	 *            The applicationContext to get teh eventBroker from
+	 */
+	public ModelServiceImpl(IEclipseContext appContext) {
+		if (appContext == null)
+			return;
+
+		IEventBroker eventBroker = appContext.get(IEventBroker.class);
+		eventBroker.subscribe(UIEvents.UIElement.TOPIC_WIDGET, hostedElementHandler);
+	}
+
 	/**
 	 * Determine if the element passes the matching test for all non-null parameters.
 	 * 
@@ -984,4 +1025,39 @@
 		}
 		return count < 2 && stack.isToBeRendered();
 	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.e4.ui.workbench.modeling.EModelService#hostElement(org.eclipse.e4.ui.model.
+	 * application.ui.MUIElement, org.eclipse.e4.ui.model.application.ui.basic.MWindow,
+	 * java.lang.Object, org.eclipse.e4.core.contexts.IEclipseContext)
+	 */
+	public void hostElement(MUIElement element, MWindow hostWindow, Object uiContainer,
+			IEclipseContext hostContext) {
+		// This is subtle; unless the element is hooked into the model it won't fire events
+		hostWindow.getSharedElements().add(element);
+		element.getTags().add(HOSTED_ELEMENT);
+
+		IPresentationEngine renderer = hostWindow.getContext().get(IPresentationEngine.class);
+		renderer.createGui(element, uiContainer, hostContext);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.e4.ui.workbench.modeling.EModelService#isHostedElement(org.eclipse.e4.ui.model
+	 * .application.ui.MUIElement, org.eclipse.e4.ui.model.application.ui.basic.MWindow)
+	 */
+	public boolean isHostedElement(MUIElement element, MWindow hostWindow) {
+		MUIElement curElement = element;
+		while (curElement != null && !curElement.getTags().contains(HOSTED_ELEMENT))
+			curElement = curElement.getParent();
+
+		if (curElement == null)
+			return false;
+
+		return hostWindow.getSharedElements().contains(curElement);
+	}
 }
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 9795220..556c3bf 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
@@ -468,4 +468,34 @@
 	 * @return <code>true</code> iff the element is the last visible stack
 	 */
 	public boolean isLastEditorStack(MUIElement stack);
+
+	/**
+	 * Allows an element to be rendered in an arbitrary UI container (I.e. SWT Composite).
+	 * 
+	 * @param element
+	 *            The element to be rendered.
+	 * @param hostWindow
+	 *            The MWindow the element is being hosted under. Must be non-nulland rendered.
+	 * @param uiContainer
+	 *            The UI container acting as the rendered element's parent. Must be non-null.
+	 * @param hostContext
+	 *            The IEclipseContext to use for hosting the element. Must be non-null.
+	 */
+	public void hostElement(MUIElement element, MWindow hostWindow, Object uiContainer,
+			IEclipseContext hostContext);
+
+	/**
+	 * Tests whether the given element is being 'hosted'. This method is used to allow UI Elements
+	 * to act as if they are contained within a given MWindow even though the element is not
+	 * actually structurally contained in that window's UI Model.
+	 * 
+	 * @param element
+	 *            The element to test. Must be non-null.
+	 * @param hostWindow
+	 *            The window to test the element against. Must be non-null.
+	 * 
+	 * @return <code>true</code> iff the given element or one of its ancestors is currently being
+	 *         hosted in the given MWindow.
+	 */
+	public boolean isHostedElement(MUIElement element, MWindow hostWindow);
 }