| /******************************************************************************* |
| * 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) { |
| } |
| } |