KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > EditorManager


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.HashSet JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.ListIterator JavaDoc;
20 import java.util.Map JavaDoc;
21
22 import org.eclipse.core.commands.AbstractHandler;
23 import org.eclipse.core.commands.ExecutionEvent;
24 import org.eclipse.core.commands.IHandler;
25 import org.eclipse.core.runtime.Assert;
26 import org.eclipse.core.runtime.CoreException;
27 import org.eclipse.core.runtime.IConfigurationElement;
28 import org.eclipse.core.runtime.IExtension;
29 import org.eclipse.core.runtime.IPath;
30 import org.eclipse.core.runtime.IProgressMonitor;
31 import org.eclipse.core.runtime.IStatus;
32 import org.eclipse.core.runtime.MultiStatus;
33 import org.eclipse.core.runtime.SafeRunner;
34 import org.eclipse.core.runtime.Status;
35 import org.eclipse.core.runtime.SubProgressMonitor;
36 import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
37 import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
38 import org.eclipse.jface.dialogs.IDialogConstants;
39 import org.eclipse.jface.dialogs.MessageDialog;
40 import org.eclipse.jface.internal.provisional.action.ICoolBarManager2;
41 import org.eclipse.jface.operation.IRunnableContext;
42 import org.eclipse.jface.operation.IRunnableWithProgress;
43 import org.eclipse.jface.preference.IPreferenceStore;
44 import org.eclipse.jface.resource.ImageDescriptor;
45 import org.eclipse.jface.resource.ImageRegistry;
46 import org.eclipse.jface.resource.JFaceResources;
47 import org.eclipse.jface.util.IPropertyChangeListener;
48 import org.eclipse.jface.util.PropertyChangeEvent;
49 import org.eclipse.jface.util.SafeRunnable;
50 import org.eclipse.jface.viewers.ArrayContentProvider;
51 import org.eclipse.jface.window.IShellProvider;
52 import org.eclipse.osgi.util.NLS;
53 import org.eclipse.swt.custom.BusyIndicator;
54 import org.eclipse.swt.program.Program;
55 import org.eclipse.swt.widgets.Display;
56 import org.eclipse.swt.widgets.Shell;
57 import org.eclipse.ui.ActiveShellExpression;
58 import org.eclipse.ui.IEditorActionBarContributor;
59 import org.eclipse.ui.IEditorDescriptor;
60 import org.eclipse.ui.IEditorInput;
61 import org.eclipse.ui.IEditorLauncher;
62 import org.eclipse.ui.IEditorMatchingStrategy;
63 import org.eclipse.ui.IEditorPart;
64 import org.eclipse.ui.IEditorReference;
65 import org.eclipse.ui.IEditorRegistry;
66 import org.eclipse.ui.IEditorSite;
67 import org.eclipse.ui.IMemento;
68 import org.eclipse.ui.IPathEditorInput;
69 import org.eclipse.ui.IPersistableEditor;
70 import org.eclipse.ui.IPersistableElement;
71 import org.eclipse.ui.ISaveablePart;
72 import org.eclipse.ui.ISaveablePart2;
73 import org.eclipse.ui.ISaveablesLifecycleListener;
74 import org.eclipse.ui.ISaveablesSource;
75 import org.eclipse.ui.IViewPart;
76 import org.eclipse.ui.IWorkbenchPage;
77 import org.eclipse.ui.IWorkbenchPart;
78 import org.eclipse.ui.IWorkbenchPart3;
79 import org.eclipse.ui.IWorkbenchPartReference;
80 import org.eclipse.ui.IWorkbenchWindow;
81 import org.eclipse.ui.PartInitException;
82 import org.eclipse.ui.PlatformUI;
83 import org.eclipse.ui.Saveable;
84 import org.eclipse.ui.dialogs.ListSelectionDialog;
85 import org.eclipse.ui.handlers.IHandlerActivation;
86 import org.eclipse.ui.handlers.IHandlerService;
87 import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
88 import org.eclipse.ui.internal.dialogs.EventLoopProgressMonitor;
89 import org.eclipse.ui.internal.editorsupport.ComponentSupport;
90 import org.eclipse.ui.internal.misc.ExternalEditor;
91 import org.eclipse.ui.internal.misc.StatusUtil;
92 import org.eclipse.ui.internal.misc.UIStats;
93 import org.eclipse.ui.internal.part.NullEditorInput;
94 import org.eclipse.ui.internal.registry.EditorDescriptor;
95 import org.eclipse.ui.internal.registry.EditorRegistry;
96 import org.eclipse.ui.internal.tweaklets.TabBehaviour;
97 import org.eclipse.ui.internal.tweaklets.Tweaklets;
98 import org.eclipse.ui.internal.util.Util;
99 import org.eclipse.ui.model.WorkbenchPartLabelProvider;
100 import org.eclipse.ui.part.MultiEditor;
101 import org.eclipse.ui.part.MultiEditorInput;
102 import org.eclipse.ui.statushandlers.StatusManager;
103
104 /**
105  * Manage a group of element editors. Prevent the creation of two editors on the
106  * same element.
107  *
108  * 06/12/00 - DS - Given the ambiguous editor input type, the manager delegates
109  * a number of responsibilities to the editor itself.
110  *
111  * <ol>
112  * <li>The editor should determine its own title.</li>
113  * <li>The editor should listen to resource deltas and close itself if the
114  * input is deleted. It may also choose to stay open if the editor has dirty
115  * state.</li>
116  * <li>The editor should persist its own state plus editor input.</li>
117  * </ol>
118  */

