0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.ui.internal;
0011:
0012: import java.io.BufferedInputStream;
0013: import java.io.BufferedReader;
0014: import java.io.File;
0015: import java.io.FileInputStream;
0016: import java.io.FileOutputStream;
0017: import java.io.IOException;
0018: import java.io.InputStream;
0019: import java.io.InputStreamReader;
0020: import java.io.OutputStreamWriter;
0021: import java.lang.reflect.Method;
0022: import java.util.ArrayList;
0023: import java.util.Arrays;
0024: import java.util.Dictionary;
0025: import java.util.HashSet;
0026: import java.util.Hashtable;
0027: import java.util.List;
0028: import java.util.Set;
0029:
0030: import org.eclipse.core.commands.Command;
0031: import org.eclipse.core.commands.CommandManager;
0032: import org.eclipse.core.commands.common.EventManager;
0033: import org.eclipse.core.commands.contexts.ContextManager;
0034: import org.eclipse.core.databinding.observable.Realm;
0035: import org.eclipse.core.runtime.Assert;
0036: import org.eclipse.core.runtime.IAdaptable;
0037: import org.eclipse.core.runtime.IExtension;
0038: import org.eclipse.core.runtime.IExtensionDelta;
0039: import org.eclipse.core.runtime.IExtensionPoint;
0040: import org.eclipse.core.runtime.IExtensionRegistry;
0041: import org.eclipse.core.runtime.IPath;
0042: import org.eclipse.core.runtime.IProduct;
0043: import org.eclipse.core.runtime.IProgressMonitor;
0044: import org.eclipse.core.runtime.IRegistryChangeEvent;
0045: import org.eclipse.core.runtime.IRegistryChangeListener;
0046: import org.eclipse.core.runtime.IStatus;
0047: import org.eclipse.core.runtime.ListenerList;
0048: import org.eclipse.core.runtime.MultiStatus;
0049: import org.eclipse.core.runtime.Platform;
0050: import org.eclipse.core.runtime.SafeRunner;
0051: import org.eclipse.core.runtime.Status;
0052: import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
0053: import org.eclipse.core.runtime.jobs.Job;
0054: import org.eclipse.jface.action.ActionContributionItem;
0055: import org.eclipse.jface.action.ExternalActionManager;
0056: import org.eclipse.jface.action.IAction;
0057: import org.eclipse.jface.action.MenuManager;
0058: import org.eclipse.jface.action.ExternalActionManager.CommandCallback;
0059: import org.eclipse.jface.action.ExternalActionManager.IActiveChecker;
0060: import org.eclipse.jface.bindings.BindingManager;
0061: import org.eclipse.jface.bindings.BindingManagerEvent;
0062: import org.eclipse.jface.bindings.IBindingManagerListener;
0063: import org.eclipse.jface.databinding.swt.SWTObservables;
0064: import org.eclipse.jface.dialogs.ErrorDialog;
0065: import org.eclipse.jface.dialogs.IDialogConstants;
0066: import org.eclipse.jface.dialogs.MessageDialog;
0067: import org.eclipse.jface.dialogs.ProgressMonitorDialog;
0068: import org.eclipse.jface.operation.IRunnableContext;
0069: import org.eclipse.jface.operation.ModalContext;
0070: import org.eclipse.jface.preference.IPreferenceStore;
0071: import org.eclipse.jface.preference.PreferenceManager;
0072: import org.eclipse.jface.resource.ImageDescriptor;
0073: import org.eclipse.jface.util.OpenStrategy;
0074: import org.eclipse.jface.util.SafeRunnable;
0075: import org.eclipse.jface.viewers.ISelection;
0076: import org.eclipse.jface.window.IShellProvider;
0077: import org.eclipse.jface.window.Window;
0078: import org.eclipse.jface.window.WindowManager;
0079: import org.eclipse.osgi.service.runnable.StartupMonitor;
0080: import org.eclipse.osgi.util.NLS;
0081: import org.eclipse.swt.SWT;
0082: import org.eclipse.swt.custom.BusyIndicator;
0083: import org.eclipse.swt.graphics.DeviceData;
0084: import org.eclipse.swt.graphics.Image;
0085: import org.eclipse.swt.widgets.Control;
0086: import org.eclipse.swt.widgets.Display;
0087: import org.eclipse.swt.widgets.Event;
0088: import org.eclipse.swt.widgets.Listener;
0089: import org.eclipse.swt.widgets.Shell;
0090: import org.eclipse.ui.IDecoratorManager;
0091: import org.eclipse.ui.IEditorPart;
0092: import org.eclipse.ui.IEditorRegistry;
0093: import org.eclipse.ui.IElementFactory;
0094: import org.eclipse.ui.ILocalWorkingSetManager;
0095: import org.eclipse.ui.IMemento;
0096: import org.eclipse.ui.IPerspectiveDescriptor;
0097: import org.eclipse.ui.IPerspectiveRegistry;
0098: import org.eclipse.ui.ISaveableFilter;
0099: import org.eclipse.ui.ISaveablePart;
0100: import org.eclipse.ui.ISaveablesLifecycleListener;
0101: import org.eclipse.ui.ISharedImages;
0102: import org.eclipse.ui.IWindowListener;
0103: import org.eclipse.ui.IWorkbench;
0104: import org.eclipse.ui.IWorkbenchListener;
0105: import org.eclipse.ui.IWorkbenchPage;
0106: import org.eclipse.ui.IWorkbenchPart;
0107: import org.eclipse.ui.IWorkbenchPreferenceConstants;
0108: import org.eclipse.ui.IWorkbenchWindow;
0109: import org.eclipse.ui.IWorkingSetManager;
0110: import org.eclipse.ui.PlatformUI;
0111: import org.eclipse.ui.Saveable;
0112: import org.eclipse.ui.WorkbenchException;
0113: import org.eclipse.ui.XMLMemento;
0114: import org.eclipse.ui.activities.IWorkbenchActivitySupport;
0115: import org.eclipse.ui.application.IWorkbenchConfigurer;
0116: import org.eclipse.ui.application.WorkbenchAdvisor;
0117: import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
0118: import org.eclipse.ui.commands.ICommandService;
0119: import org.eclipse.ui.commands.IWorkbenchCommandSupport;
0120: import org.eclipse.ui.contexts.IContextService;
0121: import org.eclipse.ui.contexts.IWorkbenchContextSupport;
0122: import org.eclipse.ui.handlers.IHandlerService;
0123: import org.eclipse.ui.help.IWorkbenchHelpSystem;
0124: import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
0125: import org.eclipse.ui.internal.activities.ws.WorkbenchActivitySupport;
0126: import org.eclipse.ui.internal.browser.WorkbenchBrowserSupport;
0127: import org.eclipse.ui.internal.commands.CommandImageManager;
0128: import org.eclipse.ui.internal.commands.CommandImageService;
0129: import org.eclipse.ui.internal.commands.CommandService;
0130: import org.eclipse.ui.internal.commands.ICommandImageService;
0131: import org.eclipse.ui.internal.commands.WorkbenchCommandSupport;
0132: import org.eclipse.ui.internal.contexts.ActiveContextSourceProvider;
0133: import org.eclipse.ui.internal.contexts.ContextService;
0134: import org.eclipse.ui.internal.contexts.WorkbenchContextSupport;
0135: import org.eclipse.ui.internal.dialogs.PropertyPageContributorManager;
0136: import org.eclipse.ui.internal.handlers.HandlerService;
0137: import org.eclipse.ui.internal.help.WorkbenchHelpSystem;
0138: import org.eclipse.ui.internal.intro.IIntroRegistry;
0139: import org.eclipse.ui.internal.intro.IntroDescriptor;
0140: import org.eclipse.ui.internal.keys.BindingService;
0141: import org.eclipse.ui.internal.menus.FocusControlSourceProvider;
0142: import org.eclipse.ui.internal.menus.WorkbenchMenuService;
0143: import org.eclipse.ui.internal.misc.Policy;
0144: import org.eclipse.ui.internal.misc.StatusUtil;
0145: import org.eclipse.ui.internal.misc.UIStats;
0146: import org.eclipse.ui.internal.progress.ProgressManager;
0147: import org.eclipse.ui.internal.registry.IActionSetDescriptor;
0148: import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
0149: import org.eclipse.ui.internal.registry.UIExtensionTracker;
0150: import org.eclipse.ui.internal.services.ActionSetSourceProvider;
0151: import org.eclipse.ui.internal.services.ActivePartSourceProvider;
0152: import org.eclipse.ui.internal.services.ActiveShellSourceProvider;
0153: import org.eclipse.ui.internal.services.CurrentSelectionSourceProvider;
0154: import org.eclipse.ui.internal.services.EvaluationService;
0155: import org.eclipse.ui.internal.services.IEvaluationService;
0156: import org.eclipse.ui.internal.services.ISourceProviderService;
0157: import org.eclipse.ui.internal.services.MenuSourceProvider;
0158: import org.eclipse.ui.internal.services.ServiceLocator;
0159: import org.eclipse.ui.internal.services.SourceProviderService;
0160: import org.eclipse.ui.internal.splash.EclipseSplashHandler;
0161: import org.eclipse.ui.internal.splash.SplashHandlerFactory;
0162: import org.eclipse.ui.internal.testing.WorkbenchTestable;
0163: import org.eclipse.ui.internal.themes.ColorDefinition;
0164: import org.eclipse.ui.internal.themes.FontDefinition;
0165: import org.eclipse.ui.internal.themes.ThemeElementHelper;
0166: import org.eclipse.ui.internal.themes.WorkbenchThemeManager;
0167: import org.eclipse.ui.internal.tweaklets.GrabFocus;
0168: import org.eclipse.ui.internal.tweaklets.Tweaklets;
0169: import org.eclipse.ui.internal.util.PrefUtil;
0170: import org.eclipse.ui.internal.util.Util;
0171: import org.eclipse.ui.intro.IIntroManager;
0172: import org.eclipse.ui.keys.IBindingService;
0173: import org.eclipse.ui.menus.IMenuService;
0174: import org.eclipse.ui.operations.IWorkbenchOperationSupport;
0175: import org.eclipse.ui.progress.IProgressService;
0176: import org.eclipse.ui.services.IDisposable;
0177: import org.eclipse.ui.splash.AbstractSplashHandler;
0178: import org.eclipse.ui.statushandlers.StatusManager;
0179: import org.eclipse.ui.swt.IFocusService;
0180: import org.eclipse.ui.themes.IThemeManager;
0181: import org.eclipse.ui.views.IViewRegistry;
0182: import org.eclipse.ui.wizards.IWizardRegistry;
0183: import org.osgi.framework.BundleContext;
0184: import org.osgi.framework.BundleEvent;
0185: import org.osgi.framework.Constants;
0186: import org.osgi.framework.ServiceRegistration;
0187: import org.osgi.framework.SynchronousBundleListener;
0188:
0189: /**
0190: * The workbench class represents the top of the Eclipse user interface. Its
0191: * primary responsability is the management of workbench windows, dialogs,
0192: * wizards, and other workbench-related windows.
0193: * <p>
0194: * Note that any code that is run during the creation of a workbench instance
0195: * should not required access to the display.
0196: * </p>
0197: * <p>
0198: * Note that this internal class changed significantly between 2.1 and 3.0.
0199: * Applications that used to define subclasses of this internal class need to be
0200: * rewritten to use the new workbench advisor API.
0201: * </p>
0202: */
0203: public final class Workbench extends EventManager implements IWorkbench {
0204:
0205: private final class StartupProgressBundleListener implements
0206: SynchronousBundleListener {
0207:
0208: private final IProgressMonitor progressMonitor;
0209:
0210: private final int maximumProgressCount;
0211:
0212: // stack of names of bundles currently starting
0213: private final List starting;
0214:
0215: StartupProgressBundleListener(IProgressMonitor progressMonitor,
0216: int maximumProgressCount) {
0217: super ();
0218: this .progressMonitor = progressMonitor;
0219: this .maximumProgressCount = maximumProgressCount;
0220: this .starting = new ArrayList();
0221: }
0222:
0223: public void bundleChanged(BundleEvent event) {
0224: int eventType = event.getType();
0225: String bundleName;
0226:
0227: synchronized (this ) {
0228: if (eventType == BundleEvent.STARTING) {
0229: starting.add(bundleName = event.getBundle()
0230: .getSymbolicName());
0231: } else if (eventType == BundleEvent.STARTED) {
0232: progressCount++;
0233: if (progressCount <= maximumProgressCount) {
0234: progressMonitor.worked(1);
0235: }
0236: int index = starting.lastIndexOf(event.getBundle()
0237: .getSymbolicName());
0238: if (index >= 0) {
0239: starting.remove(index);
0240: }
0241: if (index != starting.size()) {
0242: return; // not currently displayed
0243: }
0244: bundleName = index == 0 ? null : (String) starting
0245: .get(index - 1);
0246: } else {
0247: return; // uninteresting event
0248: }
0249: }
0250:
0251: String taskName;
0252:
0253: if (bundleName == null) {
0254: taskName = WorkbenchMessages.Startup_Loading_Workbench;
0255: } else {
0256: taskName = NLS.bind(WorkbenchMessages.Startup_Loading,
0257: bundleName);
0258: }
0259:
0260: progressMonitor.subTask(taskName);
0261: }
0262: }
0263:
0264: /**
0265: * Family for the early startup job.
0266: */
0267: public static final String EARLY_STARTUP_FAMILY = "earlyStartup"; //$NON-NLS-1$
0268:
0269: static final String VERSION_STRING[] = { "0.046", "2.0" }; //$NON-NLS-1$ //$NON-NLS-2$
0270:
0271: static final String DEFAULT_WORKBENCH_STATE_FILENAME = "workbench.xml"; //$NON-NLS-1$
0272:
0273: /**
0274: * Holds onto the only instance of Workbench.
0275: */
0276: private static Workbench instance;
0277:
0278: /**
0279: * The testable object facade.
0280: *
0281: * @since 3.0
0282: */
0283: private static WorkbenchTestable testableObject;
0284:
0285: /**
0286: * Signals that the workbench should create a splash implementation when
0287: * instantiated. Intial value is <code>true</code>.
0288: *
0289: * @since 3.3
0290: */
0291: private static boolean createSplash = true;
0292:
0293: /**
0294: * The splash handler.
0295: */
0296: private static AbstractSplashHandler splash;
0297:
0298: /**
0299: * The display used for all UI interactions with this workbench.
0300: *
0301: * @since 3.0
0302: */
0303: private Display display;
0304:
0305: private WindowManager windowManager;
0306:
0307: private WorkbenchWindow activatedWindow;
0308:
0309: private EditorHistory editorHistory;
0310:
0311: private boolean runEventLoop = true;
0312:
0313: private boolean isStarting = true;
0314:
0315: private boolean isClosing = false;
0316:
0317: /**
0318: * PlatformUI return code (as opposed to IPlatformRunnable return code).
0319: */
0320: private int returnCode = PlatformUI.RETURN_UNSTARTABLE;
0321:
0322: /**
0323: * Advisor providing application-specific configuration and customization of
0324: * the workbench.
0325: *
0326: * @since 3.0
0327: */
0328: private WorkbenchAdvisor advisor;
0329:
0330: /**
0331: * Object for configuring the workbench. Lazily initialized to an instance
0332: * unique to the workbench instance.
0333: *
0334: * @since 3.0
0335: */
0336: private WorkbenchConfigurer workbenchConfigurer;
0337:
0338: // for dynamic UI
0339: /**
0340: * ExtensionEventHandler handles extension life-cycle events.
0341: */
0342: private ExtensionEventHandler extensionEventHandler;
0343:
0344: /**
0345: * A count of how many large updates are going on. This tracks nesting of
0346: * requests to disable services during a large update -- similar to the
0347: * <code>setRedraw</code> functionality on <code>Control</code>. When
0348: * this value becomes greater than zero, services are disabled. When this
0349: * value becomes zero, services are enabled. Please see
0350: * <code>largeUpdateStart()</code> and <code>largeUpdateEnd()</code>.
0351: */
0352: private int largeUpdates = 0;
0353:
0354: /**
0355: * The service locator maintained by the workbench. These services are
0356: * initialized during workbench during the <code>init</code> method.
0357: */
0358: private final ServiceLocator serviceLocator = new ServiceLocator();
0359:
0360: /**
0361: * A count of how many plug-ins were loaded while restoring the workbench
0362: * state. Initially -1 for unknown number.
0363: */
0364: private int progressCount = -1;
0365:
0366: /**
0367: * A field to hold the workbench windows that have been restored. In the
0368: * event that not all windows have been restored, this field allows the
0369: * openWindowsAfterRestore method to open some windows.
0370: */
0371: private WorkbenchWindow[] createdWindows;
0372:
0373: /**
0374: * Listener list for registered IWorkbenchListeners .
0375: */
0376: private ListenerList workbenchListeners = new ListenerList(
0377: ListenerList.IDENTITY);
0378:
0379: /**
0380: * Creates a new workbench.
0381: *
0382: * @param display
0383: * the display to be used for all UI interactions with the
0384: * workbench
0385: * @param advisor
0386: * the application-specific advisor that configures and
0387: * specializes this workbench instance
0388: * @since 3.0
0389: */
0390: private Workbench(Display display, WorkbenchAdvisor advisor) {
0391: super ();
0392: StartupThreading.setWorkbench(this );
0393: if (instance != null && instance.isRunning()) {
0394: throw new IllegalStateException(
0395: WorkbenchMessages.Workbench_CreatingWorkbenchTwice);
0396: }
0397: Assert.isNotNull(display);
0398: Assert.isNotNull(advisor);
0399: this .advisor = advisor;
0400: this .display = display;
0401: Workbench.instance = this ;
0402:
0403: // for dynamic UI [This seems to be for everything that isn't handled by
0404: // some
0405: // subclass of RegistryManager. I think that when an extension is moved
0406: // to the
0407: // RegistryManager implementation, then it should be removed from the
0408: // list in
0409: // ExtensionEventHandler#appear.
0410: // I've found that the new wizard extension in particular is a poor
0411: // choice to
0412: // use as an example, since the result of reading the registry is not
0413: // cached
0414: // -- so it is re-read each time. The only real contribution of this
0415: // dialog is
0416: // to show the user a nice dialog describing the addition.]
0417: extensionEventHandler = new ExtensionEventHandler(this );
0418: Platform.getExtensionRegistry().addRegistryChangeListener(
0419: extensionEventHandler);
0420: }
0421:
0422: /**
0423: * Returns the one and only instance of the workbench, if there is one.
0424: *
0425: * @return the workbench, or <code>null</code> if the workbench has not
0426: * been created, or has been created and already completed
0427: */
0428: public static final Workbench getInstance() {
0429: return instance;
0430: }
0431:
0432: /**
0433: * Creates the workbench and associates it with the the given display and
0434: * workbench advisor, and runs the workbench UI. This entails processing and
0435: * dispatching events until the workbench is closed or restarted.
0436: * <p>
0437: * This method is intended to be called by <code>PlatformUI</code>. Fails
0438: * if the workbench UI has already been created.
0439: * </p>
0440: * <p>
0441: * The display passed in must be the default display.
0442: * </p>
0443: *
0444: * @param display
0445: * the display to be used for all UI interactions with the
0446: * workbench
0447: * @param advisor
0448: * the application-specific advisor that configures and
0449: * specializes the workbench
0450: * @return return code {@link PlatformUI#RETURN_OK RETURN_OK}for normal
0451: * exit; {@link PlatformUI#RETURN_RESTART RETURN_RESTART}if the
0452: * workbench was terminated with a call to
0453: * {@link IWorkbench#restart IWorkbench.restart}; other values
0454: * reserved for future use
0455: */
0456: public static final int createAndRunWorkbench(
0457: final Display display, final WorkbenchAdvisor advisor) {
0458: final int[] returnCode = new int[1];
0459: Realm.runWithDefault(SWTObservables.getRealm(display),
0460: new Runnable() {
0461: public void run() {
0462: // create the workbench instance
0463: Workbench workbench = new Workbench(display,
0464: advisor);
0465: // run the workbench event loop
0466: returnCode[0] = workbench.runUI();
0467: }
0468: });
0469: return returnCode[0];
0470: }
0471:
0472: /**
0473: * Creates the <code>Display</code> to be used by the workbench.
0474: *
0475: * @return the display
0476: */
0477: public static Display createDisplay() {
0478: // setup the application name used by SWT to lookup resources on some
0479: // platforms
0480: String applicationName = WorkbenchPlugin.getDefault()
0481: .getAppName();
0482: if (applicationName != null) {
0483: Display.setAppName(applicationName);
0484: }
0485:
0486: // create the display
0487: Display newDisplay = Display.getCurrent();
0488: if (newDisplay == null) {
0489: if (Policy.DEBUG_SWT_GRAPHICS || Policy.DEBUG_SWT_DEBUG) {
0490: DeviceData data = new DeviceData();
0491: if (Policy.DEBUG_SWT_GRAPHICS) {
0492: data.tracking = true;
0493: }
0494: if (Policy.DEBUG_SWT_DEBUG) {
0495: data.debug = true;
0496: }
0497: newDisplay = new Display(data);
0498: } else {
0499: newDisplay = new Display();
0500: }
0501: }
0502:
0503: // workaround for 1GEZ9UR and 1GF07HN
0504: newDisplay.setWarnings(false);
0505:
0506: // Set the priority higher than normal so as to be higher
0507: // than the JobManager.
0508: Thread.currentThread()
0509: .setPriority(
0510: Math.min(Thread.MAX_PRIORITY,
0511: Thread.NORM_PRIORITY + 1));
0512:
0513: initializeImages();
0514:
0515: return newDisplay;
0516: }
0517:
0518: /**
0519: * Create the splash wrapper and set it to work.
0520: *
0521: * @since 3.3
0522: */
0523: private void createSplashWrapper() {
0524: final Display display = getDisplay();
0525: String splashLoc = System
0526: .getProperty("org.eclipse.equinox.launcher.splash.location"); //$NON-NLS-1$
0527: final Image background = loadImage(splashLoc);
0528:
0529: SafeRunnable run = new SafeRunnable() {
0530:
0531: public void run() throws Exception {
0532: String splashHandle = System
0533: .getProperty("org.eclipse.equinox.launcher.splash.handle"); //$NON-NLS-1$
0534: if (splashHandle == null) {
0535: createSplash = false;
0536: return;
0537: }
0538:
0539: // create the splash
0540: getSplash();
0541: if (splash == null) {
0542: createSplash = false;
0543: return;
0544: }
0545:
0546: Shell splashShell = splash.getSplash();
0547: if (splashShell == null) {
0548: // look for the 32 bit internal_new shell method
0549: try {
0550: Method method = Shell.class
0551: .getMethod(
0552: "internal_new", new Class[] { Display.class, int.class }); //$NON-NLS-1$
0553: // we're on a 32 bit platform so invoke it with splash
0554: // handle as an int
0555: splashShell = (Shell) method.invoke(null,
0556: new Object[] { display,
0557: new Integer(splashHandle) });
0558: } catch (NoSuchMethodException e) {
0559: // look for the 64 bit internal_new shell method
0560: try {
0561: Method method = Shell.class
0562: .getMethod(
0563: "internal_new", new Class[] { Display.class, long.class }); //$NON-NLS-1$
0564:
0565: // we're on a 64 bit platform so invoke it with a long
0566: splashShell = (Shell) method.invoke(null,
0567: new Object[] { display,
0568: new Long(splashHandle) });
0569: } catch (NoSuchMethodException e2) {
0570: // cant find either method - don't do anything.
0571: }
0572: }
0573:
0574: if (splashShell == null)
0575: return;
0576: if (background != null)
0577: splashShell.setBackgroundImage(background);
0578: }
0579:
0580: Dictionary properties = new Hashtable();
0581: properties.put(Constants.SERVICE_RANKING, new Integer(
0582: Integer.MAX_VALUE));
0583: BundleContext context = WorkbenchPlugin.getDefault()
0584: .getBundleContext();
0585: final ServiceRegistration registration[] = new ServiceRegistration[1];
0586: StartupMonitor startupMonitor = new StartupMonitor() {
0587:
0588: public void applicationRunning() {
0589: splash.dispose();
0590: if (background != null)
0591: background.dispose();
0592: registration[0].unregister(); // unregister ourself
0593: }
0594:
0595: public void update() {
0596: // do nothing - we come into the picture far too late
0597: // for this to be relevant
0598: }
0599: };
0600: registration[0] = context.registerService(
0601: StartupMonitor.class.getName(), startupMonitor,
0602: properties);
0603:
0604: splash.init(splashShell);
0605: }
0606:
0607: /* (non-Javadoc)
0608: * @see org.eclipse.jface.util.SafeRunnable#handleException(java.lang.Throwable)
0609: */
0610: public void handleException(Throwable e) {
0611: StatusManager.getManager().handle(
0612: StatusUtil.newStatus(
0613: WorkbenchPlugin.PI_WORKBENCH,
0614: "Could not instantiate splash", e)); //$NON-NLS-1$
0615: createSplash = false;
0616: splash = null;
0617: if (background != null)
0618: background.dispose();
0619:
0620: }
0621: };
0622: SafeRunner.run(run);
0623: }
0624:
0625: /**
0626: * Load an image from a filesystem path.
0627: *
0628: * @param splashLoc the location to load from
0629: * @return the image or <code>null</code>
0630: * @since 3.3
0631: */
0632: private Image loadImage(String splashLoc) {
0633: Image background = null;
0634: if (splashLoc != null) {
0635: try {
0636: InputStream input = new BufferedInputStream(
0637: new FileInputStream(splashLoc));
0638: background = new Image(display, input);
0639: } catch (IOException e) {
0640: StatusManager.getManager().handle(
0641: StatusUtil.newStatus(
0642: WorkbenchPlugin.PI_WORKBENCH, e));
0643: }
0644: }
0645: return background;
0646: }
0647:
0648: /**
0649: * Return the splash handler for this application. If none is specifically
0650: * provided the default Eclipse implementation is returned.
0651: *
0652: * @return the splash handler for this application or <code>null</code>
0653: * @since 3.3
0654: */
0655: private static AbstractSplashHandler getSplash() {
0656: if (!createSplash)
0657: return null;
0658:
0659: if (splash == null) {
0660:
0661: IProduct product = Platform.getProduct();
0662: if (product != null)
0663: splash = SplashHandlerFactory
0664: .findSplashHandlerFor(product);
0665:
0666: if (splash == null)
0667: splash = new EclipseSplashHandler();
0668: }
0669: return splash;
0670: }
0671:
0672: /**
0673: * Returns the testable object facade, for use by the test harness.
0674: *
0675: * @return the testable object facade
0676: * @since 3.0
0677: */
0678: public static WorkbenchTestable getWorkbenchTestable() {
0679: if (testableObject == null) {
0680: testableObject = new WorkbenchTestable();
0681: }
0682: return testableObject;
0683: }
0684:
0685: /*
0686: * (non-Javadoc) Method declared on IWorkbench.
0687: *
0688: * @since 3.2
0689: */
0690: public void addWorkbenchListener(IWorkbenchListener listener) {
0691: workbenchListeners.add(listener);
0692: }
0693:
0694: /*
0695: * (non-Javadoc) Method declared on IWorkbench.
0696: *
0697: * @since 3.2
0698: */
0699: public void removeWorkbenchListener(IWorkbenchListener listener) {
0700: workbenchListeners.remove(listener);
0701: }
0702:
0703: /**
0704: * Fire workbench preShutdown event, stopping at the first one to veto
0705: *
0706: * @param forced
0707: * flag indicating whether the shutdown is being forced
0708: * @return <code>true</code> to allow the workbench to proceed with
0709: * shutdown, <code>false</code> to veto a non-forced shutdown
0710: * @since 3.2
0711: */
0712: boolean firePreShutdown(final boolean forced) {
0713: Object list[] = workbenchListeners.getListeners();
0714: for (int i = 0; i < list.length; i++) {
0715: final IWorkbenchListener l = (IWorkbenchListener) list[i];
0716: final boolean[] result = new boolean[] { false };
0717: SafeRunnable.run(new SafeRunnable() {
0718: public void run() {
0719: result[0] = l.preShutdown(Workbench.this , forced);
0720: }
0721: });
0722: if (!result[0]) {
0723: return false;
0724: }
0725: }
0726: return true;
0727: }
0728:
0729: /**
0730: * Fire workbench postShutdown event.
0731: *
0732: * @since 3.2
0733: */
0734: void firePostShutdown() {
0735: Object list[] = workbenchListeners.getListeners();
0736: for (int i = 0; i < list.length; i++) {
0737: final IWorkbenchListener l = (IWorkbenchListener) list[i];
0738: SafeRunnable.run(new SafeRunnable() {
0739: public void run() {
0740: l.postShutdown(Workbench.this );
0741: }
0742: });
0743: }
0744: }
0745:
0746: /*
0747: * (non-Javadoc) Method declared on IWorkbench.
0748: */
0749: public void addWindowListener(IWindowListener l) {
0750: addListenerObject(l);
0751: }
0752:
0753: /*
0754: * (non-Javadoc) Method declared on IWorkbench.
0755: */
0756: public void removeWindowListener(IWindowListener l) {
0757: removeListenerObject(l);
0758: }
0759:
0760: /**
0761: * Fire window opened event.
0762: *
0763: * @param window
0764: * The window which just opened; should not be <code>null</code>.
0765: */
0766: protected void fireWindowOpened(final IWorkbenchWindow window) {
0767: Object list[] = getListeners();
0768: for (int i = 0; i < list.length; i++) {
0769: final IWindowListener l = (IWindowListener) list[i];
0770: SafeRunner.run(new SafeRunnable() {
0771: public void run() {
0772: l.windowOpened(window);
0773: }
0774: });
0775: }
0776: }
0777:
0778: /**
0779: * Fire window closed event.
0780: *
0781: * @param window
0782: * The window which just closed; should not be <code>null</code>.
0783: */
0784: protected void fireWindowClosed(final IWorkbenchWindow window) {
0785: if (activatedWindow == window) {
0786: // Do not hang onto it so it can be GC'ed
0787: activatedWindow = null;
0788: }
0789:
0790: Object list[] = getListeners();
0791: for (int i = 0; i < list.length; i++) {
0792: final IWindowListener l = (IWindowListener) list[i];
0793: SafeRunner.run(new SafeRunnable() {
0794: public void run() {
0795: l.windowClosed(window);
0796: }
0797: });
0798: }
0799: }
0800:
0801: /**
0802: * Fire window activated event.
0803: *
0804: * @param window
0805: * The window which was just activated; should not be
0806: * <code>null</code>.
0807: */
0808: protected void fireWindowActivated(final IWorkbenchWindow window) {
0809: Object list[] = getListeners();
0810: for (int i = 0; i < list.length; i++) {
0811: final IWindowListener l = (IWindowListener) list[i];
0812: SafeRunner.run(new SafeRunnable() {
0813: public void run() {
0814: l.windowActivated(window);
0815: }
0816: });
0817: }
0818: }
0819:
0820: /**
0821: * Fire window deactivated event.
0822: *
0823: * @param window
0824: * The window which was just deactivated; should not be
0825: * <code>null</code>.
0826: */
0827: protected void fireWindowDeactivated(final IWorkbenchWindow window) {
0828: Object list[] = getListeners();
0829: for (int i = 0; i < list.length; i++) {
0830: final IWindowListener l = (IWindowListener) list[i];
0831: SafeRunner.run(new SafeRunnable() {
0832: public void run() {
0833: l.windowDeactivated(window);
0834: }
0835: });
0836: }
0837: }
0838:
0839: /**
0840: * Closes the workbench. Assumes that the busy cursor is active.
0841: *
0842: * @param force
0843: * true if the close is mandatory, and false if the close is
0844: * allowed to fail
0845: * @return true if the close succeeded, and false otherwise
0846: */
0847: private boolean busyClose(final boolean force) {
0848:
0849: // notify the advisor of preShutdown and allow it to veto if not forced
0850: isClosing = advisor.preShutdown();
0851: if (!force && !isClosing) {
0852: return false;
0853: }
0854:
0855: // notify regular workbench clients of preShutdown and allow them to
0856: // veto if not forced
0857: isClosing = firePreShutdown(force);
0858: if (!force && !isClosing) {
0859: return false;
0860: }
0861:
0862: // save any open editors if they are dirty
0863: isClosing = saveAllEditors(!force);
0864: if (!force && !isClosing) {
0865: return false;
0866: }
0867:
0868: boolean closeEditors = !force
0869: && PrefUtil
0870: .getAPIPreferenceStore()
0871: .getBoolean(
0872: IWorkbenchPreferenceConstants.CLOSE_EDITORS_ON_EXIT);
0873: if (closeEditors) {
0874: SafeRunner.run(new SafeRunnable() {
0875: public void run() {
0876: IWorkbenchWindow windows[] = getWorkbenchWindows();
0877: for (int i = 0; i < windows.length; i++) {
0878: IWorkbenchPage pages[] = windows[i].getPages();
0879: for (int j = 0; j < pages.length; j++) {
0880: isClosing = isClosing
0881: && pages[j].closeAllEditors(false);
0882: }
0883: }
0884: }
0885: });
0886: if (!force && !isClosing) {
0887: return false;
0888: }
0889: }
0890:
0891: if (getWorkbenchConfigurer().getSaveAndRestore()) {
0892: SafeRunner.run(new SafeRunnable() {
0893: public void run() {
0894: XMLMemento mem = recordWorkbenchState();
0895: // Save the IMemento to a file.
0896: saveMementoToFile(mem);
0897: }
0898:
0899: public void handleException(Throwable e) {
0900: String message;
0901: if (e.getMessage() == null) {
0902: message = WorkbenchMessages.ErrorClosingNoArg;
0903: } else {
0904: message = NLS.bind(
0905: WorkbenchMessages.ErrorClosingOneArg, e
0906: .getMessage());
0907: }
0908:
0909: if (!MessageDialog.openQuestion(null,
0910: WorkbenchMessages.Error, message)) {
0911: isClosing = false;
0912: }
0913: }
0914: });
0915: }
0916: if (!force && !isClosing) {
0917: return false;
0918: }
0919:
0920: SafeRunner
0921: .run(new SafeRunnable(WorkbenchMessages.ErrorClosing) {
0922: public void run() {
0923: if (isClosing || force) {
0924: isClosing = windowManager.close();
0925: }
0926: }
0927: });
0928:
0929: if (!force && !isClosing) {
0930: return false;
0931: }
0932:
0933: shutdown();
0934:
0935: runEventLoop = false;
0936: return true;
0937: }
0938:
0939: /* (non-Javadoc)
0940: * @see org.eclipse.ui.IWorkbench#saveAllEditors(boolean)
0941: */
0942: public boolean saveAllEditors(boolean confirm) {
0943: final boolean finalConfirm = confirm;
0944: final boolean[] result = new boolean[1];
0945: result[0] = true;
0946:
0947: SafeRunner
0948: .run(new SafeRunnable(WorkbenchMessages.ErrorClosing) {
0949: public void run() {
0950: // Collect dirtyParts
0951: ArrayList dirtyParts = new ArrayList();
0952: ArrayList dirtyEditorsInput = new ArrayList();
0953: IWorkbenchWindow windows[] = getWorkbenchWindows();
0954: for (int i = 0; i < windows.length; i++) {
0955: IWorkbenchPage pages[] = windows[i]
0956: .getPages();
0957: for (int j = 0; j < pages.length; j++) {
0958: WorkbenchPage page = (WorkbenchPage) pages[j];
0959:
0960: ISaveablePart[] parts = page
0961: .getDirtyParts();
0962:
0963: for (int k = 0; k < parts.length; k++) {
0964: ISaveablePart part = parts[k];
0965:
0966: if (part.isSaveOnCloseNeeded()) {
0967: if (part instanceof IEditorPart) {
0968: IEditorPart editor = (IEditorPart) part;
0969: if (!dirtyEditorsInput
0970: .contains(editor
0971: .getEditorInput())) {
0972: dirtyParts.add(editor);
0973: dirtyEditorsInput
0974: .add(editor
0975: .getEditorInput());
0976: }
0977: } else {
0978: dirtyParts.add(part);
0979: }
0980: }
0981: }
0982: }
0983: }
0984: IShellProvider shellProvider;
0985: IRunnableContext runnableContext;
0986: IWorkbenchWindow w = getActiveWorkbenchWindow();
0987: if (w == null && windows.length > 0) {
0988: w = windows[0];
0989: }
0990: if (w != null) {
0991: shellProvider = (WorkbenchWindow) w;
0992: runnableContext = w;
0993: } else {
0994: shellProvider = new IShellProvider() {
0995: public Shell getShell() {
0996: return null;
0997: }
0998: };
0999: runnableContext = new ProgressMonitorDialog(
1000: null);
1001: }
1002: // The fourth parameter is true to also save saveables from
1003: // non-part sources, see bug 139004.
1004: result[0] = EditorManager.saveAll(dirtyParts,
1005: finalConfirm, false, true,
1006: runnableContext, shellProvider);
1007: }
1008: });
1009: return result[0];
1010: }
1011:
1012: /**
1013: * Opens a new workbench window and page with a specific perspective.
1014: *
1015: * Assumes that busy cursor is active.
1016: */
1017: private IWorkbenchWindow busyOpenWorkbenchWindow(
1018: final String perspID, final IAdaptable input)
1019: throws WorkbenchException {
1020: // Create a workbench window (becomes active window)
1021: final WorkbenchWindow newWindowArray[] = new WorkbenchWindow[1];
1022: StartupThreading
1023: .runWithWorkbenchExceptions(new StartupRunnable() {
1024: public void runWithException() {
1025: newWindowArray[0] = newWorkbenchWindow();
1026: }
1027: });
1028:
1029: final WorkbenchWindow newWindow = newWindowArray[0];
1030:
1031: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1032:
1033: public void runWithException() {
1034: newWindow.create(); // must be created before adding to window
1035: // manager
1036: }
1037: });
1038: windowManager.add(newWindow);
1039:
1040: final WorkbenchException[] exceptions = new WorkbenchException[1];
1041: // Create the initial page.
1042: if (perspID != null) {
1043: StartupThreading
1044: .runWithWorkbenchExceptions(new StartupRunnable() {
1045:
1046: public void runWithException()
1047: throws WorkbenchException {
1048: try {
1049: newWindow.busyOpenPage(perspID, input);
1050: } catch (WorkbenchException e) {
1051: windowManager.remove(newWindow);
1052: exceptions[0] = e;
1053: }
1054: }
1055: });
1056: }
1057: if (exceptions[0] != null)
1058: throw exceptions[0];
1059:
1060: // Open window after opening page, to avoid flicker.
1061: StartupThreading
1062: .runWithWorkbenchExceptions(new StartupRunnable() {
1063:
1064: public void runWithException() {
1065: newWindow.open();
1066: }
1067: });
1068:
1069: return newWindow;
1070: }
1071:
1072: /*
1073: * (non-Javadoc) Method declared on IWorkbench.
1074: */
1075: public boolean close() {
1076: return close(PlatformUI.RETURN_OK, false);
1077: }
1078:
1079: /**
1080: * Closes the workbench, returning the given return code from the run
1081: * method. If forced, the workbench is closed no matter what.
1082: *
1083: * @param returnCode
1084: * {@link PlatformUI#RETURN_OK RETURN_OK}for normal exit;
1085: * {@link PlatformUI#RETURN_RESTART RETURN_RESTART}if the
1086: * workbench was terminated with a call to
1087: * {@link IWorkbench#restart IWorkbench.restart};
1088: * {@link PlatformUI#RETURN_EMERGENCY_CLOSE} for an emergency
1089: * shutdown
1090: * {@link PlatformUI#RETURN_UNSTARTABLE RETURN_UNSTARTABLE}if
1091: * the workbench could not be started; other values reserved for
1092: * future use
1093: *
1094: * @param force
1095: * true to force the workbench close, and false for a "soft"
1096: * close that can be canceled
1097: * @return true if the close was successful, and false if the close was
1098: * canceled
1099: */
1100: /* package */
1101: boolean close(int returnCode, final boolean force) {
1102: this .returnCode = returnCode;
1103: final boolean[] ret = new boolean[1];
1104: BusyIndicator.showWhile(null, new Runnable() {
1105: public void run() {
1106: ret[0] = busyClose(force);
1107: }
1108: });
1109: return ret[0];
1110: }
1111:
1112: /*
1113: * (non-Javadoc) Method declared on IWorkbench.
1114: */
1115: public IWorkbenchWindow getActiveWorkbenchWindow() {
1116: // Return null if called from a non-UI thread.
1117: // This is not spec'ed behaviour and is misleading, however this is how
1118: // it
1119: // worked in 2.1 and we cannot change it now.
1120: // For more details, see [Bug 57384] [RCP] Main window not active on
1121: // startup
1122: if (Display.getCurrent() == null) {
1123: return null;
1124: }
1125:
1126: // Look at the current shell and up its parent
1127: // hierarchy for a workbench window.
1128: Control shell = display.getActiveShell();
1129: while (shell != null) {
1130: Object data = shell.getData();
1131: if (data instanceof IWorkbenchWindow) {
1132: return (IWorkbenchWindow) data;
1133: }
1134: shell = shell.getParent();
1135: }
1136:
1137: // Look for the window that was last known being
1138: // the active one
1139: WorkbenchWindow win = getActivatedWindow();
1140: if (win != null) {
1141: return win;
1142: }
1143:
1144: // Look at all the shells and pick the first one
1145: // that is a workbench window.
1146: Shell shells[] = display.getShells();
1147: for (int i = 0; i < shells.length; i++) {
1148: Object data = shells[i].getData();
1149: if (data instanceof IWorkbenchWindow) {
1150: return (IWorkbenchWindow) data;
1151: }
1152: }
1153:
1154: // Can't find anything!
1155: return null;
1156: }
1157:
1158: /*
1159: * Returns the editor history.
1160: */
1161: public EditorHistory getEditorHistory() {
1162: if (editorHistory == null) {
1163: editorHistory = new EditorHistory();
1164: }
1165: return editorHistory;
1166: }
1167:
1168: /*
1169: * (non-Javadoc) Method declared on IWorkbench.
1170: */
1171: public IEditorRegistry getEditorRegistry() {
1172: return WorkbenchPlugin.getDefault().getEditorRegistry();
1173: }
1174:
1175: /*
1176: * Returns the number for a new window. This will be the first number > 0
1177: * which is not used to identify another window in the workbench.
1178: */
1179: private int getNewWindowNumber() {
1180: // Get window list.
1181: Window[] windows = windowManager.getWindows();
1182: int count = windows.length;
1183:
1184: // Create an array of booleans (size = window count).
1185: // Cross off every number found in the window list.
1186: boolean checkArray[] = new boolean[count];
1187: for (int nX = 0; nX < count; nX++) {
1188: if (windows[nX] instanceof WorkbenchWindow) {
1189: WorkbenchWindow ww = (WorkbenchWindow) windows[nX];
1190: int index = ww.getNumber() - 1;
1191: if (index >= 0 && index < count) {
1192: checkArray[index] = true;
1193: }
1194: }
1195: }
1196:
1197: // Return first index which is not used.
1198: // If no empty index was found then every slot is full.
1199: // Return next index.
1200: for (int index = 0; index < count; index++) {
1201: if (!checkArray[index]) {
1202: return index + 1;
1203: }
1204: }
1205: return count + 1;
1206: }
1207:
1208: /*
1209: * (non-Javadoc) Method declared on IWorkbench.
1210: */
1211: public IWorkbenchOperationSupport getOperationSupport() {
1212: return WorkbenchPlugin.getDefault().getOperationSupport();
1213: }
1214:
1215: /*
1216: * (non-Javadoc) Method declared on IWorkbench.
1217: */
1218: public IPerspectiveRegistry getPerspectiveRegistry() {
1219: return WorkbenchPlugin.getDefault().getPerspectiveRegistry();
1220: }
1221:
1222: /*
1223: * (non-Javadoc) Method declared on IWorkbench.
1224: */
1225: public PreferenceManager getPreferenceManager() {
1226: return WorkbenchPlugin.getDefault().getPreferenceManager();
1227: }
1228:
1229: /*
1230: * (non-Javadoc) Method declared on IWorkbench.
1231: */
1232: public IPreferenceStore getPreferenceStore() {
1233: return WorkbenchPlugin.getDefault().getPreferenceStore();
1234: }
1235:
1236: /*
1237: * (non-Javadoc) Method declared on IWorkbench.
1238: */
1239: public ISharedImages getSharedImages() {
1240: return WorkbenchPlugin.getDefault().getSharedImages();
1241: }
1242:
1243: /**
1244: * Returns the window manager for this workbench.
1245: *
1246: * @return the window manager
1247: */
1248: /* package */
1249: WindowManager getWindowManager() {
1250: return windowManager;
1251: }
1252:
1253: /*
1254: * Answer the workbench state file.
1255: */
1256: private File getWorkbenchStateFile() {
1257: IPath path = WorkbenchPlugin.getDefault().getDataLocation();
1258: if (path == null) {
1259: return null;
1260: }
1261: path = path.append(DEFAULT_WORKBENCH_STATE_FILENAME);
1262: return path.toFile();
1263: }
1264:
1265: /*
1266: * (non-Javadoc) Method declared on IWorkbench.
1267: */
1268: public int getWorkbenchWindowCount() {
1269: return windowManager.getWindowCount();
1270: }
1271:
1272: /*
1273: * (non-Javadoc) Method declared on IWorkbench.
1274: */
1275: public IWorkbenchWindow[] getWorkbenchWindows() {
1276: Window[] windows = windowManager.getWindows();
1277: IWorkbenchWindow[] dwindows = new IWorkbenchWindow[windows.length];
1278: System.arraycopy(windows, 0, dwindows, 0, windows.length);
1279: return dwindows;
1280: }
1281:
1282: /*
1283: * (non-Javadoc) Method declared on IWorkbench.
1284: */
1285: public IWorkingSetManager getWorkingSetManager() {
1286: return WorkbenchPlugin.getDefault().getWorkingSetManager();
1287: }
1288:
1289: /**
1290: * {@inheritDoc}
1291: */
1292: public ILocalWorkingSetManager createLocalWorkingSetManager() {
1293: return new LocalWorkingSetManager(WorkbenchPlugin.getDefault()
1294: .getBundleContext());
1295: }
1296:
1297: /**
1298: * Initializes the workbench now that the display is created.
1299: *
1300: * @return true if init succeeded.
1301: */
1302: private boolean init() {
1303: // setup debug mode if required.
1304: if (WorkbenchPlugin.getDefault().isDebugging()) {
1305: WorkbenchPlugin.DEBUG = true;
1306: ModalContext.setDebugMode(true);
1307: }
1308:
1309: // Set up the JFace preference store
1310: JFaceUtil.initializeJFacePreferences();
1311:
1312: // create workbench window manager
1313: windowManager = new WindowManager();
1314:
1315: IIntroRegistry introRegistry = WorkbenchPlugin.getDefault()
1316: .getIntroRegistry();
1317: if (introRegistry.getIntroCount() > 0) {
1318: IProduct product = Platform.getProduct();
1319: if (product != null) {
1320: introDescriptor = (IntroDescriptor) introRegistry
1321: .getIntroForProduct(product.getId());
1322: }
1323: }
1324:
1325: // Initialize the activity support.
1326: workbenchActivitySupport = new WorkbenchActivitySupport();
1327: activityHelper = ActivityPersistanceHelper.getInstance();
1328:
1329: initializeDefaultServices();
1330: initializeFonts();
1331: initializeColors();
1332: initializeApplicationColors();
1333:
1334: // now that the workbench is sufficiently initialized, let the advisor
1335: // have a turn.
1336: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1337:
1338: public void runWithException() {
1339: advisor
1340: .internalBasicInitialize(getWorkbenchConfigurer());
1341: }
1342: });
1343:
1344: // configure use of color icons in toolbars
1345: boolean useColorIcons = PrefUtil.getInternalPreferenceStore()
1346: .getBoolean(IPreferenceConstants.COLOR_ICONS);
1347: ActionContributionItem
1348: .setUseColorIconsInToolbars(useColorIcons);
1349:
1350: // initialize workbench single-click vs double-click behavior
1351: initializeSingleClickOption();
1352:
1353: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1354:
1355: public void runWithException() {
1356: ((GrabFocus) Tweaklets.get(GrabFocus.KEY))
1357: .init(getDisplay());
1358: }
1359: });
1360:
1361: // attempt to restore a previous workbench state
1362: try {
1363: UIStats.start(UIStats.RESTORE_WORKBENCH, "Workbench"); //$NON-NLS-1$
1364:
1365: final boolean bail[] = new boolean[1];
1366: StartupThreading
1367: .runWithoutExceptions(new StartupRunnable() {
1368:
1369: public void runWithException() throws Throwable {
1370: advisor.preStartup();
1371:
1372: if (!advisor.openWindows()) {
1373: bail[0] = true;
1374: }
1375: }
1376: });
1377:
1378: if (bail[0])
1379: return false;
1380:
1381: } finally {
1382: UIStats.end(UIStats.RESTORE_WORKBENCH, this , "Workbench"); //$NON-NLS-1$
1383: }
1384:
1385: forceOpenPerspective();
1386:
1387: return true;
1388: }
1389:
1390: /**
1391: * Establishes the relationship between JFace actions and the command
1392: * manager.
1393: */
1394: private void initializeCommandResolver() {
1395: ExternalActionManager.getInstance().setCallback(
1396: new CommandCallback(bindingManager, commandManager,
1397: new IActiveChecker() {
1398: public final boolean isActive(
1399: final String commandId) {
1400: return workbenchActivitySupport
1401: .getActivityManager()
1402: .getIdentifier(commandId)
1403: .isEnabled();
1404: }
1405: }));
1406: }
1407:
1408: /**
1409: * Initialize colors defined by the new colorDefinitions extension point.
1410: * Note this will be rolled into initializeColors() at some point.
1411: *
1412: * @since 3.0
1413: */
1414: private void initializeApplicationColors() {
1415: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1416:
1417: public void runWithException() {
1418: ColorDefinition[] colorDefinitions = WorkbenchPlugin
1419: .getDefault().getThemeRegistry().getColors();
1420: ThemeElementHelper.populateRegistry(getThemeManager()
1421: .getTheme(IThemeManager.DEFAULT_THEME),
1422: colorDefinitions, PrefUtil
1423: .getInternalPreferenceStore());
1424: }
1425: });
1426: }
1427:
1428: private void initializeSingleClickOption() {
1429: IPreferenceStore store = WorkbenchPlugin.getDefault()
1430: .getPreferenceStore();
1431: boolean openOnSingleClick = store
1432: .getBoolean(IPreferenceConstants.OPEN_ON_SINGLE_CLICK);
1433: boolean selectOnHover = store
1434: .getBoolean(IPreferenceConstants.SELECT_ON_HOVER);
1435: boolean openAfterDelay = store
1436: .getBoolean(IPreferenceConstants.OPEN_AFTER_DELAY);
1437: int singleClickMethod = openOnSingleClick ? OpenStrategy.SINGLE_CLICK
1438: : OpenStrategy.DOUBLE_CLICK;
1439: if (openOnSingleClick) {
1440: if (selectOnHover) {
1441: singleClickMethod |= OpenStrategy.SELECT_ON_HOVER;
1442: }
1443: if (openAfterDelay) {
1444: singleClickMethod |= OpenStrategy.ARROW_KEYS_OPEN;
1445: }
1446: }
1447: OpenStrategy.setOpenMethod(singleClickMethod);
1448: }
1449:
1450: /*
1451: * Initializes the workbench fonts with the stored values.
1452: */
1453: private void initializeFonts() {
1454: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1455:
1456: public void runWithException() {
1457: FontDefinition[] fontDefinitions = WorkbenchPlugin
1458: .getDefault().getThemeRegistry().getFonts();
1459:
1460: ThemeElementHelper.populateRegistry(getThemeManager()
1461: .getCurrentTheme(), fontDefinitions, PrefUtil
1462: .getInternalPreferenceStore());
1463: }
1464: });
1465: }
1466:
1467: /*
1468: * Initialize the workbench images.
1469: *
1470: * @param windowImages An array of the descriptors of the images to be used
1471: * in the corner of each window, or <code>null</code> if none. It is
1472: * expected that the array will contain the same icon, rendered at different
1473: * sizes.
1474: *
1475: * @since 3.0
1476: */
1477: private static void initializeImages() {
1478: ImageDescriptor[] windowImages = WorkbenchPlugin.getDefault()
1479: .getWindowImages();
1480: if (windowImages == null) {
1481: return;
1482: }
1483:
1484: Image[] images = new Image[windowImages.length];
1485: for (int i = 0; i < windowImages.length; ++i) {
1486: images[i] = windowImages[i].createImage();
1487: }
1488: Window.setDefaultImages(images);
1489: }
1490:
1491: /*
1492: * Take the workbenches' images out of the shared registry.
1493: *
1494: * @since 3.0
1495: */
1496: private void uninitializeImages() {
1497: WorkbenchImages.dispose();
1498: Image[] images = Window.getDefaultImages();
1499: Window.setDefaultImage(null);
1500: for (int i = 0; i < images.length; i++) {
1501: images[i].dispose();
1502: }
1503: }
1504:
1505: /*
1506: * Initialize the workbench colors.
1507: *
1508: * @since 3.0
1509: */
1510: private void initializeColors() {
1511: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1512: public void runWithException() {
1513: WorkbenchColors.startup();
1514: }
1515: });
1516: }
1517:
1518: /*
1519: * (non-Javadoc) Method declared on IWorkbench.
1520: */
1521: public boolean isClosing() {
1522: return isClosing;
1523: }
1524:
1525: /**
1526: * Initializes all of the default services for the workbench. For
1527: * initializing the command-based services, this also parses the registry
1528: * and hooks up all the required listeners.
1529: */
1530: private final void initializeDefaultServices() {
1531:
1532: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1533:
1534: public void runWithException() {
1535: serviceLocator.registerService(IWorkbench.class,
1536: Workbench.this );
1537: }
1538: });
1539:
1540: // TODO Correctly order service initialization
1541: // there needs to be some serious consideration given to
1542: // the services, and hooking them up in the correct order
1543: final EvaluationService evaluationService = new EvaluationService();
1544:
1545: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1546:
1547: public void runWithException() {
1548: serviceLocator.registerService(
1549: IEvaluationService.class, evaluationService);
1550: }
1551: });
1552:
1553: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1554:
1555: public void runWithException() {
1556: serviceLocator.registerService(
1557: ISaveablesLifecycleListener.class,
1558: new SaveablesList());
1559: }
1560: });
1561:
1562: /*
1563: * Phase 1 of the initialization of commands. When this phase completes,
1564: * all the services and managers will exist, and be accessible via the
1565: * getService(Object) method.
1566: */
1567: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1568:
1569: public void runWithException() {
1570: Command.DEBUG_COMMAND_EXECUTION = Policy.DEBUG_COMMANDS;
1571: commandManager = new CommandManager();
1572: }
1573: });
1574:
1575: final CommandService[] commandService = new CommandService[1];
1576: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1577:
1578: public void runWithException() {
1579: commandService[0] = new CommandService(commandManager);
1580: commandService[0].readRegistry();
1581: serviceLocator.registerService(ICommandService.class,
1582: commandService[0]);
1583:
1584: }
1585: });
1586:
1587: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1588:
1589: public void runWithException() {
1590: ContextManager.DEBUG = Policy.DEBUG_CONTEXTS;
1591: contextManager = new ContextManager();
1592: }
1593: });
1594:
1595: final IContextService contextService = new ContextService(
1596: contextManager);
1597:
1598: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1599:
1600: public void runWithException() {
1601: contextService.readRegistry();
1602: }
1603: });
1604:
1605: serviceLocator.registerService(IContextService.class,
1606: contextService);
1607:
1608: final IHandlerService[] handlerService = new IHandlerService[1];
1609:
1610: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1611:
1612: public void runWithException() {
1613: handlerService[0] = new HandlerService(
1614: commandService[0], evaluationService);
1615: handlerService[0].readRegistry();
1616: }
1617: });
1618:
1619: serviceLocator.registerService(IHandlerService.class,
1620: handlerService[0]);
1621:
1622: final IBindingService[] bindingService = new BindingService[1];
1623:
1624: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1625:
1626: public void runWithException() {
1627: BindingManager.DEBUG = Policy.DEBUG_KEY_BINDINGS;
1628: bindingManager = new BindingManager(contextManager,
1629: commandManager);
1630: bindingService[0] = new BindingService(bindingManager,
1631: commandService[0], Workbench.this );
1632:
1633: }
1634: });
1635:
1636: bindingService[0].readRegistryAndPreferences(commandService[0]);
1637: serviceLocator.registerService(IBindingService.class,
1638: bindingService[0]);
1639:
1640: final CommandImageManager commandImageManager = new CommandImageManager();
1641: final CommandImageService commandImageService = new CommandImageService(
1642: commandImageManager, commandService[0]);
1643: commandImageService.readRegistry();
1644: serviceLocator.registerService(ICommandImageService.class,
1645: commandImageService);
1646:
1647: final WorkbenchMenuService menuService = new WorkbenchMenuService(
1648: serviceLocator);
1649:
1650: serviceLocator.registerService(IMenuService.class, menuService);
1651: // the service must be registered before it is initialized - its
1652: // initialization uses the service locator to address a dependency on
1653: // the menu service
1654: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1655:
1656: public void runWithException() {
1657: menuService.readRegistry();
1658: }
1659: });
1660:
1661: /*
1662: * Phase 2 of the initialization of commands. The source providers that
1663: * the workbench provides are creating and registered with the above
1664: * services. These source providers notify the services when particular
1665: * pieces of workbench state change.
1666: */
1667: final ISourceProviderService sourceProviderService = new SourceProviderService();
1668: serviceLocator.registerService(ISourceProviderService.class,
1669: sourceProviderService);
1670: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1671:
1672: public void runWithException() {
1673: final ActiveShellSourceProvider activeShellSourceProvider = new ActiveShellSourceProvider(
1674: Workbench.this );
1675: evaluationService
1676: .addSourceProvider(activeShellSourceProvider);
1677: handlerService[0]
1678: .addSourceProvider(activeShellSourceProvider);
1679: contextService
1680: .addSourceProvider(activeShellSourceProvider);
1681: menuService
1682: .addSourceProvider(activeShellSourceProvider);
1683: sourceProviderService
1684: .registerProvider(activeShellSourceProvider);
1685: }
1686: });
1687:
1688: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1689:
1690: public void runWithException() {
1691: final ActivePartSourceProvider activePartSourceProvider = new ActivePartSourceProvider(
1692: Workbench.this );
1693: evaluationService
1694: .addSourceProvider(activePartSourceProvider);
1695: handlerService[0]
1696: .addSourceProvider(activePartSourceProvider);
1697: contextService
1698: .addSourceProvider(activePartSourceProvider);
1699: menuService.addSourceProvider(activePartSourceProvider);
1700: sourceProviderService
1701: .registerProvider(activePartSourceProvider);
1702: }
1703: });
1704: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1705:
1706: public void runWithException() {
1707: final ActiveContextSourceProvider activeContextSourceProvider = new ActiveContextSourceProvider(
1708: contextService);
1709: evaluationService
1710: .addSourceProvider(activeContextSourceProvider);
1711: handlerService[0]
1712: .addSourceProvider(activeContextSourceProvider);
1713: menuService
1714: .addSourceProvider(activeContextSourceProvider);
1715: sourceProviderService
1716: .registerProvider(activeContextSourceProvider);
1717: }
1718: });
1719: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1720:
1721: public void runWithException() {
1722: final CurrentSelectionSourceProvider currentSelectionSourceProvider = new CurrentSelectionSourceProvider(
1723: Workbench.this );
1724: evaluationService
1725: .addSourceProvider(currentSelectionSourceProvider);
1726: handlerService[0]
1727: .addSourceProvider(currentSelectionSourceProvider);
1728: contextService
1729: .addSourceProvider(currentSelectionSourceProvider);
1730: menuService
1731: .addSourceProvider(currentSelectionSourceProvider);
1732: sourceProviderService
1733: .registerProvider(currentSelectionSourceProvider);
1734:
1735: actionSetSourceProvider = new ActionSetSourceProvider();
1736: evaluationService
1737: .addSourceProvider(actionSetSourceProvider);
1738: handlerService[0]
1739: .addSourceProvider(actionSetSourceProvider);
1740: contextService
1741: .addSourceProvider(actionSetSourceProvider);
1742: menuService.addSourceProvider(actionSetSourceProvider);
1743: sourceProviderService
1744: .registerProvider(actionSetSourceProvider);
1745:
1746: FocusControlSourceProvider focusControl = new FocusControlSourceProvider();
1747: serviceLocator.registerService(IFocusService.class,
1748: focusControl);
1749: evaluationService.addSourceProvider(focusControl);
1750: handlerService[0].addSourceProvider(focusControl);
1751: contextService.addSourceProvider(focusControl);
1752: menuService.addSourceProvider(focusControl);
1753: sourceProviderService.registerProvider(focusControl);
1754:
1755: menuSourceProvider = new MenuSourceProvider();
1756: evaluationService.addSourceProvider(menuSourceProvider);
1757: handlerService[0].addSourceProvider(menuSourceProvider);
1758: contextService.addSourceProvider(menuSourceProvider);
1759: menuService.addSourceProvider(menuSourceProvider);
1760: sourceProviderService
1761: .registerProvider(menuSourceProvider);
1762: }
1763: });
1764:
1765: /*
1766: * Phase 3 of the initialization of commands. This handles the creation
1767: * of wrappers for legacy APIs. By the time this phase completes, any
1768: * code trying to access commands through legacy APIs should work.
1769: */
1770: workbenchContextSupport = new WorkbenchContextSupport(this ,
1771: contextManager);
1772: workbenchCommandSupport = new WorkbenchCommandSupport(
1773: bindingManager, commandManager, contextManager,
1774: handlerService[0]);
1775: initializeCommandResolver();
1776:
1777: addWindowListener(windowListener);
1778: bindingManager
1779: .addBindingManagerListener(bindingManagerListener);
1780:
1781: serviceLocator.registerService(
1782: ISelectionConversionService.class,
1783: new SelectionConversionService());
1784: }
1785:
1786: /**
1787: * Returns true if the Workbench is in the process of starting.
1788: *
1789: * @return <code>true</code> if the Workbench is starting, but not yet
1790: * running the event loop.
1791: */
1792: public boolean isStarting() {
1793: return isStarting;
1794: }
1795:
1796: /*
1797: * Creates a new workbench window.
1798: *
1799: * @return the new workbench window
1800: */
1801: private WorkbenchWindow newWorkbenchWindow() {
1802: return new WorkbenchWindow(getNewWindowNumber());
1803: }
1804:
1805: /*
1806: * If a perspective was specified on the command line (-perspective) then
1807: * force that perspective to open in the active window.
1808: */
1809: private void forceOpenPerspective() {
1810: if (getWorkbenchWindowCount() == 0) {
1811: // there should be an open window by now, bail out.
1812: return;
1813: }
1814:
1815: String perspId = null;
1816: String[] commandLineArgs = Platform.getCommandLineArgs();
1817: for (int i = 0; i < commandLineArgs.length - 1; i++) {
1818: if (commandLineArgs[i].equalsIgnoreCase("-perspective")) { //$NON-NLS-1$
1819: perspId = commandLineArgs[i + 1];
1820: break;
1821: }
1822: }
1823: if (perspId == null) {
1824: return;
1825: }
1826: IPerspectiveDescriptor desc = getPerspectiveRegistry()
1827: .findPerspectiveWithId(perspId);
1828: if (desc == null) {
1829: return;
1830: }
1831:
1832: IWorkbenchWindow win = getActiveWorkbenchWindow();
1833: if (win == null) {
1834: win = getWorkbenchWindows()[0];
1835: }
1836:
1837: final String threadPerspId = perspId;
1838: final IWorkbenchWindow threadWin = win;
1839: StartupThreading.runWithoutExceptions(new StartupRunnable() {
1840: public void runWithException() throws Throwable {
1841: try {
1842: showPerspective(threadPerspId, threadWin);
1843: } catch (WorkbenchException e) {
1844: String msg = "Workbench exception showing specified command line perspective on startup."; //$NON-NLS-1$
1845: WorkbenchPlugin.log(msg, new Status(IStatus.ERROR,
1846: PlatformUI.PLUGIN_ID, 0, msg, e));
1847: }
1848: }
1849: });
1850: }
1851:
1852: /**
1853: * Opens the initial workbench window.
1854: */
1855: /* package */void openFirstTimeWindow() {
1856: final boolean showProgress = PrefUtil
1857: .getAPIPreferenceStore()
1858: .getBoolean(
1859: IWorkbenchPreferenceConstants.SHOW_PROGRESS_ON_STARTUP);
1860:
1861: if (!showProgress) {
1862: doOpenFirstTimeWindow();
1863: } else {
1864: // We don't know how many plug-ins will be loaded,
1865: // assume we are loading a tenth of the installed plug-ins.
1866: // (The Eclipse SDK loads 7 of 86 plug-ins at startup as of
1867: // 2005-5-20)
1868: final int expectedProgressCount = Math.max(1,
1869: WorkbenchPlugin.getDefault().getBundleCount() / 10);
1870:
1871: runStartupWithProgress(expectedProgressCount,
1872: new Runnable() {
1873: public void run() {
1874: doOpenFirstTimeWindow();
1875: }
1876: });
1877: }
1878: }
1879:
1880: private void runStartupWithProgress(
1881: final int expectedProgressCount, final Runnable runnable) {
1882: progressCount = 0;
1883: final double cutoff = 0.95;
1884:
1885: AbstractSplashHandler handler = getSplash();
1886: IProgressMonitor progressMonitor = null;
1887: if (handler != null)
1888: progressMonitor = handler.getBundleProgressMonitor();
1889:
1890: if (progressMonitor == null) {
1891: // cannot report progress (e.g. if the splash screen is not showing)
1892: // fall back to starting without showing progress.
1893: runnable.run();
1894: } else {
1895: progressMonitor.beginTask("", expectedProgressCount); //$NON-NLS-1$
1896: SynchronousBundleListener bundleListener = new StartupProgressBundleListener(
1897: progressMonitor,
1898: (int) (expectedProgressCount * cutoff));
1899: WorkbenchPlugin.getDefault().addBundleListener(
1900: bundleListener);
1901: try {
1902: runnable.run();
1903: progressMonitor.subTask(WorkbenchMessages.Startup_Done);
1904: int remainingWork = expectedProgressCount
1905: - Math.min(progressCount,
1906: (int) (expectedProgressCount * cutoff));
1907: progressMonitor.worked(remainingWork);
1908: progressMonitor.done();
1909: } finally {
1910: WorkbenchPlugin.getDefault().removeBundleListener(
1911: bundleListener);
1912: }
1913: }
1914: }
1915:
1916: private void doOpenFirstTimeWindow() {
1917: try {
1918: final IAdaptable input[] = new IAdaptable[1];
1919: StartupThreading
1920: .runWithoutExceptions(new StartupRunnable() {
1921:
1922: public void runWithException() throws Throwable {
1923: input[0] = getDefaultPageInput();
1924: }
1925: });
1926:
1927: busyOpenWorkbenchWindow(getPerspectiveRegistry()
1928: .getDefaultPerspective(), input[0]);
1929: } catch (final WorkbenchException e) {
1930: // Don't use the window's shell as the dialog parent,
1931: // as the window is not open yet (bug 76724).
1932: StartupThreading
1933: .runWithoutExceptions(new StartupRunnable() {
1934:
1935: public void runWithException() throws Throwable {
1936: ErrorDialog
1937: .openError(
1938: null,
1939: WorkbenchMessages.Problems_Opening_Page,
1940: e.getMessage(), e
1941: .getStatus());
1942: }
1943: });
1944: }
1945: }
1946:
1947: /*
1948: * Restores the workbench UI from the workbench state file (workbench.xml).
1949: *
1950: * @return a status object indicating OK if a window was opened,
1951: * RESTORE_CODE_RESET if no window was opened but one should be, and
1952: * RESTORE_CODE_EXIT if the workbench should close immediately
1953: */
1954: /* package */IStatus restoreState() {
1955:
1956: if (!getWorkbenchConfigurer().getSaveAndRestore()) {
1957: String msg = WorkbenchMessages.Workbench_restoreDisabled;
1958: return new Status(IStatus.WARNING,
1959: WorkbenchPlugin.PI_WORKBENCH,
1960: IWorkbenchConfigurer.RESTORE_CODE_RESET, msg, null);
1961: }
1962: // Read the workbench state file.
1963: final File stateFile = getWorkbenchStateFile();
1964: // If there is no state file cause one to open.
1965: if (stateFile == null || !stateFile.exists()) {
1966: String msg = WorkbenchMessages.Workbench_noStateToRestore;
1967: return new Status(IStatus.WARNING,
1968: WorkbenchPlugin.PI_WORKBENCH,
1969: IWorkbenchConfigurer.RESTORE_CODE_RESET, msg, null);
1970: }
1971:
1972: final IStatus result[] = { new Status(IStatus.OK,
1973: WorkbenchPlugin.PI_WORKBENCH, IStatus.OK, "", null) }; //$NON-NLS-1$
1974: SafeRunner.run(new SafeRunnable(
1975: WorkbenchMessages.ErrorReadingState) {
1976: public void run() throws Exception {
1977: FileInputStream input = new FileInputStream(stateFile);
1978: BufferedReader reader = new BufferedReader(
1979: new InputStreamReader(input, "utf-8")); //$NON-NLS-1$
1980: IMemento memento = XMLMemento.createReadRoot(reader);
1981:
1982: // Validate known version format
1983: String version = memento
1984: .getString(IWorkbenchConstants.TAG_VERSION);
1985: boolean valid = false;
1986: for (int i = 0; i < VERSION_STRING.length; i++) {
1987: if (VERSION_STRING[i].equals(version)) {
1988: valid = true;
1989: break;
1990: }
1991: }
1992: if (!valid) {
1993: reader.close();
1994: String msg = WorkbenchMessages.Invalid_workbench_state_ve;
1995: MessageDialog.openError((Shell) null,
1996: WorkbenchMessages.Restoring_Problems, msg);
1997: stateFile.delete();
1998: result[0] = new Status(IStatus.ERROR,
1999: WorkbenchPlugin.PI_WORKBENCH,
2000: IWorkbenchConfigurer.RESTORE_CODE_RESET,
2001: msg, null);
2002: return;
2003: }
2004:
2005: // Validate compatible version format
2006: // We no longer support the release 1.0 format
2007: if (VERSION_STRING[0].equals(version)) {
2008: reader.close();
2009: String msg = WorkbenchMessages.Workbench_incompatibleSavedStateVersion;
2010: boolean ignoreSavedState = new MessageDialog(
2011: null,
2012: WorkbenchMessages.Workbench_incompatibleUIState,
2013: null, msg, MessageDialog.WARNING,
2014: new String[] { IDialogConstants.OK_LABEL,
2015: IDialogConstants.CANCEL_LABEL }, 0)
2016: .open() == 0;
2017: // OK is the default
2018: if (ignoreSavedState) {
2019: stateFile.delete();
2020: result[0] = new Status(
2021: IStatus.WARNING,
2022: WorkbenchPlugin.PI_WORKBENCH,
2023: IWorkbenchConfigurer.RESTORE_CODE_RESET,
2024: msg, null);
2025: } else {
2026: result[0] = new Status(IStatus.WARNING,
2027: WorkbenchPlugin.PI_WORKBENCH,
2028: IWorkbenchConfigurer.RESTORE_CODE_EXIT,
2029: msg, null);
2030: }
2031: return;
2032: }
2033:
2034: // Restore the saved state
2035: final IStatus restoreResult = restoreState(memento);
2036: reader.close();
2037: if (restoreResult.getSeverity() == IStatus.ERROR) {
2038: StartupThreading
2039: .runWithoutExceptions(new StartupRunnable() {
2040:
2041: public void runWithException()
2042: throws Throwable {
2043: ErrorDialog
2044: .openError(
2045: null,
2046: WorkbenchMessages.Workspace_problemsTitle,
2047: WorkbenchMessages.Workbench_problemsRestoringMsg,
2048: restoreResult);
2049: }
2050: });
2051:
2052: }
2053: }
2054:
2055: public void handleException(final Throwable e) {
2056: StartupThreading
2057: .runWithoutExceptions(new StartupRunnable() {
2058:
2059: public void runWithException() {
2060: handle(e);
2061: String msg = e.getMessage() == null ? "" : e.getMessage(); //$NON-NLS-1$
2062: result[0] = new Status(
2063: IStatus.ERROR,
2064: WorkbenchPlugin.PI_WORKBENCH,
2065: IWorkbenchConfigurer.RESTORE_CODE_RESET,
2066: msg, e);
2067: stateFile.delete();
2068: }
2069: });
2070: }
2071:
2072: private void handle(final Throwable e) {
2073: super .handleException(e);
2074: }
2075: });
2076: // ensure at least one window was opened
2077: if (result[0].isOK() && windowManager.getWindows().length == 0) {
2078: String msg = WorkbenchMessages.Workbench_noWindowsRestored;
2079: result[0] = new Status(IStatus.ERROR,
2080: WorkbenchPlugin.PI_WORKBENCH,
2081: IWorkbenchConfigurer.RESTORE_CODE_RESET, msg, null);
2082: }
2083: return result[0];
2084: }
2085:
2086: /*
2087: * (non-Javadoc) Method declared on IWorkbench.
2088: */
2089: public IWorkbenchWindow openWorkbenchWindow(IAdaptable input)
2090: throws WorkbenchException {
2091: return openWorkbenchWindow(getPerspectiveRegistry()
2092: .getDefaultPerspective(), input);
2093: }
2094:
2095: /*
2096: * (non-Javadoc) Method declared on IWorkbench.
2097: */
2098: public IWorkbenchWindow openWorkbenchWindow(final String perspID,
2099: final IAdaptable input) throws WorkbenchException {
2100: // Run op in busy cursor.
2101: final Object[] result = new Object[1];
2102: BusyIndicator.showWhile(null, new Runnable() {
2103: public void run() {
2104: try {
2105: result[0] = busyOpenWorkbenchWindow(perspID, input);
2106: } catch (WorkbenchException e) {
2107: result[0] = e;
2108: }
2109: }
2110: });
2111: if (result[0] instanceof IWorkbenchWindow) {
2112: return (IWorkbenchWindow) result[0];
2113: } else if (result[0] instanceof WorkbenchException) {
2114: throw (WorkbenchException) result[0];
2115: } else {
2116: throw new WorkbenchException(
2117: WorkbenchMessages.Abnormal_Workbench_Conditi);
2118: }
2119: }
2120:
2121: /*
2122: * (non-Javadoc)
2123: *
2124: * @see org.eclipse.ui.IWorkbench#restoreWorkbenchWindow(org.eclipse.ui.IMemento)
2125: */
2126: IWorkbenchWindow restoreWorkbenchWindow(IMemento memento)
2127: throws WorkbenchException {
2128: WorkbenchWindow newWindow = newWorkbenchWindow();
2129: newWindow.create();
2130:
2131: windowManager.add(newWindow);
2132:
2133: // whether the window was opened
2134: boolean opened = false;
2135:
2136: try {
2137: newWindow.restoreState(memento, null);
2138: newWindow.fireWindowRestored();
2139: newWindow.open();
2140: opened = true;
2141: } finally {
2142: if (!opened) {
2143: newWindow.close();
2144: }
2145: }
2146:
2147: return newWindow;
2148: }
2149:
2150: /*
2151: * Record the workbench UI in a document
2152: */
2153: private XMLMemento recordWorkbenchState() {
2154: XMLMemento memento = XMLMemento
2155: .createWriteRoot(IWorkbenchConstants.TAG_WORKBENCH);
2156: final IStatus status = saveState(memento);
2157: if (status.getSeverity() != IStatus.OK) {
2158: // don't use newWindow as parent because it has not yet been opened
2159: // (bug 76724)
2160: StartupThreading
2161: .runWithoutExceptions(new StartupRunnable() {
2162:
2163: public void runWithException() throws Throwable {
2164: ErrorDialog
2165: .openError(
2166: null,
2167: WorkbenchMessages.Workbench_problemsSaving,
2168: WorkbenchMessages.Workbench_problemsSavingMsg,
2169: status);
2170: }
2171: });
2172:
2173: }
2174: return memento;
2175: }
2176:
2177: /*
2178: * (non-Javadoc) Method declared on IWorkbench.
2179: */
2180: public boolean restart() {
2181: // this is the return code from run() to trigger a restart
2182: return close(PlatformUI.RETURN_RESTART, false);
2183: }
2184:
2185: /*
2186: * Restores the state of the previously saved workbench
2187: */
2188: private IStatus restoreState(final IMemento memento) {
2189:
2190: final MultiStatus result = new MultiStatus(
2191: PlatformUI.PLUGIN_ID, IStatus.OK,
2192: WorkbenchMessages.Workbench_problemsRestoring, null);
2193:
2194: final boolean showProgress = PrefUtil
2195: .getAPIPreferenceStore()
2196: .getBoolean(
2197: IWorkbenchPreferenceConstants.SHOW_PROGRESS_ON_STARTUP);
2198:
2199: try {
2200: /*
2201: * Restored windows will be set in the createdWindows field to be
2202: * used by the openWindowsAfterRestore() method
2203: */
2204: if (!showProgress) {
2205: doRestoreState(memento, result);
2206: } else {
2207: // Retrieve how many plug-ins were loaded while restoring the
2208: // workbench
2209: Integer lastProgressCount = memento
2210: .getInteger(IWorkbenchConstants.TAG_PROGRESS_COUNT);
2211:
2212: // If we don't know how many plug-ins were loaded last time,
2213: // assume we are loading half of the installed plug-ins.
2214: final int expectedProgressCount = Math.max(1,
2215: lastProgressCount == null ? WorkbenchPlugin
2216: .getDefault().getBundleCount() / 2
2217: : lastProgressCount.intValue());
2218:
2219: runStartupWithProgress(expectedProgressCount,
2220: new Runnable() {
2221: public void run() {
2222: doRestoreState(memento, result);
2223: }
2224: });
2225: }
2226: } finally {
2227: openWindowsAfterRestore();
2228: }
2229: return result;
2230: }
2231:
2232: /**
2233: * Returns the ids of all plug-ins that extend the
2234: * <code>org.eclipse.ui.startup</code> extension point.
2235: *
2236: * @return the ids of all plug-ins containing 1 or more startup extensions
2237: */
2238: public String[] getEarlyActivatedPlugins() {
2239: IExtensionPoint point = Platform.getExtensionRegistry()
2240: .getExtensionPoint(PlatformUI.PLUGIN_ID,
2241: IWorkbenchRegistryConstants.PL_STARTUP);
2242: IExtension[] extensions = point.getExtensions();
2243: ArrayList pluginIds = new ArrayList(extensions.length);
2244: for (int i = 0; i < extensions.length; i++) {
2245: String id = extensions[i].getNamespace();
2246: if (!pluginIds.contains(id)) {
2247: pluginIds.add(id);
2248: }
2249: }
2250: return (String[]) pluginIds
2251: .toArray(new String[pluginIds.size()]);
2252: }
2253:
2254: /**
2255: * Returns the ids of the early activated plug-ins that have been disabled
2256: * by the user.
2257: *
2258: * @return the ids of the early activated plug-ins that have been disabled
2259: * by the user
2260: */
2261: public String[] getDisabledEarlyActivatedPlugins() {
2262: String pref = PrefUtil.getInternalPreferenceStore().getString(
2263: IPreferenceConstants.PLUGINS_NOT_ACTIVATED_ON_STARTUP);
2264: return Util.getArrayFromList(pref, ";"); //$NON-NLS-1$
2265: }
2266:
2267: /*
2268: * Starts all plugins that extend the <code> org.eclipse.ui.startup </code>
2269: * extension point, and that the user has not disabled via the preference
2270: * page.
2271: */
2272: private void startPlugins() {
2273: IExtensionRegistry registry = Platform.getExtensionRegistry();
2274:
2275: // bug 55901: don't use getConfigElements directly, for pre-3.0
2276: // compat, make sure to allow both missing class
2277: // attribute and a missing startup element
2278: IExtensionPoint point = registry.getExtensionPoint(
2279: PlatformUI.PLUGIN_ID,
2280: IWorkbenchRegistryConstants.PL_STARTUP);
2281:
2282: final IExtension[] extensions = point.getExtensions();
2283: if (extensions.length == 0) {
2284: return;
2285: }
2286: Job job = new Job("Workbench early startup") { //$NON-NLS-1$
2287: protected IStatus run(IProgressMonitor monitor) {
2288: HashSet disabledPlugins = new HashSet(Arrays
2289: .asList(getDisabledEarlyActivatedPlugins()));
2290: monitor.beginTask(
2291: WorkbenchMessages.Workbench_startingPlugins,
2292: extensions.length);
2293: for (int i = 0; i < extensions.length; ++i) {
2294: if (monitor.isCanceled() || !isRunning()) {
2295: return Status.CANCEL_STATUS;
2296: }
2297: IExtension extension = extensions[i];
2298:
2299: // if the plugin is not in the set of disabled plugins, then
2300: // execute the code to start it
2301: if (!disabledPlugins.contains(extension
2302: .getNamespace())) {
2303: monitor.subTask(extension.getNamespace());
2304: SafeRunner.run(new EarlyStartupRunnable(
2305: extension));
2306: }
2307: monitor.worked(1);
2308: }
2309: monitor.done();
2310: return Status.OK_STATUS;
2311: }
2312:
2313: public boolean belongsTo(Object family) {
2314: return EARLY_STARTUP_FAMILY.equals(family);
2315: }
2316: };
2317: job.setSystem(true);
2318: job.schedule();
2319: }
2320:
2321: /**
2322: * Internal method for running the workbench UI. This entails processing and
2323: * dispatching events until the workbench is closed or restarted.
2324: *
2325: * @return return code {@link PlatformUI#RETURN_OK RETURN_OK}for normal
2326: * exit; {@link PlatformUI#RETURN_RESTART RETURN_RESTART}if the
2327: * workbench was terminated with a call to
2328: * {@link IWorkbench#restart IWorkbench.restart};
2329: * {@link PlatformUI#RETURN_UNSTARTABLE RETURN_UNSTARTABLE}if the
2330: * workbench could not be started; other values reserved for future
2331: * use
2332: * @since 3.0
2333: */
2334: private int runUI() {
2335: UIStats.start(UIStats.START_WORKBENCH, "Workbench"); //$NON-NLS-1$
2336:
2337: // deadlock code
2338: boolean avoidDeadlock = true;
2339:
2340: String[] commandLineArgs = Platform.getCommandLineArgs();
2341: for (int i = 0; i < commandLineArgs.length; i++) {
2342: if (commandLineArgs[i].equalsIgnoreCase("-allowDeadlock")) { //$NON-NLS-1$
2343: avoidDeadlock = false;
2344: }
2345: }
2346:
2347: final UISynchronizer synchronizer;
2348:
2349: if (avoidDeadlock) {
2350: UILockListener uiLockListener = new UILockListener(display);
2351: Platform.getJobManager().setLockListener(uiLockListener);
2352: synchronizer = new UISynchronizer(display, uiLockListener);
2353: display.setSynchronizer(synchronizer);
2354: // declare the main thread to be a startup thread.
2355: UISynchronizer.startupThread.set(Boolean.TRUE);
2356: } else
2357: synchronizer = null;
2358:
2359: // prime the splash nice and early
2360: if (createSplash)
2361: createSplashWrapper();
2362:
2363: // ModalContext should not spin the event loop (there is no UI yet to
2364: // block)
2365: ModalContext.setAllowReadAndDispatch(false);
2366:
2367: // if the -debug command line argument is used and the event loop is
2368: // being
2369: // run while starting the Workbench, log a warning.
2370: if (WorkbenchPlugin.getDefault().isDebugging()) {
2371: display.asyncExec(new Runnable() {
2372: public void run() {
2373: if (isStarting()) {
2374: WorkbenchPlugin
2375: .log(StatusUtil
2376: .newStatus(
2377: IStatus.WARNING,
2378: "Event loop should not be run while the Workbench is starting.", //$NON-NLS-1$
2379: new RuntimeException()));
2380: }
2381: }
2382: });
2383: }
2384:
2385: Listener closeListener = new Listener() {
2386: public void handleEvent(Event event) {
2387: event.doit = close();
2388: }
2389: };
2390:
2391: // Initialize an exception handler.
2392: Window.IExceptionHandler handler = ExceptionHandler
2393: .getInstance();
2394:
2395: try {
2396: // react to display close event by closing workbench nicely
2397: display.addListener(SWT.Close, closeListener);
2398:
2399: // install backstop to catch exceptions thrown out of event loop
2400: Window.setExceptionHandler(handler);
2401:
2402: final boolean[] initOK = new boolean[1];
2403:
2404: if (getSplash() != null) {
2405:
2406: final boolean[] initDone = new boolean[] { false };
2407: Thread initThread = new Thread() {
2408: /* (non-Javadoc)
2409: * @see java.lang.Thread#run()
2410: */
2411: public void run() {
2412: try {
2413: //declare us to be a startup thread so that our syncs will be executed
2414: UISynchronizer.startupThread
2415: .set(Boolean.TRUE);
2416: initOK[0] = Workbench.this .init();
2417: } finally {
2418: initDone[0] = true;
2419: display.wake();
2420: }
2421: }
2422: };
2423: initThread.start();
2424: while (true) {
2425: if (!display.readAndDispatch()) {
2426: if (initDone[0])
2427: break;
2428: display.sleep();
2429: }
2430:
2431: }
2432: } else {
2433: // initialize workbench and restore or open one window
2434: initOK[0] = init();
2435:
2436: }
2437: // drop the splash screen now that a workbench window is up
2438: Platform.endSplash();
2439:
2440: // let the advisor run its start up code
2441: if (initOK[0]) {
2442: advisor.postStartup(); // may trigger a close/restart
2443: }
2444:
2445: if (initOK[0] && runEventLoop) {
2446: // start eager plug-ins
2447: startPlugins();
2448: addStartupRegistryListener();
2449:
2450: // WWinPluginAction.refreshActionList();
2451:
2452: display.asyncExec(new Runnable() {
2453: public void run() {
2454: UIStats.end(UIStats.START_WORKBENCH, this ,
2455: "Workbench"); //$NON-NLS-1$
2456: UIStats.startupComplete();
2457: }
2458: });
2459:
2460: getWorkbenchTestable().init(display, this );
2461:
2462: // allow ModalContext to spin the event loop
2463: ModalContext.setAllowReadAndDispatch(true);
2464: isStarting = false;
2465:
2466: if (synchronizer != null)
2467: synchronizer.started();
2468: // the event loop
2469: runEventLoop(handler, display);
2470: }
2471:
2472: } catch (final Exception e) {
2473: if (!display.isDisposed()) {
2474: handler.handleException(e);
2475: } else {
2476: String msg = "Exception in Workbench.runUI after display was disposed"; //$NON-NLS-1$
2477: WorkbenchPlugin.log(msg, new Status(IStatus.ERROR,
2478: WorkbenchPlugin.PI_WORKBENCH, 1, msg, e));
2479: }
2480: } finally {
2481: // mandatory clean up
2482:
2483: // The runEventLoop flag may not have been cleared if an exception
2484: // occurred
2485: // Needs to be false to ensure PlatformUI.isWorkbenchRunning()
2486: // returns false.
2487: runEventLoop = false;
2488:
2489: if (!display.isDisposed()) {
2490: display.removeListener(SWT.Close, closeListener);
2491: }
2492: }
2493:
2494: // restart or exit based on returnCode
2495: return returnCode;
2496: }
2497:
2498: /*
2499: * Runs an event loop for the workbench.
2500: */
2501: private void runEventLoop(Window.IExceptionHandler handler,
2502: Display display) {
2503: runEventLoop = true;
2504: while (runEventLoop) {
2505: try {
2506: if (!display.readAndDispatch()) {
2507: getAdvisor().eventLoopIdle(display);
2508: }
2509: } catch (Throwable t) {
2510: handler.handleException(t);
2511: }
2512: }
2513: }
2514:
2515: /*
2516: * Saves the current state of the workbench so it can be restored later on
2517: */
2518: private IStatus saveState(IMemento memento) {
2519: MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID,
2520: IStatus.OK, WorkbenchMessages.Workbench_problemsSaving,
2521: null);
2522:
2523: // Save the version number.
2524: memento.putString(IWorkbenchConstants.TAG_VERSION,
2525: VERSION_STRING[1]);
2526:
2527: // Save how many plug-ins were loaded while restoring the workbench
2528: if (progressCount != -1) {
2529: memento.putInteger(IWorkbenchConstants.TAG_PROGRESS_COUNT,
2530: progressCount);
2531: }
2532:
2533: // Save the advisor state.
2534: IMemento advisorState = memento
2535: .createChild(IWorkbenchConstants.TAG_WORKBENCH_ADVISOR);
2536: result.add(getAdvisor().saveState(advisorState));
2537:
2538: // Save the workbench windows.
2539: IWorkbenchWindow[] windows = getWorkbenchWindows();
2540: for (int nX = 0; nX < windows.length; nX++) {
2541: WorkbenchWindow window = (WorkbenchWindow) windows[nX];
2542: IMemento childMem = memento
2543: .createChild(IWorkbenchConstants.TAG_WINDOW);
2544: result.merge(window.saveState(childMem));
2545: }
2546: result.add(getEditorHistory().saveState(
2547: memento.createChild(IWorkbenchConstants.TAG_MRU_LIST)));
2548: return result;
2549: }
2550:
2551: /*
2552: * Save the workbench UI in a persistence file.
2553: */
2554: private boolean saveMementoToFile(XMLMemento memento) {
2555: // Save it to a file.
2556: // XXX: nobody currently checks the return value of this method.
2557: File stateFile = getWorkbenchStateFile();
2558: if (stateFile == null) {
2559: return false;
2560: }
2561: try {
2562: FileOutputStream stream = new FileOutputStream(stateFile);
2563: OutputStreamWriter writer = new OutputStreamWriter(stream,
2564: "utf-8"); //$NON-NLS-1$
2565: memento.save(writer);
2566: writer.close();
2567: } catch (IOException e) {
2568: stateFile.delete();
2569: MessageDialog.openError((Shell) null,
2570: WorkbenchMessages.SavingProblem,
2571: WorkbenchMessages.ProblemSavingState);
2572: return false;
2573: }
2574:
2575: // Success !
2576: return true;
2577: }
2578:
2579: /*
2580: * (non-Javadoc) Method declared on IWorkbench.
2581: */
2582: public IWorkbenchPage showPerspective(String perspectiveId,
2583: IWorkbenchWindow window) throws WorkbenchException {
2584: Assert.isNotNull(perspectiveId);
2585:
2586: // If the specified window has the requested perspective open, then the
2587: // window
2588: // is given focus and the perspective is shown. The page's input is
2589: // ignored.
2590: WorkbenchWindow win = (WorkbenchWindow) window;
2591: if (win != null) {
2592: WorkbenchPage page = win.getActiveWorkbenchPage();
2593: if (page != null) {
2594: IPerspectiveDescriptor perspectives[] = page
2595: .getOpenPerspectives();
2596: for (int i = 0; i < perspectives.length; i++) {
2597: IPerspectiveDescriptor persp = perspectives[i];
2598: if (perspectiveId.equals(persp.getId())) {
2599: win.makeVisible();
2600: page.setPerspective(persp);
2601: return page;
2602: }
2603: }
2604: }
2605: }
2606:
2607: // If another window that has the workspace root as input and the
2608: // requested
2609: // perpective open and active, then the window is given focus.
2610: IAdaptable input = getDefaultPageInput();
2611: IWorkbenchWindow[] windows = getWorkbenchWindows();
2612: for (int i = 0; i < windows.length; i++) {
2613: win = (WorkbenchWindow) windows[i];
2614: if (window != win) {
2615: WorkbenchPage page = win.getActiveWorkbenchPage();
2616: if (page != null) {
2617: boolean inputSame = false;
2618: if (input == null) {
2619: inputSame = (page.getInput() == null);
2620: } else {
2621: inputSame = input.equals(page.getInput());
2622: }
2623: if (inputSame) {
2624: Perspective persp = page.getActivePerspective();
2625: if (persp != null) {
2626: IPerspectiveDescriptor desc = persp
2627: .getDesc();
2628: if (desc != null) {
2629: if (perspectiveId.equals(desc.getId())) {
2630: Shell shell = win.getShell();
2631: shell.open();
2632: if (shell.getMinimized()) {
2633: shell.setMinimized(false);
2634: }
2635: return page;
2636: }
2637: }
2638: }
2639: }
2640: }
2641: }
2642: }
2643:
2644: // Otherwise the requested perspective is opened and shown in the
2645: // specified
2646: // window or in a new window depending on the current user preference
2647: // for opening
2648: // perspectives, and that window is given focus.
2649: win = (WorkbenchWindow) window;
2650: if (win != null) {
2651: IPreferenceStore store = WorkbenchPlugin.getDefault()
2652: .getPreferenceStore();
2653: int mode = store
2654: .getInt(IPreferenceConstants.OPEN_PERSP_MODE);
2655: IWorkbenchPage page = win.getActiveWorkbenchPage();
2656: IPerspectiveDescriptor persp = null;
2657: if (page != null) {
2658: persp = page.getPerspective();
2659: }
2660:
2661: // Only open a new window if user preference is set and the window
2662: // has an active perspective.
2663: if (IPreferenceConstants.OPM_NEW_WINDOW == mode
2664: && persp != null) {
2665: IWorkbenchWindow newWindow = openWorkbenchWindow(
2666: perspectiveId, input);
2667: return newWindow.getActivePage();
2668: }
2669:
2670: IPerspectiveDescriptor desc = getPerspectiveRegistry()
2671: .findPerspectiveWithId(perspectiveId);
2672: if (desc == null) {
2673: throw new WorkbenchException(
2674: NLS
2675: .bind(
2676: WorkbenchMessages.WorkbenchPage_ErrorCreatingPerspective,
2677: perspectiveId));
2678: }
2679: win.getShell().open();
2680: if (page == null) {
2681: page = win.openPage(perspectiveId, input);
2682: } else {
2683: page.setPerspective(desc);
2684: }
2685: return page;
2686: }
2687:
2688: // Just throw an exception....
2689: throw new WorkbenchException(NLS.bind(
2690: WorkbenchMessages.Workbench_showPerspectiveError,
2691: perspectiveId));
2692: }
2693:
2694: /*
2695: * (non-Javadoc) Method declared on IWorkbench.
2696: */
2697: public IWorkbenchPage showPerspective(String perspectiveId,
2698: IWorkbenchWindow window, IAdaptable input)
2699: throws WorkbenchException {
2700: Assert.isNotNull(perspectiveId);
2701:
2702: // If the specified window has the requested perspective open and the
2703: // same requested
2704: // input, then the window is given focus and the perspective is shown.
2705: boolean inputSameAsWindow = false;
2706: WorkbenchWindow win = (WorkbenchWindow) window;
2707: if (win != null) {
2708: WorkbenchPage page = win.getActiveWorkbenchPage();
2709: if (page != null) {
2710: boolean inputSame = false;
2711: if (input == null) {
2712: inputSame = (page.getInput() == null);
2713: } else {
2714: inputSame = input.equals(page.getInput());
2715: }
2716: if (inputSame) {
2717: inputSameAsWindow = true;
2718: IPerspectiveDescriptor perspectives[] = page
2719: .getOpenPerspectives();
2720: for (int i = 0; i < perspectives.length; i++) {
2721: IPerspectiveDescriptor persp = perspectives[i];
2722: if (perspectiveId.equals(persp.getId())) {
2723: win.makeVisible();
2724: page.setPerspective(persp);
2725: return page;
2726: }
2727: }
2728: }
2729: }
2730: }
2731:
2732: // If another window has the requested input and the requested
2733: // perpective open and active, then that window is given focus.
2734: IWorkbenchWindow[] windows = getWorkbenchWindows();
2735: for (int i = 0; i < windows.length; i++) {
2736: win = (WorkbenchWindow) windows[i];
2737: if (window != win) {
2738: WorkbenchPage page = win.getActiveWorkbenchPage();
2739: if (page != null) {
2740: boolean inputSame = false;
2741: if (input == null) {
2742: inputSame = (page.getInput() == null);
2743: } else {
2744: inputSame = input.equals(page.getInput());
2745: }
2746: if (inputSame) {
2747: Perspective persp = page.getActivePerspective();
2748: if (persp != null) {
2749: IPerspectiveDescriptor desc = persp
2750: .getDesc();
2751: if (desc != null) {
2752: if (perspectiveId.equals(desc.getId())) {
2753: win.getShell().open();
2754: return page;
2755: }
2756: }
2757: }
2758: }
2759: }
2760: }
2761: }
2762:
2763: // If the specified window has the same requested input but not the
2764: // requested
2765: // perspective, then the window is given focus and the perspective is
2766: // opened and shown
2767: // on condition that the user preference is not to open perspectives in
2768: // a new window.
2769: win = (WorkbenchWindow) window;
2770: if (inputSameAsWindow && win != null) {
2771: IPreferenceStore store = WorkbenchPlugin.getDefault()
2772: .getPreferenceStore();
2773: int mode = store
2774: .getInt(IPreferenceConstants.OPEN_PERSP_MODE);
2775:
2776: if (IPreferenceConstants.OPM_NEW_WINDOW != mode) {
2777: IWorkbenchPage page = win.getActiveWorkbenchPage();
2778: IPerspectiveDescriptor desc = getPerspectiveRegistry()
2779: .findPerspectiveWithId(perspectiveId);
2780: if (desc == null) {
2781: throw new WorkbenchException(
2782: NLS
2783: .bind(
2784: WorkbenchMessages.WorkbenchPage_ErrorCreatingPerspective,
2785: perspectiveId));
2786: }
2787: win.getShell().open();
2788: if (page == null) {
2789: page = win.openPage(perspectiveId, input);
2790: } else {
2791: page.setPerspective(desc);
2792: }
2793: return page;
2794: }
2795: }
2796:
2797: // If the specified window has no active perspective, then open the
2798: // requested perspective and show the specified window.
2799: if (win != null) {
2800: IWorkbenchPage page = win.getActiveWorkbenchPage();
2801: IPerspectiveDescriptor persp = null;
2802: if (page != null) {
2803: persp = page.getPerspective();
2804: }
2805: if (persp == null) {
2806: IPerspectiveDescriptor desc = getPerspectiveRegistry()
2807: .findPerspectiveWithId(perspectiveId);
2808: if (desc == null) {
2809: throw new WorkbenchException(
2810: NLS
2811: .bind(
2812: WorkbenchMessages.WorkbenchPage_ErrorCreatingPerspective,
2813: perspectiveId));
2814: }
2815: win.getShell().open();
2816: if (page == null) {
2817: page = win.openPage(perspectiveId, input);
2818: } else {
2819: page.setPerspective(desc);
2820: }
2821: return page;
2822: }
2823: }
2824:
2825: // Otherwise the requested perspective is opened and shown in a new
2826: // window, and the
2827: // window is given focus.
2828: IWorkbenchWindow newWindow = openWorkbenchWindow(perspectiveId,
2829: input);
2830: return newWindow.getActivePage();
2831: }
2832:
2833: /*
2834: * Shuts down the application.
2835: */
2836: private void shutdown() {
2837: // shutdown application-specific portions first
2838: advisor.postShutdown();
2839:
2840: // notify regular workbench clients of shutdown, and clear the list when
2841: // done
2842: firePostShutdown();
2843: workbenchListeners.clear();
2844:
2845: cancelEarlyStartup();
2846:
2847: // for dynamic UI
2848: Platform.getExtensionRegistry().removeRegistryChangeListener(
2849: extensionEventHandler);
2850: Platform.getExtensionRegistry().removeRegistryChangeListener(
2851: startupRegistryListener);
2852:
2853: ((GrabFocus) Tweaklets.get(GrabFocus.KEY)).dispose();
2854:
2855: // Bring down all of the services.
2856: serviceLocator.dispose();
2857:
2858: workbenchActivitySupport.dispose();
2859: WorkbenchHelpSystem.disposeIfNecessary();
2860:
2861: // shutdown the rest of the workbench
2862: WorkbenchColors.shutdown();
2863: activityHelper.shutdown();
2864: uninitializeImages();
2865: if (WorkbenchPlugin.getDefault() != null) {
2866: WorkbenchPlugin.getDefault().reset();
2867: }
2868: WorkbenchThemeManager.getInstance().dispose();
2869: PropertyPageContributorManager.getManager().dispose();
2870: ObjectActionContributorManager.getManager().dispose();
2871: if (tracker != null) {
2872: tracker.close();
2873: }
2874: }
2875:
2876: /**
2877: * Cancels the early startup job, if it's still running.
2878: */
2879: private void cancelEarlyStartup() {
2880: Platform.getJobManager().cancel(EARLY_STARTUP_FAMILY);
2881: // We do not currently wait for any plug-in currently being started to
2882: // complete
2883: // (e.g. by doing a join on EARLY_STARTUP_FAMILY), since they may do a
2884: // syncExec,
2885: // which would hang. See bug 94537 for rationale.
2886: }
2887:
2888: /*
2889: * (non-Javadoc) Method declared on IWorkbench.
2890: */
2891: public IDecoratorManager getDecoratorManager() {
2892: return WorkbenchPlugin.getDefault().getDecoratorManager();
2893: }
2894:
2895: /*
2896: * Returns the workbench window which was last known being the active one,
2897: * or <code> null </code> .
2898: */
2899: private WorkbenchWindow getActivatedWindow() {
2900: if (activatedWindow != null) {
2901: Shell shell = activatedWindow.getShell();
2902: if (shell != null && !shell.isDisposed()) {
2903: return activatedWindow;
2904: }
2905: }
2906:
2907: return null;
2908: }
2909:
2910: /*
2911: * Sets the workbench window which was last known being the active one, or
2912: * <code> null </code> .
2913: */
2914: /* package */
2915: void setActivatedWindow(WorkbenchWindow window) {
2916: activatedWindow = window;
2917: }
2918:
2919: /**
2920: * Returns the unique object that applications use to configure the
2921: * workbench.
2922: * <p>
2923: * IMPORTANT This method is declared package-private to prevent regular
2924: * plug-ins from downcasting IWorkbench to Workbench and getting hold of the
2925: * workbench configurer that would allow them to tamper with the workbench.
2926: * The workbench configurer is available only to the application.
2927: * </p>
2928: */
2929: /* package */
2930: WorkbenchConfigurer getWorkbenchConfigurer() {
2931: if (workbenchConfigurer == null) {
2932: workbenchConfigurer = new WorkbenchConfigurer();
2933: }
2934: return workbenchConfigurer;
2935: }
2936:
2937: /**
2938: * Returns the workbench advisor that created this workbench.
2939: * <p>
2940: * IMPORTANT This method is declared package-private to prevent regular
2941: * plug-ins from downcasting IWorkbench to Workbench and getting hold of the
2942: * workbench advisor that would allow them to tamper with the workbench. The
2943: * workbench advisor is internal to the application.
2944: * </p>
2945: */
2946: /* package */
2947: WorkbenchAdvisor getAdvisor() {
2948: return advisor;
2949: }
2950:
2951: /*
2952: * (non-Javadoc) Method declared on IWorkbench.
2953: */
2954: public Display getDisplay() {
2955: return display;
2956: }
2957:
2958: /**
2959: * Returns the default perspective id, which may be <code>null</code>.
2960: *
2961: * @return the default perspective id, or <code>null</code>
2962: */
2963: public String getDefaultPerspectiveId() {
2964: return getAdvisor().getInitialWindowPerspectiveId();
2965: }
2966:
2967: /**
2968: * Returns the default workbench window page input.
2969: *
2970: * @return the default window page input or <code>null</code> if none
2971: */
2972: public IAdaptable getDefaultPageInput() {
2973: return getAdvisor().getDefaultPageInput();
2974: }
2975:
2976: /**
2977: * Returns the id of the preference page that should be presented most
2978: * prominently.
2979: *
2980: * @return the id of the preference page, or <code>null</code> if none
2981: */
2982: public String getMainPreferencePageId() {
2983: String id = getAdvisor().getMainPreferencePageId();
2984: return id;
2985: }
2986:
2987: /*
2988: * (non-Javadoc)
2989: *
2990: * @see org.eclipse.ui.IWorkbench
2991: * @since 3.0
2992: */
2993: public IElementFactory getElementFactory(String factoryId) {
2994: Assert.isNotNull(factoryId);
2995: return WorkbenchPlugin.getDefault()
2996: .getElementFactory(factoryId);
2997: }
2998:
2999: /*
3000: * (non-Javadoc)
3001: *
3002: * @see org.eclipse.ui.IWorkbench#getProgressService()
3003: */
3004: public IProgressService getProgressService() {
3005: return ProgressManager.getInstance();
3006: }
3007:
3008: private WorkbenchActivitySupport workbenchActivitySupport;
3009:
3010: private WorkbenchCommandSupport workbenchCommandSupport;
3011:
3012: private WorkbenchContextSupport workbenchContextSupport;
3013:
3014: /**
3015: * The single instance of the binding manager used by the workbench. This is
3016: * initialized in <code>Workbench.init(Display)</code> and then never
3017: * changed. This value will only be <code>null</code> if the
3018: * initialization call has not yet completed.
3019: *
3020: * @since 3.1
3021: */
3022: private BindingManager bindingManager;
3023:
3024: /**
3025: * The single instance of the command manager used by the workbench. This is
3026: * initialized in <code>Workbench.init(Display)</code> and then never
3027: * changed. This value will only be <code>null</code> if the
3028: * initialization call has not yet completed.
3029: *
3030: * @since 3.1
3031: */
3032: private CommandManager commandManager;
3033:
3034: /**
3035: * The single instance of the context manager used by the workbench. This is
3036: * initialized in <code>Workbench.init(Display)</code> and then never
3037: * changed. This value will only be <code>null</code> if the
3038: * initialization call has not yet completed.
3039: *
3040: * @since 3.1
3041: */
3042: private ContextManager contextManager;
3043:
3044: public IWorkbenchActivitySupport getActivitySupport() {
3045: return workbenchActivitySupport;
3046: }
3047:
3048: public IWorkbenchCommandSupport getCommandSupport() {
3049: return workbenchCommandSupport;
3050: }
3051:
3052: public IWorkbenchContextSupport getContextSupport() {
3053: return workbenchContextSupport;
3054: }
3055:
3056: private final IWindowListener windowListener = new IWindowListener() {
3057:
3058: public void windowActivated(IWorkbenchWindow window) {
3059: updateActiveWorkbenchWindowMenuManager(true);
3060: }
3061:
3062: public void windowClosed(IWorkbenchWindow window) {
3063: updateActiveWorkbenchWindowMenuManager(true);
3064: }
3065:
3066: public void windowDeactivated(IWorkbenchWindow window) {
3067: updateActiveWorkbenchWindowMenuManager(true);
3068: }
3069:
3070: public void windowOpened(IWorkbenchWindow window) {
3071: updateActiveWorkbenchWindowMenuManager(true);
3072: }
3073: };
3074:
3075: private final IBindingManagerListener bindingManagerListener = new IBindingManagerListener() {
3076:
3077: public void bindingManagerChanged(
3078: BindingManagerEvent bindingManagerEvent) {
3079: if (bindingManagerEvent.isActiveBindingsChanged()) {
3080: updateActiveWorkbenchWindowMenuManager(true);
3081: }
3082: }
3083: };
3084:
3085: /**
3086: * The source provider that tracks the activation of action sets within the
3087: * workbench. This source provider is <code>null</code> until
3088: * {@link #initializeDefaultServices()} is called.
3089: */
3090: private ActionSetSourceProvider actionSetSourceProvider;
3091:
3092: private WorkbenchWindow activeWorkbenchWindow = null;
3093:
3094: private void updateActiveWorkbenchWindowMenuManager(boolean textOnly) {
3095: if (activeWorkbenchWindow != null) {
3096: activeWorkbenchWindow
3097: .removeActionSetsListener(actionSetSourceProvider);
3098: activeWorkbenchWindow = null;
3099: }
3100: boolean actionSetsUpdated = false;
3101:
3102: final IWorkbenchWindow workbenchWindow = getActiveWorkbenchWindow();
3103:
3104: if (workbenchWindow instanceof WorkbenchWindow) {
3105: activeWorkbenchWindow = (WorkbenchWindow) workbenchWindow;
3106: if (activeWorkbenchWindow.isClosing()) {
3107: return;
3108: }
3109:
3110: // Update the action sets.
3111: final Shell windowShell = activeWorkbenchWindow.getShell();
3112: final Shell activeShell = getDisplay().getActiveShell();
3113: final IContextService service = (IContextService) getService(IContextService.class);
3114: if (Util.equals(windowShell, activeShell)
3115: || service.getShellType(activeShell) == IContextService.TYPE_WINDOW) {
3116: activeWorkbenchWindow
3117: .addActionSetsListener(actionSetSourceProvider);
3118: final WorkbenchPage page = activeWorkbenchWindow
3119: .getActiveWorkbenchPage();
3120: final IActionSetDescriptor[] newActionSets;
3121: if (page != null) {
3122: newActionSets = page.getActionSets();
3123: final ActionSetsEvent event = new ActionSetsEvent(
3124: newActionSets);
3125: actionSetSourceProvider.actionSetsChanged(event);
3126: actionSetsUpdated = true;
3127: }
3128: }
3129:
3130: final MenuManager menuManager = activeWorkbenchWindow
3131: .getMenuManager();
3132:
3133: if (textOnly) {
3134: menuManager.update(IAction.TEXT);
3135: } else {
3136: menuManager.update(true);
3137: }
3138: }
3139:
3140: if (!actionSetsUpdated) {
3141: final ActionSetsEvent event = new ActionSetsEvent(null);
3142: actionSetSourceProvider.actionSetsChanged(event);
3143: }
3144: }
3145:
3146: private ActivityPersistanceHelper activityHelper;
3147:
3148: /*
3149: * (non-Javadoc)
3150: *
3151: * @see org.eclipse.ui.IWorkbench#getIntroManager()
3152: */
3153: public IIntroManager getIntroManager() {
3154: return getWorkbenchIntroManager();
3155: }
3156:
3157: /**
3158: * @return the workbench intro manager
3159: * @since 3.0
3160: */
3161: /* package */WorkbenchIntroManager getWorkbenchIntroManager() {
3162: if (introManager == null) {
3163: introManager = new WorkbenchIntroManager(this );
3164: }
3165: return introManager;
3166: }
3167:
3168: private WorkbenchIntroManager introManager;
3169:
3170: /**
3171: * @return the intro extension for this workbench.
3172: *
3173: * @since 3.0
3174: */
3175: public IntroDescriptor getIntroDescriptor() {
3176: return introDescriptor;
3177: }
3178:
3179: /**
3180: * This method exists as a test hook. This method should <strong>NEVER</strong>
3181: * be called by clients.
3182: *
3183: * @param descriptor
3184: * The intro descriptor to use.
3185: * @since 3.0
3186: */
3187: public void setIntroDescriptor(IntroDescriptor descriptor) {
3188: if (getIntroManager().getIntro() != null) {
3189: getIntroManager().closeIntro(getIntroManager().getIntro());
3190: }
3191: introDescriptor = descriptor;
3192: }
3193:
3194: /**
3195: * The descriptor for the intro extension that is valid for this workspace,
3196: * <code>null</code> if none.
3197: */
3198: private IntroDescriptor introDescriptor;
3199:
3200: private IExtensionTracker tracker;
3201:
3202: private IRegistryChangeListener startupRegistryListener = new IRegistryChangeListener() {
3203:
3204: /*
3205: * (non-Javadoc)
3206: *
3207: * @see org.eclipse.core.runtime.IRegistryChangeListener#registryChanged(org.eclipse.core.runtime.IRegistryChangeEvent)
3208: */
3209: public void registryChanged(IRegistryChangeEvent event) {
3210: final IExtensionDelta[] deltas = event.getExtensionDeltas(
3211: PlatformUI.PLUGIN_ID,
3212: IWorkbenchRegistryConstants.PL_STARTUP);
3213: if (deltas.length == 0) {
3214: return;
3215: }
3216: final String disabledPlugins = PrefUtil
3217: .getInternalPreferenceStore()
3218: .getString(
3219: IPreferenceConstants.PLUGINS_NOT_ACTIVATED_ON_STARTUP);
3220:
3221: for (int i = 0; i < deltas.length; i++) {
3222: IExtension extension = deltas[i].getExtension();
3223: if (deltas[i].getKind() == IExtensionDelta.REMOVED) {
3224: continue;
3225: }
3226:
3227: // if the plugin is not in the set of disabled plugins,
3228: // then
3229: // execute the code to start it
3230: if (disabledPlugins.indexOf(extension.getNamespace()) == -1) {
3231: SafeRunner.run(new EarlyStartupRunnable(extension));
3232: }
3233: }
3234:
3235: }
3236: };
3237:
3238: private String factoryID;
3239:
3240: /*
3241: * (non-Javadoc)
3242: *
3243: * @see org.eclipse.ui.IWorkbench#getThemeManager()
3244: */
3245: public IThemeManager getThemeManager() {
3246: return WorkbenchThemeManager.getInstance();
3247: }
3248:
3249: /**
3250: * Returns <code>true</code> if the workbench is running,
3251: * <code>false</code> if it has been terminated.
3252: *
3253: * @return <code>true</code> if the workbench is running,
3254: * <code>false</code> if it has been terminated.
3255: */
3256: public boolean isRunning() {
3257: return runEventLoop;
3258: }
3259:
3260: /**
3261: * Return the presentation ID specified by the preference or the default ID
3262: * if undefined.
3263: *
3264: * @return the presentation ID
3265: * @see IWorkbenchPreferenceConstants#PRESENTATION_FACTORY_ID
3266: */
3267: public String getPresentationId() {
3268: if (factoryID != null) {
3269: return factoryID;
3270: }
3271:
3272: factoryID = PrefUtil.getAPIPreferenceStore().getString(
3273: IWorkbenchPreferenceConstants.PRESENTATION_FACTORY_ID);
3274:
3275: // Workaround for bug 58975 - New preference mechanism does not properly
3276: // initialize defaults
3277: // Ensure that the UI plugin has started too.
3278: if (factoryID == null || factoryID.equals("")) { //$NON-NLS-1$
3279: factoryID = IWorkbenchConstants.DEFAULT_PRESENTATION_ID;
3280: }
3281: return factoryID;
3282: }
3283:
3284: /**
3285: * <p>
3286: * Indicates the start of a large update within the workbench. This is used
3287: * to disable CPU-intensive, change-sensitive services that were temporarily
3288: * disabled in the midst of large changes. This method should always be
3289: * called in tandem with <code>largeUpdateEnd</code>, and the event loop
3290: * should not be allowed to spin before that method is called.
3291: * </p>
3292: * <p>
3293: * Important: always use with <code>largeUpdateEnd</code>!
3294: * </p>
3295: */
3296: public final void largeUpdateStart() {
3297: if (largeUpdates++ == 0) {
3298: // TODO Consider whether these lines still need to be here.
3299: // workbenchCommandSupport.setProcessing(false);
3300: // workbenchContextSupport.setProcessing(false);
3301:
3302: final IWorkbenchWindow[] windows = getWorkbenchWindows();
3303: for (int i = 0; i < windows.length; i++) {
3304: IWorkbenchWindow window = windows[i];
3305: if (window instanceof WorkbenchWindow) {
3306: ((WorkbenchWindow) window).largeUpdateStart();
3307: }
3308: }
3309: }
3310: }
3311:
3312: /**
3313: * <p>
3314: * Indicates the end of a large update within the workbench. This is used to
3315: * re-enable services that were temporarily disabled in the midst of large
3316: * changes. This method should always be called in tandem with
3317: * <code>largeUpdateStart</code>, and the event loop should not be
3318: * allowed to spin before this method is called.
3319: * </p>
3320: * <p>
3321: * Important: always protect this call by using <code>finally</code>!
3322: * </p>
3323: */
3324: public final void largeUpdateEnd() {
3325: if (--largeUpdates == 0) {
3326: // TODO Consider whether these lines still need to be here.
3327: // workbenchCommandSupport.setProcessing(true);
3328: // workbenchContextSupport.setProcessing(true);
3329:
3330: // Perform window-specific blocking.
3331: final IWorkbenchWindow[] windows = getWorkbenchWindows();
3332: for (int i = 0; i < windows.length; i++) {
3333: IWorkbenchWindow window = windows[i];
3334: if (window instanceof WorkbenchWindow) {
3335: ((WorkbenchWindow) window).largeUpdateEnd();
3336: }
3337: }
3338: }
3339: }
3340:
3341: /*
3342: * (non-Javadoc)
3343: *
3344: * @see org.eclipse.ui.IWorkbench#getExtensionTracker()
3345: */
3346: public IExtensionTracker getExtensionTracker() {
3347: if (tracker == null) {
3348: tracker = new UIExtensionTracker(getDisplay());
3349: }
3350: return tracker;
3351: }
3352:
3353: /**
3354: * Adds the listener that handles startup plugins
3355: *
3356: * @since 3.1
3357: */
3358: private void addStartupRegistryListener() {
3359: IExtensionRegistry registry = Platform.getExtensionRegistry();
3360: registry.addRegistryChangeListener(startupRegistryListener);
3361: }
3362:
3363: /*
3364: * (non-Javadoc)
3365: *
3366: * @see org.eclipse.ui.IWorkbench#getHelpSystem()
3367: */
3368: public IWorkbenchHelpSystem getHelpSystem() {
3369: return WorkbenchHelpSystem.getInstance();
3370: }
3371:
3372: /*
3373: * (non-Javadoc)
3374: *
3375: * @see org.eclipse.ui.IWorkbench#getHelpSystem()
3376: */
3377: public IWorkbenchBrowserSupport getBrowserSupport() {
3378: return WorkbenchBrowserSupport.getInstance();
3379: }
3380:
3381: /*
3382: * (non-Javadoc)
3383: *
3384: * @see org.eclipse.ui.IWorkbench#getViewRegistry()
3385: */
3386: public IViewRegistry getViewRegistry() {
3387: return WorkbenchPlugin.getDefault().getViewRegistry();
3388: }
3389:
3390: /*
3391: * (non-Javadoc)
3392: *
3393: * @see org.eclipse.ui.IWorkbench#getNewWizardRegistry()
3394: */
3395: public IWizardRegistry getNewWizardRegistry() {
3396: return WorkbenchPlugin.getDefault().getNewWizardRegistry();
3397: }
3398:
3399: /*
3400: * (non-Javadoc)
3401: *
3402: * @see org.eclipse.ui.IWorkbench#getImportWizardRegistry()
3403: */
3404: public IWizardRegistry getImportWizardRegistry() {
3405: return WorkbenchPlugin.getDefault().getImportWizardRegistry();
3406: }
3407:
3408: /*
3409: * (non-Javadoc)
3410: *
3411: * @see org.eclipse.ui.IWorkbench#getExportWizardRegistry()
3412: */
3413: public IWizardRegistry getExportWizardRegistry() {
3414: return WorkbenchPlugin.getDefault().getExportWizardRegistry();
3415: }
3416:
3417: public final Object getAdapter(final Class key) {
3418: return serviceLocator.getService(key);
3419: }
3420:
3421: private void doRestoreState(final IMemento memento,
3422: final MultiStatus status) {
3423: IMemento childMem;
3424: try {
3425: UIStats.start(UIStats.RESTORE_WORKBENCH, "MRUList"); //$NON-NLS-1$
3426: IMemento mruMemento = memento
3427: .getChild(IWorkbenchConstants.TAG_MRU_LIST);
3428: if (mruMemento != null) {
3429: status.add(getEditorHistory().restoreState(mruMemento));
3430: }
3431: } finally {
3432: UIStats.end(UIStats.RESTORE_WORKBENCH, this , "MRUList"); //$NON-NLS-1$
3433: }
3434:
3435: // Restore advisor state.
3436: IMemento advisorState = memento
3437: .getChild(IWorkbenchConstants.TAG_WORKBENCH_ADVISOR);
3438: if (advisorState != null) {
3439: status.add(getAdvisor().restoreState(advisorState));
3440: }
3441:
3442: // Get the child windows.
3443: IMemento[] children = memento
3444: .getChildren(IWorkbenchConstants.TAG_WINDOW);
3445:
3446: createdWindows = new WorkbenchWindow[children.length];
3447:
3448: // Read the workbench windows.
3449: for (int i = 0; i < children.length; i++) {
3450: childMem = children[i];
3451: final WorkbenchWindow[] newWindow = new WorkbenchWindow[1];
3452:
3453: StartupThreading
3454: .runWithoutExceptions(new StartupRunnable() {
3455:
3456: public void runWithException() {
3457: newWindow[0] = newWorkbenchWindow();
3458: newWindow[0].create();
3459: }
3460: });
3461: createdWindows[i] = newWindow[0];
3462:
3463: // allow the application to specify an initial perspective to open
3464: // @issue temporary workaround for ignoring initial perspective
3465: // String initialPerspectiveId =
3466: // getAdvisor().getInitialWindowPerspectiveId();
3467: // if (initialPerspectiveId != null) {
3468: // IPerspectiveDescriptor desc =
3469: // getPerspectiveRegistry().findPerspectiveWithId(initialPerspectiveId);
3470: // result.merge(newWindow.restoreState(childMem, desc));
3471: // }
3472: // add the window so that any work done in newWindow.restoreState
3473: // that relies on Workbench methods has windows to work with
3474: windowManager.add(newWindow[0]);
3475:
3476: // now that we've added it to the window manager we need to listen
3477: // for any exception that might hose us before we get a chance to
3478: // open it. If one occurs, remove the new window from the manager.
3479: // Assume that the new window is a phantom for now
3480: boolean restored = false;
3481: try {
3482: status.merge(newWindow[0].restoreState(childMem, null));
3483: try {
3484: newWindow[0].fireWindowRestored();
3485: } catch (WorkbenchException e) {
3486: status.add(e.getStatus());
3487: }
3488: // everything worked so far, don't close now
3489: restored = true;
3490: } finally {
3491: if (!restored) {
3492: // null the window in newWindowHolder so that it won't be
3493: // opened later on
3494: createdWindows[i] = null;
3495: StartupThreading
3496: .runWithoutExceptions(new StartupRunnable() {
3497:
3498: public void runWithException()
3499: throws Throwable {
3500: newWindow[0].close();
3501: }
3502: });
3503: }
3504: }
3505: }
3506: }
3507:
3508: private void openWindowsAfterRestore() {
3509: if (createdWindows == null) {
3510: return;
3511: }
3512: // now open the windows (except the ones that were nulled because we
3513: // closed them above)
3514: for (int i = 0; i < createdWindows.length; i++) {
3515: if (createdWindows[i] != null) {
3516: final WorkbenchWindow myWindow = createdWindows[i];
3517: StartupThreading
3518: .runWithoutExceptions(new StartupRunnable() {
3519:
3520: public void runWithException()
3521: throws Throwable {
3522: boolean opened = false;
3523: try {
3524: myWindow.open();
3525: opened = true;
3526: } finally {
3527: if (!opened) {
3528: myWindow.close();
3529: }
3530: }
3531: }
3532: });
3533: }
3534: }
3535: createdWindows = null;
3536: }
3537:
3538: /*
3539: * (non-Javadoc)
3540: *
3541: * @see org.eclipse.ui.services.IServiceLocator#getService(java.lang.Object)
3542: */
3543: public final Object getService(final Class key) {
3544: return serviceLocator.getService(key);
3545: }
3546:
3547: /*
3548: * (non-Javadoc)
3549: *
3550: * @see org.eclipse.ui.services.IServiceLocator#hasService(java.lang.Object)
3551: */
3552: public final boolean hasService(final Class key) {
3553: return serviceLocator.hasService(key);
3554: }
3555:
3556: /**
3557: * Registers a service with this locator. If there is an existing service
3558: * matching the same <code>api</code> and it implements
3559: * {@link IDisposable}, it will be disposed.
3560: *
3561: * @param api
3562: * This is the interface that the service implements. Must not be
3563: * <code>null</code>.
3564: * @param service
3565: * The service to register. This must be some implementation of
3566: * <code>api</code>. This value must not be <code>null</code>.
3567: */
3568: public final void registerService(final Class api,
3569: final Object service) {
3570: serviceLocator.registerService(api, service);
3571: }
3572:
3573: /**
3574: * The source provider that tracks which context menus (i.e., menus with
3575: * target identifiers) are now showing. This value is <code>null</code>
3576: * until {@link #initializeDefaultServices()} is called.
3577: */
3578: private MenuSourceProvider menuSourceProvider;
3579:
3580: /**
3581: * Adds the ids of a menu that is now showing to the menu source provider.
3582: * This is used for legacy action-based handlers which need to become active
3583: * only for the duration of a menu being visible.
3584: *
3585: * @param menuIds
3586: * The identifiers of the menu that is now showing; must not be
3587: * <code>null</code>.
3588: */
3589: public final void addShowingMenus(final Set menuIds,
3590: final ISelection localSelection,
3591: final ISelection localEditorInput) {
3592: menuSourceProvider.addShowingMenus(menuIds, localSelection,
3593: localEditorInput);
3594: }
3595:
3596: /**
3597: * Removes the ids of a menu that is now hidden from the menu source
3598: * provider. This is used for legacy action-based handlers which need to
3599: * become active only for the duration of a menu being visible.
3600: *
3601: * @param menuIds
3602: * The identifiers of the menu that is now hidden; must not be
3603: * <code>null</code>.
3604: */
3605: public final void removeShowingMenus(final Set menuIds,
3606: final ISelection localSelection,
3607: final ISelection localEditorInput) {
3608: menuSourceProvider.removeShowingMenus(menuIds, localSelection,
3609: localEditorInput);
3610: }
3611:
3612: /* (non-Javadoc)
3613: * @see org.eclipse.ui.IWorkbench#saveAll(org.eclipse.jface.window.IShellProvider, org.eclipse.jface.operation.IRunnableContext, org.eclipse.ui.ISaveableFilter, boolean)
3614: */
3615: public boolean saveAll(IShellProvider shellProvider,
3616: IRunnableContext runnableContext, ISaveableFilter filter,
3617: boolean confirm) {
3618: SaveablesList saveablesList = (SaveablesList) PlatformUI
3619: .getWorkbench().getService(
3620: ISaveablesLifecycleListener.class);
3621: Saveable[] saveables = saveablesList.getOpenModels();
3622: List toSave = getFilteredSaveables(filter, saveables);
3623: if (toSave.isEmpty())
3624: return true;
3625:
3626: if (!confirm) {
3627: return !saveablesList.saveModels(toSave, shellProvider,
3628: runnableContext);
3629: }
3630:
3631: // We must negate the result since false is cancel saveAll
3632: return !saveablesList.promptForSaving(toSave, shellProvider,
3633: runnableContext, true, false);
3634: }
3635:
3636: /*
3637: * Apply the given filter to the list of saveables
3638: */
3639: private List getFilteredSaveables(ISaveableFilter filter,
3640: Saveable[] saveables) {
3641: List toSave = new ArrayList();
3642: if (filter == null) {
3643: for (int i = 0; i < saveables.length; i++) {
3644: Saveable saveable = saveables[i];
3645: if (saveable.isDirty())
3646: toSave.add(saveable);
3647: }
3648: } else {
3649: SaveablesList saveablesList = (SaveablesList) getService(ISaveablesLifecycleListener.class);
3650: for (int i = 0; i < saveables.length; i++) {
3651: Saveable saveable = saveables[i];
3652: if (saveable.isDirty()) {
3653: IWorkbenchPart[] parts = saveablesList
3654: .getPartsForSaveable(saveable);
3655: if (matchesFilter(filter, saveable, parts))
3656: toSave.add(saveable);
3657: }
3658: }
3659: }
3660: return toSave;
3661: }
3662:
3663: /*
3664: * Test whether the given filter matches the saveable
3665: */
3666: private boolean matchesFilter(ISaveableFilter filter,
3667: Saveable saveable, IWorkbenchPart[] parts) {
3668: return filter == null || filter.select(saveable, parts);
3669: }
3670: }
|