/******************************************************************************* * Copyright (c) 2008, 2016 BestSolution.at 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: * Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation * IBM Corporation - initial API and implementation * Christian Georgi (SAP) - Bug 432480 * Lars Vogel <Lars.Vogel@vogella.com> - Bug 472654, 393171, 508450 ******************************************************************************/ package org.eclipse.e4.ui.internal.workbench; import java.net.URI; import java.util.Hashtable; import java.util.List; import java.util.UUID; import org.eclipse.e4.core.commands.ExpressionContext; import org.eclipse.e4.core.contexts.ContextInjectionFactory; 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.log.Logger; import org.eclipse.e4.ui.model.application.MApplication; import org.eclipse.e4.ui.model.application.MApplicationElement; import org.eclipse.e4.ui.model.application.ui.MContext; import org.eclipse.e4.ui.workbench.IPresentationEngine; import org.eclipse.e4.ui.workbench.IWorkbench; import org.eclipse.e4.ui.workbench.UIEvents; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.osgi.service.datalocation.Location; import org.osgi.framework.ServiceRegistration; /** * Default implementation of {@link IWorkbench} */ public class E4Workbench implements IWorkbench { /** * The argument for the locale active shell <br> * <br> * Value is: <code>localActiveShell</code> */ public static final String LOCAL_ACTIVE_SHELL = "localActiveShell"; //$NON-NLS-1$ /** * The argument for the {@link URI} of the initial workbench model <br> * <br> * Value is: <code>initialWorkbenchModelURI</code> */ public static final String INITIAL_WORKBENCH_MODEL_URI = "initialWorkbenchModelURI"; //$NON-NLS-1$ /** * The argument for the {@link Location} of the running instance <br> * <br> * Value is: <code>instanceLocation</code> */ public static final String INSTANCE_LOCATION = "instanceLocation"; //$NON-NLS-1$ /** * The argument for the renderer factory to use <br> * <br> * Value is: <code>rendererFactoryUri</code> */ public static final String RENDERER_FACTORY_URI = "rendererFactoryUri"; //$NON-NLS-1$ /** * The argument for setting RTL mode <br> * <br> * Value is: <code>dir</code> */ public static final String RTL_MODE = "dir"; //$NON-NLS-1$ /** * The argument for the perspective to activate <br> * <br> * Value is: <code>perspectiveId</code> */ public static final String FORCED_PERSPECTIVE_ID = "forcedPerspetiveId"; //$NON-NLS-1$ public static final String NO_SAVED_MODEL_FOUND = "NO_SAVED_MODEL_FOUND"; //$NON-NLS-1$ /** * The argument for the whether to forcefully show the location in the window title (set on the * command line)<br> * <br> * Value is: <code>forcedShowLocation</code> */ public static final String FORCED_SHOW_LOCATION = "forcedShowLocation"; //$NON-NLS-1$ private final String id; private ServiceRegistration<?> osgiRegistration; IEclipseContext appContext; IPresentationEngine renderer; MApplication appModel = null; private UIEventPublisher uiEventPublisher; private boolean restart; /** * @return the {@link IEclipseContext} for the main application */ public IEclipseContext getContext() { return appContext; } /** * Constructor * * @param uiRoot * the root UI element * @param applicationContext * the root context */ public E4Workbench(MApplicationElement uiRoot, IEclipseContext applicationContext) { id = createId(); appContext = applicationContext; appContext.set(IWorkbench.class.getName(), this); if (uiRoot instanceof MApplication) { appModel = (MApplication) uiRoot; } if (uiRoot instanceof MApplication) { init((MApplication) uiRoot); } uiEventPublisher = new UIEventPublisher(appContext); appContext.set(UIEventPublisher.class, uiEventPublisher); ((Notifier) uiRoot).eAdapters().add(uiEventPublisher); Hashtable<String, Object> properties = new Hashtable<>(); properties.put("id", getId()); //$NON-NLS-1$ osgiRegistration = Activator.getDefault().getContext() .registerService(IWorkbench.class.getName(), this, properties); ContextInjectionFactory.make(PartOnTopManager.class, appContext); } @Override public final String getId() { return id; } protected String createId() { return UUID.randomUUID().toString(); } /** * @param uiRoot */ public void createAndRunUI(MApplicationElement uiRoot) { // Has someone already created one ? instantiateRenderer(); if (renderer != null) { renderer.run(uiRoot, appContext); } } /** * */ public void instantiateRenderer() { renderer = appContext.get(IPresentationEngine.class); if (renderer == null) { String presentationURI = (String) appContext.get(IWorkbench.PRESENTATION_URI_ARG); if (presentationURI != null) { IContributionFactory factory = appContext.get(IContributionFactory.class); renderer = (IPresentationEngine) factory.create(presentationURI, appContext); appContext.set(IPresentationEngine.class, renderer); } if (renderer == null) { Logger logger = appContext.get(Logger.class); logger.error("Failed to create the presentation engine for URI: " + presentationURI); //$NON-NLS-1$ } } } private void init(MApplication appElement) { if (Policy.DEBUG_WORKBENCH) { Activator.trace(Policy.DEBUG_WORKBENCH_FLAG, "init() workbench", null); //$NON-NLS-1$ } IEclipseContext context = appElement.getContext(); if (context != null) { context.set(ExpressionContext.ALLOW_ACTIVATION, Boolean.TRUE); } } @Override public boolean close() { // Fire an E4 lifecycle notification UIEvents.publishEvent(UIEvents.UILifeCycle.APP_SHUTDOWN_STARTED, appModel); if (renderer != null) { renderer.stop(); } if (uiEventPublisher != null && appModel != null) { ((Notifier) appModel).eAdapters().remove(uiEventPublisher); uiEventPublisher = null; } if (osgiRegistration != null) { osgiRegistration.unregister(); osgiRegistration = null; } return true; } @Override public boolean restart() { this.restart = true; return close(); } /** * @return <code>true</code> when the workbench should be restarted */ public boolean isRestart() { return restart; } /** * @return a context that can be used to lookup OSGi services */ public static IEclipseContext getServiceContext() { return EclipseContextFactory.getServiceContext(Activator.getDefault().getContext()); } @Override public MApplication getApplication() { return appModel; } /** * Create the context chain. It both creates the chain for the current model, and adds eAdapters * so it can add new contexts when new model items are added. * * @param parentContext * The parent context * @param contextModel * needs a context created * @return a chained {@link IEclipseContext} */ public static IEclipseContext initializeContext(IEclipseContext parentContext, MContext contextModel) { final IEclipseContext context; if (contextModel.getContext() != null) { context = contextModel.getContext(); } else { context = parentContext.createChild("PartContext(" + contextModel + ')'); //$NON-NLS-1$ } if (Policy.DEBUG_CONTEXTS) { Activator.trace(Policy.DEBUG_CONTEXTS_FLAG, "initializeContext(" //$NON-NLS-1$ + parentContext.toString() + ", " + contextModel + ")", null); //$NON-NLS-1$ //$NON-NLS-2$ } // fill in the interfaces, so MContributedPart.class.getName() will // return the model element, for example. ContributionsAnalyzer.populateModelInterfaces(contextModel, context, contextModel .getClass().getInterfaces()); // declares modifiable variables from the model List<String> containedProperties = contextModel.getVariables(); for (String name : containedProperties) { context.declareModifiable(name); } contextModel.setContext(context); return context; } }