119 public class EditorManager implements IExtensionChangeHandler {
120     EditorAreaHelper editorPresentation;
121
122     WorkbenchWindow window;
123
124     WorkbenchPage page;
125
126     private Map JavaDoc actionCache = new HashMap JavaDoc();
127
128     private static final String JavaDoc PIN_EDITOR_KEY = "PIN_EDITOR"; //$NON-NLS-1$
129

130     private static final String JavaDoc PIN_EDITOR = "ovr16/pinned_ovr.gif"; //$NON-NLS-1$
131

132     // When the user removes or adds the close editors automatically preference
133
// the icon should be removed or added accordingly
134
private IPropertyChangeListener editorPropChangeListnener = null;
135
136     // Handler for the pin editor keyboard shortcut
137
private IHandlerActivation pinEditorHandlerActivation = null;
138
139     static final String JavaDoc RESOURCES_TO_SAVE_MESSAGE = WorkbenchMessages.EditorManager_saveResourcesMessage;
140
141     static final String JavaDoc SAVE_RESOURCES_TITLE = WorkbenchMessages.EditorManager_saveResourcesTitle;
142
143     /**
144      * EditorManager constructor comment.
145      */

146     public EditorManager(WorkbenchWindow window, WorkbenchPage workbenchPage,
147             EditorAreaHelper pres) {
148         Assert.isNotNull(window);
149         Assert.isNotNull(workbenchPage);
150         Assert.isNotNull(pres);
151         this.window = window;
152         this.page = workbenchPage;
153         this.editorPresentation = pres;
154
155         page.getExtensionTracker().registerHandler(this, null);
156     }
157
158     /**
159      * Check to determine if the editor resources are no longer needed removes
160      * property change listener for editors removes pin editor keyboard shortcut
161      * handler disposes cached images and clears the cached images hash table
162      */

163     void checkDeleteEditorResources() {
164         // get the current number of editors
165
IEditorReference[] editors = page.getEditorReferences();
166         // If there are no editors
167
if (editors.length == 0) {
168             if (editorPropChangeListnener != null) {
169                 // remove property change listener for editors
170
IPreferenceStore prefStore = WorkbenchPlugin.getDefault()
171                         .getPreferenceStore();
172                 prefStore
173                         .removePropertyChangeListener(editorPropChangeListnener);
174                 editorPropChangeListnener = null;
175             }
176             if (pinEditorHandlerActivation != null) {
177                 // remove pin editor keyboard shortcut handler
178
final IHandlerService handlerService = (IHandlerService) window.getWorkbench().getService(IHandlerService.class);
179                 handlerService.deactivateHandler(pinEditorHandlerActivation);
180                 pinEditorHandlerActivation = null;
181             }
182         }
183     }
184
185     /**
186      * Check to determine if the property change listener for editors should be
187      * created
188      */

189     void checkCreateEditorPropListener() {
190         if (editorPropChangeListnener == null) {
191             // Add a property change listener for closing editors automatically
192
// preference
193
// Add or remove the pin icon accordingly
194
editorPropChangeListnener = new IPropertyChangeListener() {
195                 public void propertyChange(PropertyChangeEvent event) {
196                     if (event.getProperty().equals(
197                             IPreferenceConstants.REUSE_EDITORS_BOOLEAN)) {
198                         IEditorReference[] editors = getEditors();
199                         for (int i = 0; i < editors.length; i++) {
200                             ((EditorReference) editors[i]).pinStatusUpdated();
201                         }
202                     }
203                 }
204             };
205             WorkbenchPlugin.getDefault().getPreferenceStore()
206                     .addPropertyChangeListener(editorPropChangeListnener);
207         }
208     }
209
210     /**
211      * Check to determine if the handler for the pin editor keyboard shortcut
212      * should be created.
213      */

214     void checkCreatePinEditorShortcutKeyHandler() {
215         if (pinEditorHandlerActivation == null) {
216             final Shell shell = window.getShell();
217             final IHandler pinEditorHandler = new AbstractHandler() {
218                 public final Object JavaDoc execute(final ExecutionEvent event) {
219                     // check if the "Close editors automatically" preference is
220
// set
221
IPreferenceStore store = WorkbenchPlugin.getDefault().getPreferenceStore();
222                     if (store
223                             .getBoolean(IPreferenceConstants.REUSE_EDITORS_BOOLEAN)
224                             || ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).alwaysShowPinAction()) {
225
226                         IWorkbenchPartReference ref = editorPresentation
227                                 .getVisibleEditor();
228                         if (ref instanceof WorkbenchPartReference) {
229                             WorkbenchPartReference concreteRef = (WorkbenchPartReference) ref;
230
231                             concreteRef.setPinned(concreteRef.isPinned());
232                         }
233                     }
234                     return null;
235                 }
236             };
237
238             // Assign the handler for the pin editor keyboard shortcut.
239
final IHandlerService handlerService = (IHandlerService) window.getWorkbench().getService(IHandlerService.class);
240             pinEditorHandlerActivation = handlerService.activateHandler(
241                     "org.eclipse.ui.window.pinEditor", pinEditorHandler, //$NON-NLS-1$
242
new ActiveShellExpression(shell));
243         }
244     }
245
246     /**
247      * Method to create the editor's pin ImageDescriptor
248      *
249      * @return the single image descriptor for the editor's pin icon
250      */

251     ImageDescriptor getEditorPinImageDesc() {
252         ImageRegistry registry = JFaceResources.getImageRegistry();
253         ImageDescriptor pinDesc = registry.getDescriptor(PIN_EDITOR_KEY);
254         // Avoid registering twice
255
if (pinDesc == null) {
256             pinDesc = WorkbenchImages.getWorkbenchImageDescriptor(PIN_EDITOR);
257             registry.put(PIN_EDITOR_KEY, pinDesc);
258
259         }
260         return pinDesc;
261     }
262
263     /**
264      * Answer a list of dirty editors.
265      */

266     private List JavaDoc collectDirtyEditors() {
267         List JavaDoc result = new ArrayList JavaDoc(3);
268         IEditorReference[] editors = page.getEditorReferences();
269         for (int i = 0; i < editors.length; i++) {
270             IEditorPart part = (IEditorPart) editors[i].getPart(false);
271             if (part != null && part.isDirty()) {
272                 result.add(part);
273             }
274
275         }
276         return result;
277     }
278
279     /**
280      * Returns whether the manager contains an editor.
281      */

282     public boolean containsEditor(IEditorReference ref) {
283         IEditorReference[] editors = page.getEditorReferences();
284         for (int i = 0; i < editors.length; i++) {
285             if (ref == editors[i]) {
286                 return true;
287             }
288         }
289         return false;
290     }
291
292     /*
293      * Creates the action bars for an editor. Editors of the same type should
294      * share a single editor action bar, so this implementation may return an
295      * existing action bar vector.
296      */

297     private EditorActionBars createEditorActionBars(EditorDescriptor desc,
298             final IEditorSite site) {
299         // Get the editor type.
300
String JavaDoc type = desc.getId();
301
302         // If an action bar already exists for this editor type return it.
303
EditorActionBars actionBars = (EditorActionBars) actionCache.get(type);
304         if (actionBars != null) {
305             actionBars.addRef();
306             return actionBars;
307         }
308
309         // Create a new action bar set.
310
actionBars = new EditorActionBars(page, site.getWorkbenchWindow(), type);
311         actionBars.addRef();
312         actionCache.put(type, actionBars);
313
314         // Read base contributor.
315
IEditorActionBarContributor contr = desc.createActionBarContributor();
316         if (contr != null) {
317             actionBars.setEditorContributor(contr);
318             contr.init(actionBars, page);
319         }
320
321         // Read action extensions.
322
EditorActionBuilder builder = new EditorActionBuilder();
323         contr = builder.readActionExtensions(desc);
324         if (contr != null) {
325             actionBars.setExtensionContributor(contr);
326             contr.init(actionBars, page);
327         }
328
329         // Return action bars.
330
return actionBars;
331     }
332
333     /*
334      * Creates the action bars for an editor.
335      */

336     private EditorActionBars createEmptyEditorActionBars(final IEditorSite site) {
337         // Get the editor type.
338
String JavaDoc type = String.valueOf(System.currentTimeMillis());
339
340         // Create a new action bar set.
341
// Note: It is an empty set.
342
EditorActionBars actionBars = new EditorActionBars(page, site.getWorkbenchWindow(), type);
343         actionBars.addRef();
344         actionCache.put(type, actionBars);
345
346         // Return action bars.
347
return actionBars;
348     }
349
350     /*
351      * Dispose
352      */

353     void disposeEditorActionBars(EditorActionBars actionBars) {
354         actionBars.removeRef();
355         if (actionBars.getRef() <= 0) {
356             String JavaDoc type = actionBars.getEditorType();
357             actionCache.remove(type);
358             // refresh the cool bar manager before disposing of a cool item
359
ICoolBarManager2 coolBar = (ICoolBarManager2) window.getCoolBarManager2();
360             if (coolBar != null) {
361                 coolBar.refresh();
362             }
363             actionBars.dispose();
364         }
365     }
366
367     /**
368      * Returns an open editor matching the given editor input. If none match,
369      * returns <code>null</code>.
370      *
371      * @param input
372      * the editor input
373      * @return the matching editor, or <code>null</code> if no match fond
374      */

375     public IEditorPart findEditor(IEditorInput input) {
376         return findEditor(null, input, IWorkbenchPage.MATCH_INPUT);
377     }
378
379     /**
380      * Returns an open editor matching the given editor input and/or editor id,
381      * as specified by matchFlags. If none match, returns <code>null</code>.
382      *
383      * @param editorId
384      * the editor id
385      * @param input
386      * the editor input
387      * @param matchFlags
388      * flags specifying which aspects to match
389      * @return the matching editor, or <code>null</code> if no match fond
390      * @since 3.1
391      */

