blob: c1ff0a3b2ea7adf45e3d1261dabab8d7a1c6c705 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2012 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.tests.application;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.eclipse.core.runtime.Assert;
import org.eclipse.e4.core.contexts.EclipseContextFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.services.contributions.IContributionFactory;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.internal.workbench.Activator;
import org.eclipse.e4.ui.internal.workbench.Policy;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.MApplicationElement;
import org.eclipse.e4.ui.model.application.MContribution;
import org.eclipse.e4.ui.model.application.ui.MContext;
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
import org.eclipse.e4.ui.model.application.ui.MGenericStack;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
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.advanced.MPlaceholder;
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.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.workbench.IPresentationEngine;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.emf.ecore.EObject;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
public class HeadlessContextPresentationEngine implements IPresentationEngine {
@Inject
private IEventBroker eventBroker;
@Inject
private IContributionFactory contributionFactory;
private EventHandler childHandler;
private EventHandler activeChildHandler;
private EventHandler toBeRenderedHandler;
private Map<MUIElement, List<MPlaceholder>> renderedPlaceholders = new HashMap<MUIElement, List<MPlaceholder>>();
private boolean createContributions = true;
@Inject
private EModelService modelService;
protected IEclipseContext getParentContext(MUIElement element) {
return modelService.getContainingContext(element);
}
private static void populateModelInterfaces(MContext contextModel,
IEclipseContext context, Class<?>[] interfaces) {
for (Class<?> intf : interfaces) {
Activator.trace(Policy.DEBUG_CONTEXTS,
"Adding " + intf.getName() + " for " //$NON-NLS-1$ //$NON-NLS-2$
+ contextModel.getClass().getName(), null);
context.set(intf.getName(), contextModel);
populateModelInterfaces(contextModel, context, intf.getInterfaces());
}
}
@PostConstruct
void postConstruct() {
childHandler = new EventHandler() {
public void handleEvent(Event event) {
if (UIEvents.isADD(event)) {
for (Object element : UIEvents.asIterable(event,
UIEvents.EventTags.NEW_VALUE)) {
if (element instanceof MUIElement) {
Object parent = event
.getProperty(UIEvents.EventTags.ELEMENT);
IEclipseContext parentContext = getParentContext((MUIElement) element);
if (element instanceof MContext) {
IEclipseContext context = ((MContext) element)
.getContext();
if (context != null
&& context.getParent() != parentContext) {
context.deactivate();
}
}
createGui((MUIElement) element, parent,
parentContext);
if (parent instanceof MPartStack) {
MPartStack stack = (MPartStack) parent;
List<MStackElement> children = stack
.getChildren();
MStackElement stackElement = (MStackElement) element;
if (children.size() == 1
&& stackElement.isVisible()
&& stackElement.isToBeRendered()) {
stack.setSelectedElement(stackElement);
}
}
}
}
}
}
};
eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_CHILDREN,
childHandler);
activeChildHandler = new EventHandler() {
public void handleEvent(Event event) {
Object element = event
.getProperty(UIEvents.EventTags.NEW_VALUE);
if (element instanceof MUIElement) {
Object parent = event
.getProperty(UIEvents.EventTags.ELEMENT);
if (parent instanceof MGenericStack) {
MUIElement uiElement = (MUIElement) element;
IEclipseContext parentContext = getParentContext(uiElement);
createGui(uiElement, parent, parentContext);
if (parent instanceof MPerspectiveStack) {
MPerspective perspective = (MPerspective) uiElement;
adjustPlaceholders(perspective);
parentContext.get(EPartService.class)
.switchPerspective(perspective);
}
}
}
}
};
eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT,
activeChildHandler);
toBeRenderedHandler = new EventHandler() {
public void handleEvent(Event event) {
MUIElement element = (MUIElement) event
.getProperty(UIEvents.EventTags.ELEMENT);
Boolean value = (Boolean) event
.getProperty(UIEvents.EventTags.NEW_VALUE);
if (value.booleanValue()) {
createGui(element, element.getParent(),
getParentContext(element));
} else {
removeGui(element);
}
}
};
eventBroker.subscribe(UIEvents.UIElement.TOPIC_TOBERENDERED,
toBeRenderedHandler);
}
@PreDestroy
void preDestroy() {
eventBroker.unsubscribe(childHandler);
eventBroker.unsubscribe(activeChildHandler);
eventBroker.unsubscribe(toBeRenderedHandler);
}
private void adjustPlaceholders(MUIElement element) {
if (element.isToBeRendered()) {
if (element instanceof MPlaceholder) {
MPlaceholder placeholder = (MPlaceholder) element;
MUIElement ref = placeholder.getRef();
if (ref != null) {
ref.setCurSharedRef(placeholder);
element = ref;
}
}
if (element instanceof MGenericStack<?>) {
MGenericStack<?> stack = (MGenericStack<?>) element;
Object selectedElement = stack.getSelectedElement();
if (selectedElement != null) {
adjustPlaceholders((MUIElement) selectedElement);
}
} else if (element instanceof MElementContainer<?>) {
for (Object child : ((MElementContainer<?>) element)
.getChildren()) {
adjustPlaceholders((MUIElement) child);
}
}
}
}
public void setCreateContributions(boolean createContributions) {
this.createContributions = createContributions;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.e4.ui.workbench.IPresentationEngine#createGui(org.eclipse
* .e4.ui.model.application.MUIElement, java.lang.Object)
*/
public Object createGui(MUIElement element, Object parentWidget,
IEclipseContext parentContext) {
if (!element.isToBeRendered()) {
return null;
}
MUIElement parent = element.getParent();
if (!(parent instanceof MApplication)) {
// if the element is not under the application, it should have a
// parent widget
Assert.isNotNull(parentWidget);
}
if (element.getWidget() != null) {
if (element instanceof MContext) {
IEclipseContext context = ((MContext) element).getContext();
if (context.getParent() != parentContext) {
context.setParent(parentContext);
}
}
return element.getWidget();
}
element.setRenderer(this);
Object widget = new Object();
element.setWidget(widget);
if (element instanceof MContext) {
MContext mcontext = (MContext) element;
IEclipseContext createdContext = mcontext.getContext();
if (createdContext == null) {
String contextName = element.getClass().getInterfaces()[0]
.getName() + " eclipse context"; //$NON-NLS-1$
createdContext = (parentContext != null) ? parentContext
.createChild(contextName) : EclipseContextFactory
.create(contextName);
populateModelInterfaces(mcontext, createdContext, element
.getClass().getInterfaces());
for (String variable : mcontext.getVariables()) {
createdContext.declareModifiable(variable);
}
mcontext.setContext(createdContext);
if (element instanceof MContribution && createContributions) {
MContribution contribution = (MContribution) element;
String uri = contribution.getContributionURI();
if (uri != null) {
Object clientObject = contributionFactory.create(uri,
createdContext);
contribution.setObject(clientObject);
}
}
if (parentContext != null
&& parentContext.getActiveChild() == null) {
createdContext.activate();
}
} else if (createdContext.getParent() != parentContext) {
createdContext.setParent(parentContext);
}
}
if (element instanceof MGenericStack) {
MGenericStack<?> container = (MGenericStack<?>) element;
MUIElement active = container.getSelectedElement();
if (active != null) {
createGui(active, container, getParentContext(active));
} else {
List<?> children = container.getChildren();
if (!children.isEmpty()) {
((MElementContainer) element)
.setSelectedElement((MUIElement) children.get(0));
}
}
} else if (element instanceof MElementContainer<?>) {
for (Object child : ((MElementContainer<?>) element).getChildren()) {
if (child instanceof MUIElement) {
createGui((MUIElement) child, element,
getParentContext((MUIElement) child));
if (child instanceof MContext) {
IEclipseContext childContext = ((MContext) child)
.getContext();
IEclipseContext pContext = getParentContext((MUIElement) child);
if (childContext != null
&& pContext.getActiveChild() == null) {
childContext.activate();
}
}
}
}
if (element instanceof MWindow) {
MWindow window = (MWindow) element;
for (MWindow childWindow : window.getWindows()) {
createGui(childWindow, element, window.getContext());
}
}
if (element instanceof MPerspective) {
MPerspective perspective = (MPerspective) element;
for (MWindow childWindow : perspective.getWindows()) {
createGui(childWindow, element, perspective.getContext());
}
}
} else if (element instanceof MPlaceholder) {
MPlaceholder placeholder = (MPlaceholder) element;
MUIElement ref = placeholder.getRef();
if (ref != null) {
ref.setCurSharedRef(placeholder);
ref.setToBeRendered(true);
createGui(ref);
List<MPlaceholder> placeholders = renderedPlaceholders.get(ref);
if (placeholders == null) {
placeholders = new ArrayList<MPlaceholder>();
renderedPlaceholders.put(ref, placeholders);
} else if (placeholders.contains(placeholder)) {
return null;
}
placeholders.add(placeholder);
}
}
return widget;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.e4.ui.workbench.IPresentationEngine#createGui(org.eclipse
* .e4.ui.model.application.MUIElement)
*/
public Object createGui(MUIElement element) {
MUIElement placeholder = element.getCurSharedRef();
if (placeholder != null) {
return createGui(element, placeholder.getWidget(),
getParentContext(element));
}
MUIElement parent = element.getParent();
if (parent == null) {
parent = (MUIElement) ((EObject) element).eContainer();
}
return createGui(element, parent.getWidget(), getParentContext(element));
}
public void removeGui(MUIElement element) {
if (element instanceof MElementContainer<?>) {
for (Object child : ((MElementContainer<?>) element).getChildren()) {
if (child instanceof MUIElement) {
removeGui((MUIElement) child);
}
}
}
if (element instanceof MPlaceholder) {
removePlaceholder((MPlaceholder) element);
}
if (element instanceof MContext) {
MContext mcontext = (MContext) element;
IEclipseContext context = mcontext.getContext();
if (context != null) {
IEclipseContext parentContext = context.getParent();
if (parentContext != null
&& parentContext.getActiveChild() == context) {
context.deactivate();
}
}
mcontext.setContext(null);
if (context != null) {
context.dispose();
}
}
element.setRenderer(null);
element.setWidget(null);
}
private void removePlaceholder(MPlaceholder placeholder) {
MUIElement ref = placeholder.getRef();
List<MPlaceholder> placeholders = renderedPlaceholders.get(placeholder
.getRef());
placeholders.remove(placeholder);
if (placeholders.isEmpty()) {
// no other placeholders around, unrender the element
removeGui(ref);
renderedPlaceholders.remove(ref);
} else {
IEclipseContext currentContext = modelService
.getContainingContext(placeholder);
// find another placeholder to put the element under
for (MPlaceholder other : placeholders) {
IEclipseContext newParentContext = modelService
.getContainingContext(other);
if (newParentContext != null) {
List<MContext> contextElements = modelService.findElements(
ref, null, MContext.class, null);
for (MContext contextElement : contextElements) {
IEclipseContext context = contextElement.getContext();
// this is currently pointing at the placeholder's
// containing context, reparent it
if (context.getParent() == currentContext) {
context.setParent(newParentContext);
}
}
ref.setCurSharedRef(other);
break;
}
}
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.e4.ui.workbench.IPresentationEngine#run(org.eclipse.e4.ui
* .model.application.MApplicationElement)
*/
public Object run(MApplicationElement uiRoot, IEclipseContext appContext) {
return 0;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.e4.ui.workbench.IPresentationEngine#stop()
*/
public void stop() {
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.e4.ui.workbench.IPresentationEngine#focusGui(org.eclipse.
* e4.ui.model.application.ui.MUIElement)
*/
public void focusGui(MUIElement element) {
}
}