392     public IEditorPart findEditor(String JavaDoc editorId, IEditorInput input,
393             int matchFlags) {
394         IEditorReference[] refs = findEditors(input, editorId, matchFlags);
395         if (refs.length == 0) {
396             return null;
397         }
398         return refs[0].getEditor(true);
399     }
400
401     /**
402      * Returns the open editor references matching the given editor input and/or
403      * editor id, as specified by matchFlags. If none match, returns an empty
404      * array.
405      *
406      * @param editorId
407      * the editor id
408      * @param input
409      * the editor input
410      * @param matchFlags
411      * flags specifying which aspects to match
412      * @return the matching editor, or <code>null</code> if no match fond
413      * @since 3.1
414      */

415     public IEditorReference[] findEditors(IEditorInput input, String JavaDoc editorId,
416             int matchFlags) {
417         if (matchFlags == IWorkbenchPage.MATCH_NONE) {
418             return new IEditorReference[0];
419         }
420         List JavaDoc result = new ArrayList JavaDoc();
421         ArrayList JavaDoc othersList = new ArrayList JavaDoc(Arrays.asList(page
422                 .getEditorReferences()));
423         if (!othersList.isEmpty()) {
424             IEditorReference active = page.getActiveEditorReference();
425             if (active != null) {
426                 othersList.remove(active);
427                 ArrayList JavaDoc activeList = new ArrayList JavaDoc(1);
428                 activeList.add(active);
429                 findEditors(activeList, input, editorId, matchFlags, result);
430             }
431             findEditors(othersList, input, editorId, matchFlags, result);
432         }
433         return (IEditorReference[]) result.toArray(new IEditorReference[result
434                 .size()]);
435     }
436
437     /**
438      * Returns an open editor matching the given editor id and/or editor input.
439      * Returns <code>null</code> if none match.
440      *
441      * @param editorId
442      * the editor id
443      * @param input
444      * the editor input
445      * @param editorList
446      * a mutable list containing the references for the editors to
447      * check (warning: items may be removed)
448      * @param result
449      * the list to which matching editor references should be added
450      * @since 3.1
451      */

452     private void findEditors(List JavaDoc editorList, IEditorInput input,
453             String JavaDoc editorId, int matchFlags, List JavaDoc result) {
454         if (matchFlags == IWorkbenchPage.MATCH_NONE) {
455             return;
456         }
457
458         // Phase 0: Remove editors whose ids don't match (if matching by id)
459
if (((matchFlags & IWorkbenchPage.MATCH_ID) != 0) && editorId != null) {
460             for (Iterator JavaDoc i = editorList.iterator(); i.hasNext();) {
461                 EditorReference editor = (EditorReference) i.next();
462                 if (!editorId.equals(editor.getId())) {
463                     i.remove();
464                 }
465             }
466         }
467
468         // If not matching on editor input, just return the remaining editors.
469
// In practice, this case is never used.
470
if ((matchFlags & IWorkbenchPage.MATCH_INPUT) == 0) {
471             result.addAll(editorList);
472             return;
473         }
474
475         // Phase 1: check editors that have their own matching strategy
476
for (Iterator JavaDoc i = editorList.iterator(); i.hasNext();) {
477             EditorReference editor = (EditorReference) i.next();
478             IEditorDescriptor desc = editor.getDescriptor();
479             if (desc != null) {
480                 IEditorMatchingStrategy matchingStrategy = desc
481                         .getEditorMatchingStrategy();
482                 if (matchingStrategy != null) {
483                     i.remove(); // We're handling this one here, so remove it
484
// from the list.
485
if (matchingStrategy.matches(editor, input)) {
486                         result.add(editor);
487                     }
488                 }
489             }
490         }
491
492         // Phase 2: check materialized editors (without their own matching
493
// strategy)
494
for (Iterator JavaDoc i = editorList.iterator(); i.hasNext();) {
495             IEditorReference editor = (IEditorReference) i.next();
496             IEditorPart part = (IEditorPart) editor.getPart(false);
497             if (part != null) {
498                 i.remove(); // We're handling this one here, so remove it from
499
// the list.
500
if (part.getEditorInput() != null
501                         && part.getEditorInput().equals(input)) {
502                     result.add(editor);
503                 }
504             }
505         }
506
507         // Phase 3: check unmaterialized editors for input equality,
508
// delaying plug-in activation further by only restoring the editor
509
// input
510
// if the editor reference's factory id and name match.
511
String JavaDoc name = input.getName();
512         IPersistableElement persistable = input.getPersistable();
513         if (name == null || persistable == null) {
514             return;
515         }
516         String JavaDoc id = persistable.getFactoryId();
517         if (id == null) {
518             return;
519         }
520         for (Iterator JavaDoc i = editorList.iterator(); i.hasNext();) {
521             EditorReference editor = (EditorReference) i.next();
522             if (name.equals(editor.getName())
523                     && id.equals(editor.getFactoryId())) {
524                 IEditorInput restoredInput;
525                 try {
526                     restoredInput = editor.getEditorInput();
527                     if (Util.equals(restoredInput, input)) {
528                         result.add(editor);
529                     }
530                 } catch (PartInitException e1) {
531                     WorkbenchPlugin.log(e1);
532                 }
533             }
534         }
535     }
536
537     /**
538      * Returns the SWT Display.
539      */

540     private Display getDisplay() {
541         return window.getShell().getDisplay();
542     }
543
544     /**
545      * Answer the number of editors.
546      */

547     public int getEditorCount() {
548         return page.getEditorReferences().length;
549     }
550
551     /*
552      * Answer the editor registry.
553      */

554     private IEditorRegistry getEditorRegistry() {
555         return WorkbenchPlugin.getDefault().getEditorRegistry();
556     }
557
558     /*
559      * See IWorkbenchPage.
560      */

561     public IEditorPart[] getDirtyEditors() {
562         List JavaDoc dirtyEditors = collectDirtyEditors();
563         return (IEditorPart[]) dirtyEditors
564                 .toArray(new IEditorPart[dirtyEditors.size()]);
565     }
566
567     /*
568      * See IWorkbenchPage.
569      */

570     public IEditorReference[] getEditors() {
571         return page.getEditorReferences();
572     }
573
574     /*
575      * See IWorkbenchPage#getFocusEditor
576      */

577     public IEditorPart getVisibleEditor() {
578         IEditorReference ref = editorPresentation.getVisibleEditor();
579         if (ref == null) {
580             return null;
581         }
582         return (IEditorPart) ref.getPart(true);
583     }
584
585     /**
586      * Answer true if save is needed in any one of the editors.
587      */

588     public boolean isSaveAllNeeded() {
589         IEditorReference[] editors = page.getEditorReferences();
590         for (int i = 0; i < editors.length; i++) {
591             IEditorReference ed = editors[i];
592             if (ed.isDirty()) {
593                 return true;
594             }
595         }
596         return false;
597     }
598
599     /*
600      * Prompt the user to save the reusable editor. Return false if a new editor
601      * should be opened.
602      */

603     private IEditorReference findReusableEditor(EditorDescriptor desc) {
604         return ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).findReusableEditor(page);
605     }
606
607     /**
608      * @param editorId
609      * the editor part id
610      * @param input
611      * the input
612      * @param setVisible
613      * if this is to be created visible ... not used
614      * @param editorState
615      * an {@link IMemento} &lt;editorState&gt; for persistable
616      * editors. Can be <code>null</code>.
617      * @return a created editor reference
618      * @throws PartInitException
619      */

620     public IEditorReference openEditor(String JavaDoc editorId, IEditorInput input,
621             boolean setVisible, IMemento editorState) throws PartInitException {
622         if (editorId == null || input == null) {
623             throw new IllegalArgumentException JavaDoc();
624         }
625
626         IEditorRegistry reg = getEditorRegistry();
627         EditorDescriptor desc = (EditorDescriptor) reg.findEditor(editorId);
628         if (desc == null) {
629             throw new PartInitException(NLS.bind(
630                     WorkbenchMessages.EditorManager_unknownEditorIDMessage,
631                     editorId));
632         }
633
634         IEditorReference result = openEditorFromDescriptor(desc, input, editorState);
635         return result;
636     }
637
638     /*
639      * Open a new editor
640      */

641     public IEditorReference openEditorFromDescriptor(EditorDescriptor desc,
642             IEditorInput input, IMemento editorState) throws PartInitException {
643         IEditorReference result = null;
644         if (desc.isInternal()) {
645             result = reuseInternalEditor(desc, input);
646             if (result == null) {
647                 result = new EditorReference(this, input, desc, editorState);
648             }
649         } else if (desc.getId()
650                 .equals(IEditorRegistry.SYSTEM_INPLACE_EDITOR_ID)) {
651             if (ComponentSupport.inPlaceEditorSupported()) {
652                 result = new EditorReference(this, input, desc);
653             }
654         } else if (desc.getId().equals(
655                 IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID)) {
656             IPathEditorInput pathInput = getPathEditorInput(input);
657             if (pathInput != null) {
658                 result = openSystemExternalEditor(pathInput.getPath());
659             } else {
660                 throw new PartInitException(
661                         WorkbenchMessages.EditorManager_systemEditorError);
662             }
663         } else if (desc.isOpenExternal()) {
664             result = openExternalEditor(desc, input);
665         } else {
666             // this should never happen
667
throw new PartInitException(NLS.bind(
668                     WorkbenchMessages.EditorManager_invalidDescriptor, desc
669                             .getId()));
670         }
671
672         if (result != null) {
673             createEditorTab((EditorReference) result, ""); //$NON-NLS-1$
674
}
675
676         Workbench wb = (Workbench) window.getWorkbench();
677         wb.getEditorHistory().add(input, desc);
678         return result;
679     }
680
681     /**
682      * Open a specific external editor on an file based on the descriptor.
683      */

684     private IEditorReference openExternalEditor(final EditorDescriptor desc,
685             IEditorInput input) throws PartInitException {
686         final CoreException ex[] = new CoreException[1];
687
688         final IPathEditorInput pathInput = getPathEditorInput(input);
689         if (pathInput != null && pathInput.getPath() != null) {
690             BusyIndicator.showWhile(getDisplay(), new Runnable JavaDoc() {
691                 public void run() {
692                     try {
693                         if (desc.getLauncher() != null) {
694                             // open using launcher
695
Object JavaDoc launcher = WorkbenchPlugin.createExtension(
696                                     desc.getConfigurationElement(), "launcher"); //$NON-NLS-1$
697
((IEditorLauncher) launcher).open(pathInput
698                                     .getPath());
699                         } else {
700                             // open using command
701
ExternalEditor oEditor = new ExternalEditor(
702                                     pathInput.getPath(), desc);
703                             oEditor.open();
704                         }
705                     } catch (CoreException e) {
706                         ex[0] = e;
707                     }
708                 }
709             });
710         } else {
711             throw new PartInitException(NLS.bind(
712                     WorkbenchMessages.EditorManager_errorOpeningExternalEditor,
713                     desc.getFileName(), desc.getId()));
714         }
715
716         if (ex[0] != null) {
717             throw new PartInitException(NLS.bind(
718                     WorkbenchMessages.EditorManager_errorOpeningExternalEditor,
719                     desc.getFileName(), desc.getId()), ex[0]);
720         }
721
722         // we do not have an editor part for external editors
723
return null;
724     }
725
726     /**
727      * Create the part and reference for each inner editor.
728      *
729      * @param ref
730      * the MultiEditor reference
731      * @param part
732      * the part
733      * @param input
734      * the MultiEditor input
735      * @return the array of inner references to store in the MultiEditor reference
736      */

737     IEditorReference[] openMultiEditor(final IEditorReference ref,
738             final MultiEditor part, final MultiEditorInput input)
739             throws PartInitException {
740
741         String JavaDoc[] editorArray = input.getEditors();
742         IEditorInput[] inputArray = input.getInput();
743
744         // find all descriptors
745
EditorDescriptor[] descArray = new EditorDescriptor[editorArray.length];
746         IEditorReference refArray[] = new IEditorReference[editorArray.length];
747         IEditorPart partArray[] = new IEditorPart[editorArray.length];
748
749         IEditorRegistry reg = getEditorRegistry();
750         for (int i = 0; i < editorArray.length; i++) {
751             EditorDescriptor innerDesc = (EditorDescriptor) reg
752                     .findEditor(editorArray[i]);
753             if (innerDesc == null) {
754                 throw new PartInitException(NLS.bind(
755                         WorkbenchMessages.EditorManager_unknownEditorIDMessage,
756                         editorArray[i]));
757             }
758             descArray[i] = innerDesc;
759             InnerEditor innerRef = new InnerEditor(ref, inputArray[i],
760                     descArray[i]);
761             refArray[i] = innerRef;
762             partArray[i] = innerRef.getEditor(true);
763         }
764         part.setChildren(partArray);
765         return refArray;
766     }
767
768     /*
769      * Opens an editor part.
770      */

771     private void createEditorTab(final EditorReference ref,
772             final String JavaDoc workbookId) throws PartInitException {
773
774         editorPresentation.addEditor(ref, workbookId);
775
776     }
777
778     /*
779      * Create the site and initialize it with its action bars.
780      */

781     EditorSite createSite(final IEditorReference ref, final IEditorPart part,
782             final EditorDescriptor desc, final IEditorInput input)
783             throws PartInitException {
784         EditorSite site = new EditorSite(ref, part, page, desc);
785         if (desc != null) {
786             site.setActionBars(createEditorActionBars(desc, site));
787         } else {
788             site.setActionBars(createEmptyEditorActionBars(site));
789         }
790         final String JavaDoc label = part.getTitle(); // debugging only
791
try {
792             try {
793                 UIStats.start(UIStats.INIT_PART, label);
794                 part.init(site, input);
795             } finally {
796                 UIStats.end(UIStats.INIT_PART, part, label);
797             }
798
799             // Sanity-check the site
800
if (part.getSite() != site || part.getEditorSite() != site) {
801                 throw new PartInitException(NLS.bind(
802                         WorkbenchMessages.EditorManager_siteIncorrect, desc
803                                 .getId()));
804             }
805
806         } catch (Exception JavaDoc e) {
807             disposeEditorActionBars((EditorActionBars) site.getActionBars());
808             site.dispose();
809             if (e instanceof PartInitException) {
810                 throw (PartInitException) e;
811             }
812
813             throw new PartInitException(
814                     WorkbenchMessages.EditorManager_errorInInit, e);
815         }
816
817         return site;
818     }
819
820     /*
821      * See IWorkbenchPage.
822      */

823     private IEditorReference reuseInternalEditor(EditorDescriptor desc,
824             IEditorInput input) throws PartInitException {
825
826         Assert.isNotNull(desc, "descriptor must not be null"); //$NON-NLS-1$
827
Assert.isNotNull(input, "input must not be null"); //$NON-NLS-1$
828

829         IEditorReference reusableEditorRef = findReusableEditor(desc);
830         if (reusableEditorRef != null) {
831             return ((TabBehaviour) Tweaklets.get(TabBehaviour.KEY))
832                     .reuseInternalEditor(page, this, editorPresentation, desc,
833                             input, reusableEditorRef);
834         }
835         return null;
836     }
837
838     IEditorPart createPart(final EditorDescriptor desc)
839             throws PartInitException {
840         try {
841             IEditorPart result = desc.createEditor();
842             IConfigurationElement element = desc.getConfigurationElement();
843             if (element != null) {
844                 page.getExtensionTracker().registerObject(
845                         element.getDeclaringExtension(), result,
846                         IExtensionTracker.REF_WEAK);
847             }
848             return result;
849         } catch (CoreException e) {
850             throw new PartInitException(StatusUtil.newStatus(
851                     desc.getPluginID(),
852                     WorkbenchMessages.EditorManager_instantiationError, e));
853         }
854     }
855
856     /**
857      * Open a system external editor on the input path.
858      */

859     private IEditorReference openSystemExternalEditor(final IPath location)
860             throws PartInitException {
861         if (location == null) {
862             throw new IllegalArgumentException JavaDoc();
863         }
864
865         final boolean result[] = { false };
866         BusyIndicator.showWhile(getDisplay(), new Runnable JavaDoc() {
867             public void run() {
868                 if (location != null) {
869                     result[0] = Program.launch(location.toOSString());
870                 }
871             }
872         });
873
874         if (!result[0]) {
875             throw new PartInitException(NLS.bind(
876                     WorkbenchMessages.EditorManager_unableToOpenExternalEditor,
877                     location));
878         }
879
880         // We do not have an editor part for external editors
881
return null;
882     }
883
884     ImageDescriptor findImage(EditorDescriptor desc, IPath path) {
885         if (desc == null) {
886             // @issue what should be the default image?
887
return ImageDescriptor.getMissingImageDescriptor();
888         }
889
890         if (desc.isOpenExternal() && path != null) {
891             return PlatformUI.getWorkbench().getEditorRegistry()
892                     .getImageDescriptor(path.toOSString());
893         }
894
895         return desc.getImageDescriptor();
896     }
897
898     /**
899      * @see org.eclipse.ui.IPersistable
900      */

901     public IStatus restoreState(IMemento memento) {
902         // Restore the editor area workbooks layout/relationship
903
final MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID,
904                 IStatus.OK,
905                 WorkbenchMessages.EditorManager_problemsRestoringEditors, null);
906         final String JavaDoc activeWorkbookID[] = new String JavaDoc[1];
907         final ArrayList JavaDoc visibleEditors = new ArrayList JavaDoc(5);
908         final IEditorReference activeEditor[] = new IEditorReference[1];
909
910         IMemento areaMem = memento.getChild(IWorkbenchConstants.TAG_AREA);
911         if (areaMem != null) {
912             result.add(editorPresentation.restoreState(areaMem));
913             activeWorkbookID[0] = areaMem
914                     .getString(IWorkbenchConstants.TAG_ACTIVE_WORKBOOK);
915         }
916
917         // Loop through the editors.
918

919         IMemento[] editorMems = memento
920                 .getChildren(IWorkbenchConstants.TAG_EDITOR);
921         for (int x = 0; x < editorMems.length; x++) {
922             // for dynamic UI - call restoreEditorState to replace code which is
923
// commented out
924
restoreEditorState(editorMems[x], visibleEditors, activeEditor,
925                     result);
926         }
927
928         // restore the presentation
929
if (areaMem != null) {
930             result.add(editorPresentation.restorePresentationState(areaMem));
931         }
932         try {
933             StartupThreading.runWithThrowable(new StartupRunnable(){
934
935                 public void runWithException() throws Throwable JavaDoc {
936                     // Update each workbook with its visible editor.
937
for (int i = 0; i < visibleEditors.size(); i++) {
938                         setVisibleEditor((IEditorReference) visibleEditors.get(i),
939                                 false);
940                     }
941
942                     // Update the active workbook
943
if (activeWorkbookID[0] != null) {
944                         editorPresentation
945                                 .setActiveEditorWorkbookFromID(activeWorkbookID[0]);
946                     }
947
948                     if (activeEditor[0] != null) {
949                         IWorkbenchPart editor = activeEditor[0].getPart(true);
950
951                         if (editor != null) {
952                             page.activate(editor);
953                         }
954                     }
955                 }});
956         }
957         catch (Throwable JavaDoc t) {
958             // The exception is already logged.
959
result
960                     .add(new Status(
961                             IStatus.ERROR,
962                             PlatformUI.PLUGIN_ID,
963                             0,
964                             WorkbenchMessages.EditorManager_exceptionRestoringEditor,
965                             t));
966         }
967         
968         return result;
969     }
970
971     /**
972      * Save all of the editors in the workbench. Return true if successful.
973      * Return false if the user has canceled the command.
974      * @param confirm true if the user should be prompted before the save
975      * @param closing true if the page is being closed
976      * @param addNonPartSources true if saveables from non-part sources should be saved too.
977      * @return false if the user canceled or an error occurred while saving
978      */

979     public boolean saveAll(boolean confirm, boolean closing, boolean addNonPartSources) {
980         // Get the list of dirty editors and views. If it is
981
// empty just return.
982
ISaveablePart[] parts = page.getDirtyParts();
983         if (parts.length == 0) {
984             return true;
985         }
986         // saveAll below expects a mutable list
987
List JavaDoc dirtyParts = new ArrayList JavaDoc(parts.length);
988         for (int i = 0; i < parts.length; i++) {
989             dirtyParts.add(parts[i]);
990         }
991
992         // If confirmation is required ..
993
return saveAll(dirtyParts, confirm, closing, addNonPartSources, window);
994     }
995
996     /**
997      * Saves the given dirty editors and views, optionally prompting the user.
998      *
999      * @param dirtyParts
1000     * the dirty views and editors
1001     * @param confirm
1002     * <code>true</code> to prompt whether to save, <code>false</code>
1003     * to save without prompting
1004     * @param closing
1005     * <code>true</code> if the parts are being closed,
1006     * <code>false</code> if just being saved without closing
1007     * @param addNonPartSources true if non-part sources should be saved too
1008     * @param window
1009     * the window to use as the parent for the dialog that prompts to
1010     * save multiple dirty editors and views
1011     * @return <code>true</code> on success, <code>false</code> if the user
1012     * canceled the save or an error occurred while saving
1013     */

1014    public static boolean saveAll(List JavaDoc dirtyParts, boolean confirm, boolean closing,
1015            boolean addNonPartSources, final IWorkbenchWindow window) {
1016        return saveAll(dirtyParts, confirm, closing, addNonPartSources, window, window);
1017    }
1018    
1019    /**
1020     * Saves the given dirty editors and views, optionally prompting the user.
1021     *
1022     * @param dirtyParts
1023     * the dirty views and editors
1024     * @param confirm
1025     * <code>true</code> to prompt whether to save,
1026     * <code>false</code> to save without prompting
1027     * @param closing
1028     * <code>true</code> if the parts are being closed,
1029     * <code>false</code> if just being saved without closing
1030     * @param addNonPartSources
1031     * true if non-part sources should be saved too
1032     * @param runnableContext
1033     * the context in which to run long-running operations
1034     * @param shellProvider
1035     * providing the shell to use as the parent for the dialog that
1036     * prompts to save multiple dirty editors and views
1037     * @return <code>true</code> on success, <code>false</code> if the user
1038     * canceled the save
1039     */

1040    public static boolean saveAll(List JavaDoc dirtyParts, final boolean confirm, final boolean closing,
1041                boolean addNonPartSources, final IRunnableContext runnableContext, final IShellProvider shellProvider) {
1042        // clone the input list
1043
dirtyParts = new ArrayList JavaDoc(dirtyParts);
1044        List JavaDoc modelsToSave;
1045        if (confirm) {
1046            boolean saveable2Processed = false;
1047            // Process all parts that implement ISaveablePart2.
1048
// These parts are removed from the list after saving
1049
// them. We then need to restore the workbench to
1050
// its previous state, for now this is just last
1051
// active perspective.
1052
// Note that the given parts may come from multiple
1053
// windows, pages and perspectives.
1054
ListIterator JavaDoc listIterator = dirtyParts.listIterator();
1055
1056            WorkbenchPage currentPage = null;
1057            Perspective currentPageOriginalPerspective = null;
1058            while (listIterator.hasNext()) {
1059                IWorkbenchPart part = (IWorkbenchPart) listIterator.next();
1060                if (part instanceof ISaveablePart2) {
1061                    WorkbenchPage page = (WorkbenchPage) part.getSite()
1062                            .getPage();
1063                    if (!Util.equals(currentPage, page)) {
1064                        if (currentPage != null
1065                                && currentPageOriginalPerspective != null) {
1066                            if (!currentPageOriginalPerspective
1067                                    .equals(currentPage.getActivePerspective())) {
1068                                currentPage
1069                                        .setPerspective(currentPageOriginalPerspective
1070                                                .getDesc());
1071                            }
1072                        }
1073                        currentPage = page;
1074                        currentPageOriginalPerspective = page
1075                                .getActivePerspective();
1076                    }
1077                    if (confirm) {
1078                        if (part instanceof IViewPart) {
1079                            Perspective perspective = page
1080                                    .getFirstPerspectiveWithView((IViewPart) part);
1081                            if (perspective != null) {
1082                                page.setPerspective(perspective.getDesc());
1083                            }
1084                        }
1085                        // show the window containing the page?
1086
IWorkbenchWindow partsWindow = page
1087                                .getWorkbenchWindow();
1088                        if (partsWindow != partsWindow.getWorkbench()
1089                                .getActiveWorkbenchWindow()) {
1090                            Shell shell = partsWindow.getShell();
1091                            if (shell.getMinimized()) {
1092                                shell.setMinimized(false);
1093                            }
1094                            shell.setActive();
1095                        }
1096                        page.bringToTop(part);
1097                    }
1098                    // try to save the part
1099
int choice = SaveableHelper.savePart((ISaveablePart2) part,
1100                            page.getWorkbenchWindow(), confirm);
1101                    if (choice == ISaveablePart2.CANCEL) {
1102                        // If the user cancels, don't restore the previous
1103
// workbench state, as that will
1104
// be an unexpected switch from the current state.
1105
return false;
1106                    } else if (choice != ISaveablePart2.DEFAULT) {
1107                        saveable2Processed = true;
1108                        listIterator.remove();
1109                    }
1110                }
1111            }
1112
1113            // try to restore the workbench to its previous state
1114
if (currentPage != null && currentPageOriginalPerspective != null) {
1115                if (!currentPageOriginalPerspective.equals(currentPage
1116                        .getActivePerspective())) {
1117                    currentPage.setPerspective(currentPageOriginalPerspective
1118                            .getDesc());
1119                }
1120            }
1121
1122            // if processing a ISaveablePart2 caused other parts to be
1123
// saved, remove them from the list presented to the user.
1124
if (saveable2Processed) {
1125                listIterator = dirtyParts.listIterator();
1126                while (listIterator.hasNext()) {
1127                    ISaveablePart part = (ISaveablePart) listIterator.next();
1128                    if (!part.isDirty()) {
1129                        listIterator.remove();
1130                    }
1131                }
1132            }
1133
1134            modelsToSave = convertToSaveables(dirtyParts, closing, addNonPartSources);
1135            
1136            // If nothing to save, return.
1137
if (modelsToSave.isEmpty()) {
1138                return true;
1139            }
1140            boolean canceled = SaveableHelper.waitForBackgroundSaveJobs(modelsToSave);
1141            if (canceled) {
1142                return false;
1143            }
1144            // Use a simpler dialog if there's only one
1145
if (modelsToSave.size() == 1) {
1146                Saveable model = (Saveable) modelsToSave.get(0);
1147                String JavaDoc message = NLS.bind(WorkbenchMessages.EditorManager_saveChangesQuestion, model.getName());
1148                // Show a dialog.
1149
String JavaDoc[] buttons = new String JavaDoc[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL };
1150                MessageDialog d = new MessageDialog(
1151                    shellProvider.getShell(), WorkbenchMessages.Save_Resource,
1152                    null, message, MessageDialog.QUESTION, buttons, 0);
1153                
1154                int choice = SaveableHelper.testGetAutomatedResponse();
1155                if (SaveableHelper.testGetAutomatedResponse() == SaveableHelper.USER_RESPONSE) {
1156                    choice = d.open();
1157                }
1158
1159                // Branch on the user choice.
1160
// The choice id is based on the order of button labels
1161
// above.
1162
switch (choice) {
1163                case ISaveablePart2.YES: // yes
1164
break;
1165                case ISaveablePart2.NO: // no
1166
return true;
1167                default:
1168                case ISaveablePart2.CANCEL: // cancel
1169
return false;
1170                }
1171            }
1172            else {
1173                ListSelectionDialog dlg = new ListSelectionDialog(
1174                        shellProvider.getShell(), modelsToSave,
1175                        new ArrayContentProvider(),
1176                        new WorkbenchPartLabelProvider(), RESOURCES_TO_SAVE_MESSAGE);
1177                dlg.setInitialSelections(modelsToSave.toArray());
1178                dlg.setTitle(SAVE_RESOURCES_TITLE);
1179    
1180                // this "if" statement aids in testing.
1181
if (SaveableHelper.testGetAutomatedResponse()==SaveableHelper.USER_RESPONSE) {
1182                    int result = dlg.open();
1183                    //Just return false to prevent the operation continuing
1184
if (result == IDialogConstants.CANCEL_ID) {
1185                        return false;
1186                    }
1187    
1188                    modelsToSave = Arrays.asList(dlg.getResult());
1189                }
1190            }
1191        }
1192        else {
1193            modelsToSave = convertToSaveables(dirtyParts, closing, addNonPartSources);
1194        }
1195
1196        // If the editor list is empty return.
1197
if (modelsToSave.isEmpty()) {
1198            return true;
1199        }
1200        
1201        // Create save block.
1202
final List JavaDoc finalModels = modelsToSave;
1203        IRunnableWithProgress progressOp = new IRunnableWithProgress() {
1204            public void run(IProgressMonitor monitor) {
1205                IProgressMonitor monitorWrap = new EventLoopProgressMonitor(
1206                        monitor);
1207                monitorWrap.beginTask("", finalModels.size()); //$NON-NLS-1$
1208
for (Iterator JavaDoc i = finalModels.iterator(); i.hasNext();) {
1209                    Saveable model = (Saveable) i.next();
1210                    // handle case where this model got saved as a result of saving another
1211
if (!model.isDirty()) {
1212                        monitor.worked(1);
1213                        continue;
1214                    }
1215                    SaveableHelper.doSaveModel(model, new SubProgressMonitor(monitorWrap, 1), shellProvider, closing || confirm);
1216                    if (monitorWrap.isCanceled()) {
1217                        break;
1218                    }
1219                }
1220                monitorWrap.done();
1221            }
1222        };
1223
1224        // Do the save.
1225
return SaveableHelper.runProgressMonitorOperation(
1226                WorkbenchMessages.Save_All, progressOp, runnableContext, shellProvider);
1227    }
1228
1229    /**
1230     * For each part (view or editor) in the given list, attempts to convert it
1231     * to one or more saveable models. Duplicate models are removed. If closing
1232     * is true, then models that will remain open in parts other than the given
1233     * parts are removed.
1234     *
1235     * @param parts
1236     * the parts (list of IViewPart or IEditorPart)
1237     * @param closing
1238     * whether the parts are being closed
1239     * @param addNonPartSources
1240     * whether non-part sources should be added (true for the Save
1241     * All action, see bug 139004)
1242     * @return the dirty models
1243     */

1244    private static List JavaDoc convertToSaveables(List JavaDoc parts, boolean closing, boolean addNonPartSources) {
1245        ArrayList JavaDoc result = new ArrayList JavaDoc();
1246        HashSet JavaDoc seen = new HashSet JavaDoc();
1247        for (Iterator JavaDoc i = parts.iterator(); i.hasNext();) {
1248            IWorkbenchPart part = (IWorkbenchPart) i.next();
1249            Saveable[] saveables = getSaveables(part);
1250            for (int j = 0; j < saveables.length; j++) {
1251                Saveable saveable = saveables[j];
1252                if (saveable.isDirty() && !seen.contains(saveable)) {
1253                    seen.add(saveable);
1254                    if (!closing
1255                            || closingLastPartShowingModel(saveable, parts, part
1256                                    .getSite().getPage())) {
1257                        result.add(saveable);
1258                    }
1259                }
1260            }
1261        }
1262        if (addNonPartSources) {
1263            SaveablesList saveablesList = (SaveablesList) PlatformUI
1264                    .getWorkbench().getService(
1265                            ISaveablesLifecycleListener.class);
1266            ISaveablesSource[] nonPartSources = saveablesList
1267                    .getNonPartSources();
1268            for (int i = 0; i < nonPartSources.length; i++) {
1269                Saveable[] saveables = nonPartSources[i].getSaveables();
1270                for (int j = 0; j < saveables.length; j++) {
1271                    Saveable saveable = saveables[j];
1272                    if (saveable.isDirty() && !seen.contains(saveable)) {
1273                        seen.add(saveable);
1274                        result.add(saveable);
1275                    }
1276                }
1277            }
1278        }
1279        return result;
1280    }
1281
1282    /**
1283     * Returns the saveable models provided by the given part.
1284     * If the part does not provide any models, a default model
1285     * is returned representing the part.
1286     *
1287     * @param part the workbench part
1288     * @return the saveable models
1289     */

1290    private static Saveable[] getSaveables(IWorkbenchPart part) {
1291        if (part instanceof ISaveablesSource) {
1292            ISaveablesSource source = (ISaveablesSource) part;
1293            return source.getSaveables();
1294        }
1295        return new Saveable[] { new DefaultSaveable(part) };
1296    }
1297
1298    /**
1299     * Returns true if, in the given page, no more parts will reference the
1300     * given model if the given parts are closed.
1301     *
1302     * @param model
1303     * the model
1304     * @param closingParts
1305     * the parts being closed (list of IViewPart or IEditorPart)
1306     * @param page
1307     * the page
1308     * @return <code>true</code> if no more parts in the page will reference
1309     * the given model, <code>false</code> otherwise
1310     */

1311    private static boolean closingLastPartShowingModel(Saveable model,
1312            List JavaDoc closingParts, IWorkbenchPage page) {
1313        HashSet JavaDoc closingPartsWithSameModel = new HashSet JavaDoc();
1314        for (Iterator JavaDoc i = closingParts.iterator(); i.hasNext();) {
1315            IWorkbenchPart part = (IWorkbenchPart) i.next();
1316            Saveable[] models = getSaveables(part);
1317            if (Arrays.asList(models).contains(model)) {
1318                closingPartsWithSameModel.add(part);
1319            }
1320        }
1321        IWorkbenchPartReference[] pagePartRefs = ((WorkbenchPage) page).getAllParts();
1322        HashSet JavaDoc pagePartsWithSameModels = new HashSet JavaDoc();
1323        for (int i = 0; i < pagePartRefs.length; i++) {
1324            IWorkbenchPartReference partRef = pagePartRefs[i];
1325            IWorkbenchPart part = partRef.getPart(false);
1326            if (part != null) {
1327                Saveable[] models = getSaveables(part);
1328                if (Arrays.asList(models).contains(model)) {
1329                    pagePartsWithSameModels.add(part);
1330                }
1331            }
1332        }
1333        for (Iterator JavaDoc i = closingPartsWithSameModel.iterator(); i.hasNext();) {
1334            IWorkbenchPart part = (IWorkbenchPart) i.next();
1335            pagePartsWithSameModels.remove(part);
1336        }
1337        return pagePartsWithSameModels.isEmpty();
1338    }
1339    
1340    /*
1341     * Saves the workbench part.
1342     */

1343    public boolean savePart(final ISaveablePart saveable, IWorkbenchPart part,
1344            boolean confirm) {
1345        return SaveableHelper.savePart(saveable, part, window, confirm);
1346    }
1347
1348    /**
1349     * @see IPersistablePart
1350     */

1351    public IStatus saveState(final IMemento memento) {
1352
1353        final MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID,
1354                IStatus.OK,
1355                WorkbenchMessages.EditorManager_problemsSavingEditors, null);
1356
1357        // Save the editor area workbooks layout/relationship
1358
IMemento editorAreaMem = memento
1359                .createChild(IWorkbenchConstants.TAG_AREA);
1360        result.add(editorPresentation.saveState(editorAreaMem));
1361
1362        // Save the active workbook id
1363
editorAreaMem.putString(IWorkbenchConstants.TAG_ACTIVE_WORKBOOK,
1364                editorPresentation.getActiveEditorWorkbookID());
1365
1366        // Get each workbook
1367
ArrayList JavaDoc workbooks = editorPresentation.getWorkbooks();
1368
1369        for (Iterator JavaDoc iter = workbooks.iterator(); iter.hasNext();) {
1370            EditorStack workbook = (EditorStack) iter.next();
1371
1372            // Use the list of editors found in EditorStack; fix for 24091
1373
EditorPane editorPanes[] = workbook.getEditors();
1374
1375            for (int i = 0; i < editorPanes.length; i++) {
1376                // Save each open editor.
1377
IEditorReference editorReference = editorPanes[i]
1378                        .getEditorReference();
1379                EditorReference e = (EditorReference) editorReference;
1380                final IEditorPart editor = editorReference.getEditor(false);
1381                if (editor == null) {
1382                    if (e.getMemento() != null) {
1383                        IMemento editorMem = memento
1384                                .createChild(IWorkbenchConstants.TAG_EDITOR);
1385                        editorMem.putMemento(e.getMemento());
1386                    }
1387                    continue;
1388                }
1389
1390                // for dynamic UI - add the next line to replace the subsequent
1391
// code which is commented out
1392
saveEditorState(memento, e, result);
1393            }
1394        }
1395        return result;
1396    }
1397
1398    /**
1399     * Shows an editor. If <code>setFocus == true</code> then give it focus,
1400     * too.
1401     *
1402     * @return true if the active editor was changed, false if not.
1403     */

1404    public boolean setVisibleEditor(IEditorReference newEd, boolean setFocus) {
1405        return editorPresentation.setVisibleEditor(newEd, setFocus);
1406    }
1407
1408    private IPathEditorInput getPathEditorInput(IEditorInput input) {
1409        if (input instanceof IPathEditorInput) {
1410            return (IPathEditorInput) input;
1411        }
1412
1413        return (IPathEditorInput) Util.getAdapter(input, IPathEditorInput.class);
1414    }
1415
1416    private class InnerEditor extends EditorReference {
1417
1418        private IEditorReference outerEditor;
1419
1420        public InnerEditor(IEditorReference outerEditor, IEditorInput input,
1421                EditorDescriptor desc) {
1422            super(EditorManager.this, input, desc);
1423            this.outerEditor = outerEditor;
1424        }
1425
1426        protected PartPane createPane() {
1427            return new MultiEditorInnerPane(
1428                    (EditorPane) ((EditorReference) outerEditor).getPane(),
1429                    this, page, editorPresentation.getActiveWorkbook());
1430        }
1431
1432    }
1433
1434    /*
1435     * Made public for Mylar in 3.3 - see bug 138666. Can be made private once
1436     * we have real API for this.
1437     */

1438    public void restoreEditorState(IMemento editorMem,
1439            ArrayList JavaDoc visibleEditors, IEditorReference[] activeEditor,
1440            MultiStatus result) {
1441        // String strFocus = editorMem.getString(IWorkbenchConstants.TAG_FOCUS);
1442
// boolean visibleEditor = "true".equals(strFocus); //$NON-NLS-1$
1443
final EditorReference e = new EditorReference(this, editorMem);
1444
1445        // if the editor is not visible, ensure it is put in the correct
1446
// workbook. PR 24091
1447

1448        final String JavaDoc workbookID = editorMem
1449                .getString(IWorkbenchConstants.TAG_WORKBOOK);
1450
1451        try {
1452            StartupThreading.runWithPartInitExceptions(new StartupRunnable () {
1453
1454                public void runWithException() throws Throwable JavaDoc {
1455                    createEditorTab(e, workbookID);
1456                }});
1457            
1458        } catch (PartInitException ex) {
1459            result.add(ex.getStatus());
1460        }
1461
1462        String JavaDoc strActivePart = editorMem
1463                .getString(IWorkbenchConstants.TAG_ACTIVE_PART);
1464        if ("true".equals(strActivePart)) { //$NON-NLS-1$
1465
activeEditor[0] = e;
1466        }
1467
1468        String JavaDoc strFocus = editorMem.getString(IWorkbenchConstants.TAG_FOCUS);
1469        boolean visibleEditor = "true".equals(strFocus); //$NON-NLS-1$
1470
if (visibleEditor) {
1471            visibleEditors.add(e);
1472        }
1473    }
1474
1475    // for dynamic UI
1476
protected void saveEditorState(IMemento mem, IEditorReference ed,
1477            MultiStatus res) {
1478        final EditorReference editorRef = (EditorReference) ed;
1479        final IEditorPart editor = ed.getEditor(false);
1480        final IMemento memento = mem;
1481        final MultiStatus result = res;
1482        if (!(editor.getEditorSite() instanceof EditorSite)) {
1483            return;
1484        }
1485        final EditorSite site = (EditorSite) editor.getEditorSite();
1486        if (site.getPane() instanceof MultiEditorInnerPane) {
1487            return;
1488        }
1489
1490        SafeRunner.run(new SafeRunnable() {
1491            public void run() {
1492                // Get the input.
1493
IEditorInput input = editor.getEditorInput();
1494                IPersistableElement persistable = input.getPersistable();
1495                if (persistable == null) {
1496                    return;
1497                }
1498
1499                // Save editor.
1500
IMemento editorMem = memento
1501                        .createChild(IWorkbenchConstants.TAG_EDITOR);
1502                editorMem.putString(IWorkbenchConstants.TAG_TITLE, editorRef
1503                        .getTitle());
1504                editorMem.putString(IWorkbenchConstants.TAG_NAME, editorRef
1505                        .getName());
1506                editorMem.putString(IWorkbenchConstants.TAG_ID, editorRef
1507                        .getId());
1508                editorMem.putString(IWorkbenchConstants.TAG_TOOLTIP, editorRef
1509                        .getTitleToolTip());
1510
1511                editorMem.putString(IWorkbenchConstants.TAG_PART_NAME,
1512                        editorRef.getPartName());
1513                
1514                if (editor instanceof IWorkbenchPart3) {
1515                    Map JavaDoc properties = ((IWorkbenchPart3) editor)
1516                            .getPartProperties();
1517                    if (!properties.isEmpty()) {
1518                        IMemento propBag = editorMem
1519                                .createChild(IWorkbenchConstants.TAG_PROPERTIES);
1520                        Iterator JavaDoc i = properties.entrySet().iterator();
1521                        while (i.hasNext()) {
1522                            Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
1523                            IMemento p = propBag.createChild(
1524                                    IWorkbenchConstants.TAG_PROPERTY,
1525                                    (String JavaDoc) entry.getKey());
1526                            p.putTextData((String JavaDoc) entry.getValue());
1527                        }
1528                    }
1529                }
1530
1531                if (editorRef.isPinned()) {
1532                    editorMem.putString(IWorkbenchConstants.TAG_PINNED, "true"); //$NON-NLS-1$
1533
}
1534
1535                EditorPane editorPane = (EditorPane) ((EditorSite) editor
1536                        .getEditorSite()).getPane();
1537                editorMem.putString(IWorkbenchConstants.TAG_WORKBOOK,
1538                        editorPane.getWorkbook().getID());
1539
1540                if (editor == page.getActivePart()) {
1541                    editorMem.putString(IWorkbenchConstants.TAG_ACTIVE_PART,
1542                            "true"); //$NON-NLS-1$
1543
}
1544
1545                if (editorPane == editorPane.getWorkbook().getSelection()) {
1546                    editorMem.putString(IWorkbenchConstants.TAG_FOCUS, "true"); //$NON-NLS-1$
1547
}
1548
1549                if (input instanceof IPathEditorInput) {
1550                    IPath path = ((IPathEditorInput) input).getPath();
1551                    if (path != null) {
1552                        editorMem.putString(IWorkbenchConstants.TAG_PATH, path
1553                                .toString());
1554                    }
1555                }
1556
1557                // Save input.
1558
IMemento inputMem = editorMem
1559                        .createChild(IWorkbenchConstants.TAG_INPUT);
1560                inputMem.putString(IWorkbenchConstants.TAG_FACTORY_ID,
1561                        persistable.getFactoryId());
1562                persistable.saveState(inputMem);
1563                
1564                // any editors that want to persist state
1565
if (editor instanceof IPersistableEditor) {
1566                    IMemento editorState = editorMem
1567                            .createChild(IWorkbenchConstants.TAG_EDITOR_STATE);
1568                    ((IPersistableEditor) editor).saveState(editorState);
1569                }
1570            }
1571
1572            public void handleException(Throwable JavaDoc e) {
1573                result
1574                        .add(new Status(
1575                                IStatus.ERROR,
1576                                PlatformUI.PLUGIN_ID,
1577                                0,
1578                                NLS
1579                                        .bind(
1580                                                WorkbenchMessages.EditorManager_unableToSaveEditor,
1581                                                editorRef.getTitle()), e));
1582            }
1583        });
1584    }
1585
1586    // for dynamic UI
1587
public IMemento getMemento(IEditorReference e) {
1588        if (e instanceof EditorReference) {
1589            return ((EditorReference) e).getMemento();
1590        }
1591        return null;
1592    }
1593
1594    /*
1595     * (non-Javadoc)
1596     *
1597     * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension,
1598     * java.lang.Object[])
1599     */

1600    public void removeExtension(IExtension source, Object JavaDoc[] objects) {
1601        for (int i = 0; i < objects.length; i++) {
1602            if (objects[i] instanceof IEditorPart) {
1603                // close the editor and clean up the editor history
1604

1605                IEditorPart editor = (IEditorPart) objects[i];
1606                IEditorInput input = editor.getEditorInput();
1607                page.closeEditor(editor, true);
1608                ((Workbench) window.getWorkbench()).getEditorHistory().remove(
1609                        input);
1610            }
1611        }
1612    }
1613
1614    /*
1615     * (non-Javadoc)
1616     *
1617     * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker,
1618     * org.eclipse.core.runtime.IExtension)
1619     */

1620    public void addExtension(IExtensionTracker tracker, IExtension extension) {
1621        // Nothing to do
1622
}
1623
1624    /**
1625     * @return
1626     */

1627    /*package*/ IEditorReference openEmptyTab() {
1628        IEditorInput input = new NullEditorInput();
1629        EditorDescriptor desc = (EditorDescriptor) ((EditorRegistry) getEditorRegistry())
1630                .findEditor(EditorRegistry.EMPTY_EDITOR_ID);
1631        EditorReference result = new EditorReference(this, input, desc);
1632        try {
1633            createEditorTab(result, ""); //$NON-NLS-1$
1634
return result;
1635        } catch (PartInitException e) {
1636            StatusManager.getManager().handle(
1637                    StatusUtil.newStatus(WorkbenchPlugin.PI_WORKBENCH, e));
1638        }
1639        return null;
1640    }
1641    
1642    public static boolean useIPersistableEditor() {
1643        IPreferenceStore store = WorkbenchPlugin.getDefault()
1644                .getPreferenceStore();
1645        return store.getBoolean(IPreferenceConstants.USE_IPERSISTABLE_EDITORS);
1646    }
1647}
1648
Popular Tags