KickJava   Java API By Example, From Geeks To Geeks.

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


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
12 package org.eclipse.ui.internal;
13
14 import java.lang.reflect.InvocationTargetException JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Arrays JavaDoc;
17 import java.util.Collection JavaDoc;
18 import java.util.Collections JavaDoc;
19 import java.util.Comparator JavaDoc;
20 import java.util.HashSet JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Set JavaDoc;
24 import java.util.StringTokenizer JavaDoc;
25
26 import org.eclipse.core.runtime.Assert;
27 import org.eclipse.core.runtime.IAdaptable;
28 import org.eclipse.core.runtime.IConfigurationElement;
29 import org.eclipse.core.runtime.IExtension;
30 import org.eclipse.core.runtime.IExtensionPoint;
31 import org.eclipse.core.runtime.IProgressMonitor;
32 import org.eclipse.core.runtime.IStatus;
33 import org.eclipse.core.runtime.ListenerList;
34 import org.eclipse.core.runtime.MultiStatus;
35 import org.eclipse.core.runtime.Platform;
36 import org.eclipse.core.runtime.Status;
37 import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
38 import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
39 import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
40 import org.eclipse.jface.dialogs.ErrorDialog;
41 import org.eclipse.jface.dialogs.IDialogConstants;
42 import org.eclipse.jface.dialogs.MessageDialog;
43 import org.eclipse.jface.internal.provisional.action.ICoolBarManager2;
44 import org.eclipse.jface.operation.IRunnableWithProgress;
45 import org.eclipse.jface.util.IPropertyChangeListener;
46 import org.eclipse.jface.util.PropertyChangeEvent;
47 import org.eclipse.jface.util.SafeRunnable;
48 import org.eclipse.jface.viewers.ISelection;
49 import org.eclipse.jface.window.Window;
50 import org.eclipse.osgi.util.NLS;
51 import org.eclipse.swt.SWT;
52 import org.eclipse.swt.custom.BusyIndicator;
53 import org.eclipse.swt.graphics.Rectangle;
54 import org.eclipse.swt.widgets.Composite;
55 import org.eclipse.swt.widgets.Control;
56 import org.eclipse.swt.widgets.Display;
57 import org.eclipse.swt.widgets.Shell;
58 import org.eclipse.ui.IActionBars;
59 import org.eclipse.ui.IEditorDescriptor;
60 import org.eclipse.ui.IEditorInput;
61 import org.eclipse.ui.IEditorPart;
62 import org.eclipse.ui.IEditorReference;
63 import org.eclipse.ui.IEditorRegistry;
64 import org.eclipse.ui.IMemento;
65 import org.eclipse.ui.INavigationHistory;
66 import org.eclipse.ui.IPartListener;
67 import org.eclipse.ui.IPartListener2;
68 import org.eclipse.ui.IPerspectiveDescriptor;
69 import org.eclipse.ui.IPerspectiveRegistry;
70 import org.eclipse.ui.IReusableEditor;
71 import org.eclipse.ui.ISaveablePart;
72 import org.eclipse.ui.ISaveablesLifecycleListener;
73 import org.eclipse.ui.ISelectionListener;
74 import org.eclipse.ui.IShowEditorInput;
75 import org.eclipse.ui.IViewPart;
76 import org.eclipse.ui.IViewReference;
77 import org.eclipse.ui.IWorkbench;
78 import org.eclipse.ui.IWorkbenchPage;
79 import org.eclipse.ui.IWorkbenchPart;
80 import org.eclipse.ui.IWorkbenchPartReference;
81 import org.eclipse.ui.IWorkbenchPartSite;
82 import org.eclipse.ui.IWorkbenchPreferenceConstants;
83 import org.eclipse.ui.IWorkbenchWindow;
84 import org.eclipse.ui.IWorkingSet;
85 import org.eclipse.ui.IWorkingSetManager;
86 import org.eclipse.ui.PartInitException;
87 import org.eclipse.ui.PlatformUI;
88 import org.eclipse.ui.SubActionBars;
89 import org.eclipse.ui.WorkbenchException;
90 import org.eclipse.ui.contexts.IContextService;
91 import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
92 import org.eclipse.ui.internal.contexts.ContextAuthority;
93 import org.eclipse.ui.internal.dialogs.CustomizePerspectiveDialog;
94 import org.eclipse.ui.internal.dnd.SwtUtil;
95 import org.eclipse.ui.internal.intro.IIntroConstants;
96 import org.eclipse.ui.internal.misc.UIListenerLogging;
97 import org.eclipse.ui.internal.misc.UIStats;
98 import org.eclipse.ui.internal.registry.ActionSetRegistry;
99 import org.eclipse.ui.internal.registry.EditorDescriptor;
100 import org.eclipse.ui.internal.registry.EditorRegistry;
101 import org.eclipse.ui.internal.registry.IActionSetDescriptor;
102 import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
103 import org.eclipse.ui.internal.registry.PerspectiveDescriptor;
104 import org.eclipse.ui.internal.registry.UIExtensionTracker;
105 import org.eclipse.ui.internal.tweaklets.GrabFocus;
106 import org.eclipse.ui.internal.tweaklets.TabBehaviour;
107 import org.eclipse.ui.internal.tweaklets.Tweaklets;
108 import org.eclipse.ui.internal.util.PrefUtil;
109 import org.eclipse.ui.internal.util.Util;
110 import org.eclipse.ui.model.IWorkbenchAdapter;
111 import org.eclipse.ui.part.MultiEditor;
112 import org.eclipse.ui.presentations.IStackPresentationSite;
113
114 /**
115  * A collection of views and editors in a workbench.
116  */

117 public class WorkbenchPage extends CompatibleWorkbenchPage implements
118         IWorkbenchPage {
119     
120     private static final String JavaDoc ATT_AGGREGATE_WORKING_SET_ID = "aggregateWorkingSetId"; //$NON-NLS-1$
121

122     private WorkbenchWindow window;
123
124     private IAdaptable input;
125
126     private IWorkingSet workingSet;
127     
128     private AggregateWorkingSet aggregateWorkingSet;
129
130     private Composite composite;
131     
132     //Could be delete. This information is in the active part list;
133
private ActivationList activationList = new ActivationList();
134
135     /**
136      * This field controls whether or not the ActivationList will
137      * remove Fast Views from its list of active views. It's currently
138      * only <core>true</code> when new editors are added, allowing
139      * a minimized View that opens (but doesn't activate) a new editor
140      * to remain active.
141      */

142     private boolean includeActiveFastViews = false;
143
144     private EditorManager editorMgr;
145
146     private EditorAreaHelper editorPresentation;
147
148     private ListenerList propertyChangeListeners = new ListenerList();
149
150     private PageSelectionService selectionService = new PageSelectionService(
151             this);
152
153     private WorkbenchPagePartList partList = new WorkbenchPagePartList(selectionService);
154
155     private IActionBars actionBars;
156     
157     private ActionSetManager actionSets;
158     
159     private ViewFactory viewFactory;
160
161     private PerspectiveList perspList = new PerspectiveList();
162
163     private PerspectiveDescriptor deferredActivePersp;
164
165     private NavigationHistory navigationHistory = new NavigationHistory(this);
166     
167     private IStickyViewManager stickyViewMan = StickyViewManager.getInstance(this);
168
169     /**
170      * If we're in the process of activating a part, this points to the new part.
171      * Otherwise, this is null.
172      */

173     private IWorkbenchPartReference partBeingActivated = null;
174     
175     /**
176      * Contains a list of perspectives that may be dirty due to plugin
177      * installation and removal.
178      */

179     private Set JavaDoc dirtyPerspectives = new HashSet JavaDoc();
180     
181     private IPropertyChangeListener workingSetPropertyChangeListener = new IPropertyChangeListener() {
182         /*
183          * Remove the working set from the page if the working set is deleted.
184          */

185         public void propertyChange(PropertyChangeEvent event) {
186             String JavaDoc property = event.getProperty();
187             if (IWorkingSetManager.CHANGE_WORKING_SET_REMOVE.equals(property)) {
188                     if(event.getOldValue().equals(workingSet)) {
189                         setWorkingSet(null);
190                     }
191                     
192                     // room for optimization here
193
List JavaDoc newList = new ArrayList JavaDoc(Arrays.asList(workingSets));
194                     if (newList.remove(event.getOldValue())) {
195                         setWorkingSets((IWorkingSet []) newList
196                                 .toArray(new IWorkingSet [newList.size()]));
197                     }
198             }
199         }
200     };
201
202     private ActionSwitcher actionSwitcher = new ActionSwitcher();
203
204     private IExtensionTracker tracker;
205     
206     // Deferral count... delays disposing parts and sending certain events if nonzero
207
private int deferCount = 0;
208     // Parts waiting to be disposed
209
private List JavaDoc pendingDisposals = new ArrayList JavaDoc();
210     
211     private IExtensionChangeHandler perspectiveChangeHandler = new IExtensionChangeHandler() {
212
213         /* (non-Javadoc)
214          * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
215          */

216         public void removeExtension(IExtension extension, Object JavaDoc[] objects) {
217             boolean suggestReset = false;
218             for (int i = 0; i < objects.length; i++) {
219                 if (objects[i] instanceof DirtyPerspectiveMarker) {
220                     String JavaDoc id = ((DirtyPerspectiveMarker)objects[i]).perspectiveId;
221                     if (!dirtyPerspectives.remove(id)) {
222                         dirtyPerspectives.add(id); // otherwise we will be dirty
223
}
224                     PerspectiveDescriptor persp = (PerspectiveDescriptor) getPerspective();
225                     if (persp == null || persp.hasCustomDefinition()) {
226                         continue;
227                     }
228                     if (persp.getId().equals(id)) {
229                         suggestReset = true;
230                     }
231                 }
232             }
233             if (suggestReset) {
234                 suggestReset();
235             }
236         }
237         
238         /* (non-Javadoc)
239          * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
240          */

241         public void addExtension(IExtensionTracker tracker, IExtension extension) {
242             if (WorkbenchPage.this != getWorkbenchWindow().getActivePage()) {
243                 return;
244             }
245             
246             // Get the current perspective.
247
PerspectiveDescriptor persp = (PerspectiveDescriptor) getPerspective();
248             if (persp == null) {
249                 return;
250             }
251             String JavaDoc currentId = persp.getId();
252             IConfigurationElement[] elements = extension.getConfigurationElements();
253             boolean suggestReset = false;
254             for (int i = 0; i < elements.length; i++) {
255                 // If any of these refer to the current perspective, output
256
// a message saying this perspective will need to be reset
257
// in order to see the changes. For any other case, the
258
// perspective extension registry will be rebuilt anyway so
259
// just ignore it.
260
String JavaDoc id = elements[i].getAttribute(IWorkbenchRegistryConstants.ATT_TARGET_ID);
261                 if (id == null) {
262                     continue;
263                 }
264                 if (id.equals(currentId) && !persp.hasCustomDefinition()) {
265                     suggestReset = true;
266                 }
267                 else {
268                     dirtyPerspectives.add(id);
269                 }
270                 DirtyPerspectiveMarker marker = new DirtyPerspectiveMarker(id);
271                 tracker.registerObject(extension, marker, IExtensionTracker.REF_STRONG);
272             }
273             if (suggestReset) {
274                 suggestReset();
275             }
276
277         }
278     };
279     private IWorkingSet[] workingSets = new IWorkingSet[0];
280     private String JavaDoc aggregateWorkingSetId;
281
282     private IExtensionPoint getPerspectiveExtensionPoint() {
283         return Platform.getExtensionRegistry().getExtensionPoint(PlatformUI.PLUGIN_ID, IWorkbenchRegistryConstants.PL_PERSPECTIVE_EXTENSIONS);
284     }
285
286     /**
287      * Manages editor contributions and action set part associations.
288      */

289     private class ActionSwitcher {
290         private IWorkbenchPart activePart;
291
292         private IEditorPart topEditor;
293
294         private ArrayList JavaDoc oldActionSets = new ArrayList JavaDoc();
295
296         /**
297          * Updates the contributions given the new part as the active part.
298          *
299          * @param newPart
300          * the new active part, may be <code>null</code>
301          */

302         public void updateActivePart(IWorkbenchPart newPart) {
303             if (activePart == newPart) {
304                 return;
305             }
306
307             boolean isNewPartAnEditor = newPart instanceof IEditorPart;
308             if (isNewPartAnEditor) {
309                 String JavaDoc oldId = null;
310                 if (topEditor != null) {
311                     oldId = topEditor.getSite().getId();
312                 }
313                 String JavaDoc newId = newPart.getSite().getId();
314
315                 // if the active part is an editor and the new editor
316
// is the same kind of editor, then we don't have to do
317
// anything
318
if (activePart == topEditor && newId.equals(oldId)) {
319                     activePart = newPart;
320                     topEditor = (IEditorPart) newPart;
321                     return;
322                 }
323
324                 // remove the contributions of the old editor
325
// if it is a different kind of editor
326
if (oldId != null && !oldId.equals(newId)) {
327                     deactivateContributions(topEditor, true);
328                 }
329
330                 // if a view was the active part, disable its contributions
331
if (activePart != null && activePart != topEditor) {
332                     deactivateContributions(activePart, true);
333                 }
334
335                 // show (and enable) the contributions of the new editor
336
// if it is a different kind of editor or if the
337
// old active part was a view
338
if (!newId.equals(oldId) || activePart != topEditor) {
339                     activateContributions(newPart, true);
340                 }
341
342             } else if (newPart == null) {
343                 if (activePart != null) {
344                     // remove all contributions
345
deactivateContributions(activePart, true);
346                 }
347             } else {
348                 // new part is a view
349

350                 // if old active part is a view, remove all contributions,
351
// but if old part is an editor only disable
352
if (activePart != null) {
353                     deactivateContributions(activePart,
354                             activePart instanceof IViewPart);
355                 }
356
357                 activateContributions(newPart, true);
358             }
359
360             ArrayList JavaDoc newActionSets = null;
361             if (isNewPartAnEditor
362                     || (activePart == topEditor && newPart == null)) {
363                 newActionSets = calculateActionSets(newPart, null);
364             } else {
365                 newActionSets = calculateActionSets(newPart, topEditor);
366             }
367
368             if (!updateActionSets(newActionSets)) {
369                 updateActionBars();
370             }
371
372             if (isNewPartAnEditor) {
373                 topEditor = (IEditorPart) newPart;
374             } else if (activePart == topEditor && newPart == null) {
375                 // since we removed all the contributions, we clear the top
376
// editor
377
topEditor = null;
378             }
379
380             activePart = newPart;
381         }
382
383         /**
384          * Updates the contributions given the new part as the topEditor.
385          *
386          * @param newEditor
387          * the new top editor, may be <code>null</code>
388          */

389         public void updateTopEditor(IEditorPart newEditor) {
390             if (topEditor == newEditor) {
391                 return;
392             }
393
394             if (activePart == topEditor) {
395                 updateActivePart(newEditor);
396                 return;
397             }
398             
399             String JavaDoc oldId = null;
400             if (topEditor != null) {
401                 oldId = topEditor.getSite().getId();
402             }
403             String JavaDoc newId = null;
404             if (newEditor != null) {
405                 newId = newEditor.getSite().getId();
406             }
407             if (oldId == null ? newId == null : oldId.equals(newId)) {
408                 // we don't have to change anything
409
topEditor = newEditor;
410                 return;
411             }
412
413             // Remove the contributions of the old editor
414
if (topEditor != null) {
415                 deactivateContributions(topEditor, true);
416             }
417
418             // Show (disabled) the contributions of the new editor
419
if (newEditor != null) {
420                 activateContributions(newEditor, false);
421             }
422
423             ArrayList JavaDoc newActionSets = calculateActionSets(activePart, newEditor);
424             if (!updateActionSets(newActionSets)) {
425                 updateActionBars();
426             }
427
428             topEditor = newEditor;
429         }
430
431         /**
432          * Activates the contributions of the given part. If <code>enable</code>
433          * is <code>true</code> the contributions are visible and enabled,
434          * otherwise they are disabled.
435          *
436          * @param part
437          * the part whose contributions are to be activated
438          * @param enable
439          * <code>true</code> the contributions are to be enabled,
440          * not just visible.
441          */

442         private void activateContributions(IWorkbenchPart part, boolean enable) {
443             PartSite site = (PartSite) part.getSite();
444             site.activateActionBars(enable);
445         }
446
447         /**
448          * Deactivates the contributions of the given part. If <code>remove</code>
449          * is <code>true</code> the contributions are removed, otherwise they
450          * are disabled.
451          *
452          * @param part
453          * the part whose contributions are to be deactivated
454          * @param remove
455          * <code>true</code> the contributions are to be removed,
456          * not just disabled.
457          */

458         private void deactivateContributions(IWorkbenchPart part, boolean remove) {
459             PartSite site = (PartSite) part.getSite();
460             site.deactivateActionBars(remove);
461         }
462
463         /**
464          * Calculates the action sets to show for the given part and editor
465          *
466          * @param part
467          * the active part, may be <code>null</code>
468          * @param editor
469          * the current editor, may be <code>null</code>, may be
470          * the active part
471          * @return the new action sets
472          */

473         private ArrayList JavaDoc calculateActionSets(IWorkbenchPart part,
474                 IEditorPart editor) {
475             ArrayList JavaDoc newActionSets = new ArrayList JavaDoc();
476             if (part != null) {
477                 IActionSetDescriptor[] partActionSets = WorkbenchPlugin
478                         .getDefault().getActionSetRegistry().getActionSetsFor(
479                                 part.getSite().getId());
480                 for (int i = 0; i < partActionSets.length; i++) {
481                     newActionSets.add(partActionSets[i]);
482                 }
483             }
484             if (editor != null && editor != part) {
485                 IActionSetDescriptor[] editorActionSets = WorkbenchPlugin
486                         .getDefault().getActionSetRegistry().getActionSetsFor(
487                                 editor.getSite().getId());
488                 for (int i = 0; i < editorActionSets.length; i++) {
489                     newActionSets.add(editorActionSets[i]);
490                 }
491             }
492             return newActionSets;
493         }
494
495         /**
496          * Updates the actions we are showing for the active part and current
497          * editor.
498          *
499          * @param newActionSets
500          * the action sets to show
501          * @return <code>true</code> if the action sets changed
502          */

503         private boolean updateActionSets(ArrayList JavaDoc newActionSets) {
504             if (oldActionSets.equals(newActionSets)) {
505                 return false;
506             }
507
508             IContextService service = (IContextService) window
509                     .getService(IContextService.class);
510             try {
511                 service.activateContext(ContextAuthority.DEFER_EVENTS);
512
513                 // show the new
514
for (int i = 0; i < newActionSets.size(); i++) {
515                     actionSets.showAction((IActionSetDescriptor) newActionSets
516                             .get(i));
517                 }
518
519                 // hide the old
520
for (int i = 0; i < oldActionSets.size(); i++) {
521                     actionSets.hideAction((IActionSetDescriptor) oldActionSets
522                             .get(i));
523                 }
524
525                 oldActionSets = newActionSets;
526
527             } finally {
528                 service.activateContext(ContextAuthority.SEND_EVENTS);
529             }
530             Perspective persp = getActivePerspective();
531             if (persp == null) {
532                 return false;
533             }
534
535             window.updateActionSets(); // this calls updateActionBars
536
window.firePerspectiveChanged(WorkbenchPage.this, getPerspective(),
537                     CHANGE_ACTION_SET_SHOW);
538             return true;
539         }
540
541     }
542
543     /**
544      * Constructs a new page with a given perspective and input.
545      *
546      * @param w
547      * the parent window
548      * @param layoutID
549      * must not be <code>null</code>
550      * @param input
551      * the page input
552      * @throws WorkbenchException
553      * on null layout id
554      */

555     public WorkbenchPage(WorkbenchWindow w, String JavaDoc layoutID, IAdaptable input)
556             throws WorkbenchException {
557         super();
558         if (layoutID == null) {
559             throw new WorkbenchException(WorkbenchMessages.WorkbenchPage_UndefinedPerspective);
560         }
561         init(w, layoutID, input, true);
562     }
563
564     /**
565      * Constructs a page. <code>restoreState(IMemento)</code> should be
566      * called to restore this page from data stored in a persistance file.
567      *
568      * @param w
569      * the parent window
570      * @param input
571      * the page input
572      * @throws WorkbenchException
573      */

574     public WorkbenchPage(WorkbenchWindow w, IAdaptable input)
575             throws WorkbenchException {
576         super();
577         init(w, null, input, false);
578     }
579
580     /**
581      * Activates a part. The part will be brought to the front and given focus.
582      *
583      * @param part
584      * the part to activate
585      */

586     public void activate(IWorkbenchPart part) {
587         // Sanity check.
588
if (!certifyPart(part)) {
589             return;
590         }
591
592         if (window.isClosing()) {
593             return;
594         }
595
596         if (composite!=null && composite.isVisible()
597                 && !((GrabFocus)Tweaklets.get(GrabFocus.KEY)).grabFocusAllowed(part)) {
598             return;
599         }
600         
601         // If zoomed, unzoom.
602
zoomOutIfNecessary(part);
603
604         if (part instanceof MultiEditor) {
605             part = ((MultiEditor) part).getActiveEditor();
606         }
607         // Activate part.
608
//if (window.getActivePage() == this) {
609
IWorkbenchPartReference ref = getReference(part);
610         internalBringToTop(ref);
611         setActivePart(part);
612     }
613
614     /**
615      * Activates a part. The part is given focus, the pane is hilighted.
616      */

617     private void activatePart(final IWorkbenchPart part) {
618         Platform.run(new SafeRunnable(WorkbenchMessages.WorkbenchPage_ErrorActivatingView) {
619                     public void run() {
620                         if (part != null) {
621                             //part.setFocus();
622
PartPane pane = getPane(part);
623                             pane.setFocus();
624                             PartSite site = (PartSite) part.getSite();
625                             pane.showFocus(true);
626                             updateTabList(part);
627                             SubActionBars bars = (SubActionBars) site
628                                     .getActionBars();
629                             bars.partChanged(part);
630                         }
631                     }
632                 });
633     }
634
635     /**
636      * Add a fast view.
637      */

638     public void addFastView(IViewReference ref) {
639         Perspective persp = getActivePerspective();
640         if (persp == null) {
641             return;
642         }
643         
644         persp.getFastViewManager().addViewReference(FastViewBar.FASTVIEWBAR_ID, -1, ref, true);
645     }
646     
647     /**
648      * Add a fast view.
649      */

650     public void makeFastView(IViewReference ref) {
651         Perspective persp = getActivePerspective();
652         if (persp == null) {
653             return;
654         }
655
656         FastViewManager fvm = persp.getFastViewManager();
657         if (fvm.isFastView(ref)) {
658             return;
659         }
660         
661         // Do real work.
662
persp.makeFastView(ref);
663
664         updateActivePart();
665         
666         // The view is now invisible.
667
// If it is active then deactivate it.
668

669         // Notify listeners.
670
window.firePerspectiveChanged(this, getPerspective(), ref,
671                 CHANGE_FAST_VIEW_ADD);
672         window.firePerspectiveChanged(this, getPerspective(),
673                 CHANGE_FAST_VIEW_ADD);
674     }
675
676     /**
677      * Adds an IPartListener to the part service.
678      */

679     public void addPartListener(IPartListener l) {
680         partList.getPartService().addPartListener(l);
681     }
682
683     /**
684      * Adds an IPartListener to the part service.
685      */

686     public void addPartListener(IPartListener2 l) {
687         partList.getPartService().addPartListener(l);
688     }
689
690     /**
691      * Implements IWorkbenchPage
692      *
693      * @see org.eclipse.ui.IWorkbenchPage#addPropertyChangeListener(IPropertyChangeListener)
694      * @since 2.0
695      * @deprecated individual views should store a working set if needed and
696      * register a property change listener directly with the
697      * working set manager to receive notification when the view
698      * working set is removed.
699      */

700     public void addPropertyChangeListener(IPropertyChangeListener listener) {
701         propertyChangeListeners.add(listener);
702     }
703
704     /*
705      * (non-Javadoc) Method declared on ISelectionListener.
706      */

707     public void addSelectionListener(ISelectionListener listener) {
708         selectionService.addSelectionListener(listener);
709     }
710
711     /*
712      * (non-Javadoc) Method declared on ISelectionListener.
713      */

714     public void addSelectionListener(String JavaDoc partId, ISelectionListener listener) {
715         selectionService.addSelectionListener(partId, listener);
716     }
717
718     /*
719      * (non-Javadoc) Method declared on ISelectionListener.
720      */

721     public void addPostSelectionListener(ISelectionListener listener) {
722         selectionService.addPostSelectionListener(listener);
723     }
724
725     /*
726      * (non-Javadoc) Method declared on ISelectionListener.
727      */

728     public void addPostSelectionListener(String JavaDoc partId,
729             ISelectionListener listener) {
730         selectionService.addPostSelectionListener(partId, listener);
731     }
732     
733     private ILayoutContainer getContainer(IWorkbenchPart part) {
734         PartPane pane = getPane(part);
735         if (pane == null) {
736             return null;
737         }
738         
739         return pane.getContainer();
740     }
741
742     private ILayoutContainer getContainer(IWorkbenchPartReference part) {
743         PartPane pane = getPane(part);
744         if (pane == null) {
745             return null;
746         }
747         
748         return pane.getContainer();
749     }
750     
751     private PartPane getPane(IWorkbenchPart part) {
752         if (part == null) {
753             return null;
754         }
755         return getPane(getReference(part));
756     }
757     
758     private PartPane getPane(IWorkbenchPartReference part) {
759         if (part == null) {
760             return null;
761         }
762         
763         return ((WorkbenchPartReference)part).getPane();
764     }
765
766     
767     /**
768      * Brings a part to the front of its stack. Does not update the active part or
769      * active editor. This should only be called if the caller knows that the part
770      * is not in the same stack as the active part or active editor, or if the caller
771      * is prepared to update activation after the call.
772      *
773      * @param part
774      */

775     private boolean internalBringToTop(IWorkbenchPartReference part) {
776
777         boolean broughtToTop = false;
778         
779         // Move part.
780
if (part instanceof IEditorReference) {
781             ILayoutContainer container = getContainer(part);
782             if (container instanceof PartStack) {
783                 PartStack stack = (PartStack)container;
784                 PartPane newPart = getPane(part);
785                 if (stack.getSelection() != newPart) {
786                     stack.setSelection(newPart);
787                 }
788                 broughtToTop = true;
789             }
790         } else if (part instanceof IViewReference) {
791             Perspective persp = getActivePerspective();
792             if (persp != null) {
793                 broughtToTop = persp.bringToTop((IViewReference)part);
794             }
795         }
796         
797         // Ensure that this part is considered the most recently activated part
798
// in this stack
799
activationList.bringToTop(part);
800         
801         return broughtToTop;
802     }
803
804     
805     /**
806      * Moves a part forward in the Z order of a perspective so it is visible.
807      * If the part is in the same stack as the active part, the new part is
808      * activated.
809      *
810      * @param part
811      * the part to bring to move forward
812      */

813     public void bringToTop(IWorkbenchPart part) {
814         // Sanity check.
815
Perspective persp = getActivePerspective();
816         if (persp == null || !certifyPart(part)) {
817             return;
818         }
819         
820         if (!((GrabFocus)Tweaklets.get(GrabFocus.KEY)).grabFocusAllowed(part)) {
821             return;
822         }
823
824         String JavaDoc label = null; // debugging only
825
if (UIStats.isDebugging(UIStats.BRING_PART_TO_TOP)) {
826             label = part != null ? part.getTitle() : "none"; //$NON-NLS-1$
827
}
828         
829         try {
830             UIStats.start(UIStats.BRING_PART_TO_TOP, label);
831             
832             IWorkbenchPartReference ref = getReference(part);
833             ILayoutContainer activeEditorContainer = getContainer(getActiveEditor());
834             ILayoutContainer activePartContainer = getContainer(getActivePart());
835             ILayoutContainer newPartContainer = getContainer(part);
836             
837             if (newPartContainer == activePartContainer) {
838                 makeActive(ref);
839             } else if (newPartContainer == activeEditorContainer) {
840                 if (ref instanceof IEditorReference) {
841                     if (part!=null) {
842                         IWorkbenchPartSite site = part.getSite();
843                         if (site instanceof PartSite) {
844                             ref = ((PartSite) site).getPane()
845                                     .getPartReference();
846                         }
847                     }
848                     makeActiveEditor((IEditorReference)ref);
849                 } else {
850                     makeActiveEditor(null);
851                 }
852             } else {
853                 internalBringToTop(ref);
854                 if (ref != null) {
855                     partList.firePartBroughtToTop(ref);
856                 }
857             }
858         } finally {
859             UIStats.end(UIStats.BRING_PART_TO_TOP, part, label);
860         }
861     }
862
863     /**
864      * Resets the layout for the perspective. The active part in the old layout
865      * is activated in the new layout for consistent user context.
866      *
867      * Assumes the busy cursor is active.
868      */

869     private void busyResetPerspective() {
870
871         ViewIntroAdapterPart introViewAdapter = ((WorkbenchIntroManager) getWorkbenchWindow()
872                 .getWorkbench().getIntroManager()).getViewIntroAdapterPart();
873         PartPane introPane = null;
874         boolean introFullScreen = false;
875         if (introViewAdapter != null) {
876             introPane = ((PartSite) introViewAdapter.getSite()).getPane();
877             introViewAdapter.setHandleZoomEvents(false);
878             introFullScreen = introPane.isZoomed();
879         }
880
881         //try to prevent intro flicker.
882
if (introFullScreen) {
883             window.getShell().setRedraw(false);
884         }
885
886         try {
887
888             // Always unzoom
889
if (isZoomed()) {
890                 zoomOut();
891             }
892
893             // Get the current perspective.
894
// This describes the working layout of the page and differs from
895
// the original template.
896
Perspective oldPersp = getActivePerspective();
897
898             // Map the current perspective to the original template.
899
// If the original template cannot be found then it has been deleted.
900
// In that case just return. (PR#1GDSABU).
901
IPerspectiveRegistry reg = WorkbenchPlugin.getDefault()
902                     .getPerspectiveRegistry();
903             PerspectiveDescriptor desc = (PerspectiveDescriptor) reg
904                     .findPerspectiveWithId(oldPersp.getDesc().getId());
905             if (desc == null) {
906                 desc = (PerspectiveDescriptor) reg
907                         .findPerspectiveWithId(((PerspectiveDescriptor) oldPersp
908                                 .getDesc()).getOriginalId());
909             }
910             if (desc == null) {
911                 return;
912             }
913
914             // Notify listeners that we are doing a reset.
915
window.firePerspectiveChanged(this, desc, CHANGE_RESET);
916
917             // Create new persp from original template.
918
// Suppress the perspectiveOpened and perspectiveClosed events otherwise it looks like two
919
// instances of the same perspective are open temporarily (see bug 127470).
920
Perspective newPersp = createPerspective(desc, false);
921             if (newPersp == null) {
922                 // We're not going through with the reset, so it is complete.
923
window
924                         .firePerspectiveChanged(this, desc,
925                                 CHANGE_RESET_COMPLETE);
926                 return;
927             }
928
929             // Update the perspective list and shortcut
930
perspList.swap(oldPersp, newPersp);
931
932             // Install new persp.
933
setPerspective(newPersp);
934
935             // Destroy old persp.
936
disposePerspective(oldPersp, false);
937
938             // Update the Coolbar layout.
939
resetToolBarLayout();
940
941             // restore the maximized intro
942
if (introViewAdapter != null) {
943                 try {
944                     // ensure that the intro is visible in the new perspective
945
showView(IIntroConstants.INTRO_VIEW_ID);
946                     if (introFullScreen) {
947                         toggleZoom(introPane.getPartReference());
948                     }
949                 } catch (PartInitException e) {
950                     WorkbenchPlugin.log("Could not restore intro", //$NON-NLS-1$
951
WorkbenchPlugin.getStatus(e));
952                 } finally {
953                     // we want the intro back to a normal state before we fire the event
954
introViewAdapter.setHandleZoomEvents(true);
955                 }
956             }
957             // Notify listeners that we have completed our reset.
958
window.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE);
959         } finally {
960             // reset the handling of zoom events (possibly for the second time) in case there was
961
// an exception thrown
962
if (introViewAdapter != null) {
963                 introViewAdapter.setHandleZoomEvents(true);
964             }
965
966             if (introFullScreen) {
967                 window.getShell().setRedraw(true);
968             }
969         }
970
971     }
972
973     /**
974      * Implements <code>setPerspective</code>.
975      *
976      * Assumes that busy cursor is active.
977      *
978      * @param desc
979      * identifies the new perspective.
980      */

981     private void busySetPerspective(IPerspectiveDescriptor desc) {
982         // Create new layout.
983
String JavaDoc label = desc.getId(); // debugging only
984
Perspective newPersp = null;
985         try {
986             UIStats.start(UIStats.SWITCH_PERSPECTIVE, label);
987             PerspectiveDescriptor realDesc = (PerspectiveDescriptor) desc;
988             newPersp = findPerspective(realDesc);
989             if (newPersp == null) {
990                 newPersp = createPerspective(realDesc, true);
991                 if (newPersp == null) {
992                     return;
993                 }
994             }
995
996             // Change layout.
997
setPerspective(newPersp);
998         } finally {
999             UIStats.end(UIStats.SWITCH_PERSPECTIVE, desc.getId(), label);
1000        }
1001    }
1002
1003    /**
1004     * Shows a view.
1005     *
1006     * Assumes that a busy cursor is active.
1007     */

1008    private IViewPart busyShowView(String JavaDoc viewID, String JavaDoc secondaryID, int mode)
1009            throws PartInitException {
1010        Perspective persp = getActivePerspective();
1011        if (persp == null) {
1012            return null;
1013        }
1014
1015        // If this view is already visible just return.
1016
IViewReference ref = persp.findView(viewID, secondaryID);
1017        IViewPart view = null;
1018        if (ref != null) {
1019            view = ref.getView(true);
1020        }
1021        if (view != null) {
1022            busyShowView(view, mode);
1023            return view;
1024        }
1025
1026        // Show the view.
1027
view = persp.showView(viewID, secondaryID);
1028        if (view != null) {
1029            busyShowView(view, mode);
1030            
1031            IWorkbenchPartReference partReference = getReference(view);
1032            PartPane partPane = getPane(partReference);
1033            partPane.setInLayout(true);
1034
1035            window.firePerspectiveChanged(this, getPerspective(),
1036                    partReference, CHANGE_VIEW_SHOW);
1037            window.firePerspectiveChanged(this, getPerspective(),
1038                    CHANGE_VIEW_SHOW);
1039        }
1040        return view;
1041    }
1042
1043    /*
1044     * Performs showing of the view in the given mode.
1045     */

1046    private void busyShowView(IViewPart part, int mode) {
1047        if (!((GrabFocus)Tweaklets.get(GrabFocus.KEY)).grabFocusAllowed(part)) {
1048            return;
1049        }
1050        if (mode == VIEW_ACTIVATE) {
1051            activate(part);
1052        } else if (mode == VIEW_VISIBLE) {
1053            IWorkbenchPartReference ref = getActivePartReference();
1054            // if there is no active part or it's not a view, bring to top
1055
if (ref == null || !(ref instanceof IViewReference)) {
1056                bringToTop(part);
1057            } else {
1058                // otherwise check to see if the we're in the same stack as the active view
1059
IViewReference activeView = (IViewReference) ref;
1060                IViewReference[] viewStack = getViewReferenceStack(part);
1061                for (int i = 0; i < viewStack.length; i++) {
1062                    if (viewStack[i].equals(activeView)) {
1063                        return;
1064                    }
1065                }
1066                bringToTop(part);
1067            }
1068        }
1069    }
1070
1071    /**
1072     * Returns whether a part exists in the current page.
1073     */

1074    private boolean certifyPart(IWorkbenchPart part) {
1075        //Workaround for bug 22325
1076
if (part != null && !(part.getSite() instanceof PartSite)) {
1077            return false;
1078        }
1079
1080        if (part instanceof IEditorPart) {
1081            IEditorReference ref = (IEditorReference) getReference(part);
1082            return ref != null && getEditorManager().containsEditor(ref);
1083        }
1084        if (part instanceof IViewPart) {
1085            Perspective persp = getActivePerspective();
1086            return persp != null && persp.containsView((IViewPart) part);
1087        }
1088        return false;
1089    }
1090
1091    /**
1092     * Closes the perspective.
1093     */

1094    public boolean close() {
1095        final boolean[] ret = new boolean[1];
1096        BusyIndicator.showWhile(null, new Runnable JavaDoc() {
1097            public void run() {
1098                ret[0] = window.closePage(WorkbenchPage.this, true);
1099            }
1100        });
1101        return ret[0];
1102    }
1103
1104    /**
1105     * See IWorkbenchPage
1106     */

1107    public boolean closeAllSavedEditors() {
1108        // get the Saved editors
1109
IEditorReference editors[] = getEditorReferences();
1110        IEditorReference savedEditors[] = new IEditorReference[editors.length];
1111        int j = 0;
1112        for (int i = 0; i < editors.length; i++) {
1113            IEditorReference editor = editors[i];
1114            if (!editor.isDirty()) {
1115                savedEditors[j++] = editor;
1116            }
1117        }
1118        //there are no unsaved editors
1119
if (j == 0) {
1120            return true;
1121        }
1122        IEditorReference[] newSaved = new IEditorReference[j];
1123        System.arraycopy(savedEditors, 0, newSaved, 0, j);
1124        return closeEditors(newSaved, false);
1125    }
1126
1127    /**
1128     * See IWorkbenchPage
1129     */

1130    public boolean closeAllEditors(boolean save) {
1131        return closeEditors(getEditorReferences(), save);
1132    }
1133
1134    private void updateActivePart() {
1135        
1136        if (isDeferred()) {
1137            return;
1138        }
1139        
1140        IWorkbenchPartReference oldActivePart = partList.getActivePartReference();
1141        IWorkbenchPartReference oldActiveEditor = partList.getActiveEditorReference();
1142        IWorkbenchPartReference newActivePart = null;
1143        IEditorReference newActiveEditor = null;
1144        
1145        if (!window.isClosing()) {
1146            // If an editor is active, try to keep an editor active
1147
if (oldActivePart == oldActiveEditor) {
1148                newActiveEditor = (IEditorReference)activationList.getActiveReference(true);
1149                newActivePart = newActiveEditor;
1150                if (newActivePart == null) {
1151                    // Only activate a non-editor if there's no editors left
1152
newActivePart = activationList.getActiveReference(false);
1153                }
1154            } else {
1155                // If a non-editor is active, activate whatever was activated most recently
1156
newActivePart = activationList.getActiveReference(false);
1157                
1158                if (newActivePart instanceof IEditorReference) {
1159                    // If that happens to be an editor, make it the active editor as well
1160
newActiveEditor = (IEditorReference)newActivePart;
1161                } else {
1162                    // Otherwise, select whatever editor was most recently active
1163
newActiveEditor = (IEditorReference)activationList.getActiveReference(true);
1164                }
1165            }
1166        }
1167
1168        if (newActiveEditor != oldActiveEditor) {
1169            makeActiveEditor(newActiveEditor);
1170        }
1171        
1172        if (newActivePart != oldActivePart) {
1173            makeActive(newActivePart);
1174        }
1175    }
1176    
1177    /**
1178     * Makes the given part active. Brings it in front if necessary. Permits null
1179     * (indicating that no part should be active).
1180     *
1181     * @since 3.1
1182     *
1183     * @param ref new active part (or null)
1184     */

1185    private void makeActive(IWorkbenchPartReference ref) {
1186        if (ref == null) {
1187            setActivePart(null);
1188        } else {
1189            IWorkbenchPart newActive = ref.getPart(true);
1190            if (newActive == null) {
1191                setActivePart(null);
1192            } else {
1193                activate(newActive);
1194            }
1195        }
1196    }
1197    
1198    /**
1199     * Makes the given editor active. Brings it to front if necessary. Permits <code>null</code>
1200     * (indicating that no editor is active).
1201     *
1202     * @since 3.1
1203     *
1204     * @param ref the editor to make active, or <code>null</code> for no active editor
1205     */

1206    private void makeActiveEditor(IEditorReference ref) {
1207        if (ref == getActiveEditorReference()) {
1208            return;
1209        }
1210        
1211        IEditorPart part = (ref == null) ? null : ref.getEditor(true);
1212        
1213        if (part != null) {
1214            editorMgr.setVisibleEditor(ref, false);
1215            navigationHistory.markEditor(part);
1216        }
1217        
1218        actionSwitcher.updateTopEditor(part);
1219
1220        if (ref != null) {
1221            activationList.bringToTop(getReference(part));
1222        }
1223        
1224        partList.setActiveEditor(ref);
1225    }
1226    
1227    /**
1228     * See IWorkbenchPage
1229     */

1230    public boolean closeEditors(IEditorReference[] refArray, boolean save) {
1231        if (refArray.length == 0) {
1232            return true;
1233        }
1234        
1235        // Check if we're being asked to close any parts that are already closed or cannot
1236
// be closed at this time
1237
ArrayList JavaDoc toClose = new ArrayList JavaDoc();
1238        for (int i = 0; i < refArray.length; i++) {
1239            IEditorReference reference = refArray[i];
1240            
1241            // If we're in the middle of creating this part, this is a programming error. Abort the entire
1242
// close operation. This usually occurs if someone tries to open a dialog in a method that
1243
// isn't allowed to do so, and a *syncExec tries to close the part. If this shows up in a log
1244
// file with a dialog's event loop on the stack, then the code that opened the dialog is usually
1245
// at fault.
1246
if (reference == partBeingActivated) {
1247                WorkbenchPlugin.log(new RuntimeException JavaDoc("WARNING: Blocked recursive attempt to close part " //$NON-NLS-1$
1248
+ partBeingActivated.getId() + " while still in the middle of activating it")); //$NON-NLS-1$
1249
return false;
1250            }
1251            
1252            if(reference instanceof WorkbenchPartReference) {
1253                WorkbenchPartReference ref = (WorkbenchPartReference) reference;
1254                
1255                // If we're being asked to close a part that is disposed (ie: already closed),
1256
// skip it and proceed with closing the remaining parts.
1257
if (ref.isDisposed()) {
1258                    continue;
1259                }
1260            }
1261            
1262            toClose.add(reference);
1263        }
1264        
1265        IEditorReference[] editorRefs = (IEditorReference[]) toClose.toArray(new IEditorReference[toClose.size()]);
1266        
1267        // notify the model manager before the close
1268
List JavaDoc partsToClose = new ArrayList JavaDoc();
1269        for (int i = 0; i < editorRefs.length; i++) {
1270            IEditorPart refPart = editorRefs[i].getEditor(false);
1271            if (refPart != null) {
1272                partsToClose.add(refPart);
1273            }
1274        }
1275        SaveablesList modelManager = null;
1276        Object JavaDoc postCloseInfo = null;
1277        if(partsToClose.size()>0) {
1278            modelManager = (SaveablesList) getWorkbenchWindow().getService(ISaveablesLifecycleListener.class);
1279            // this may prompt for saving and return null if the user canceled:
1280
postCloseInfo = modelManager.preCloseParts(partsToClose, save, getWorkbenchWindow());
1281            if (postCloseInfo==null) {
1282                return false;
1283            }
1284        }
1285
1286        // Fire pre-removal changes
1287
for (int i = 0; i < editorRefs.length; i++) {
1288            IEditorReference ref = editorRefs[i];
1289            
1290            // Notify interested listeners before the close
1291
window.firePerspectiveChanged(this, getPerspective(), ref,
1292                    CHANGE_EDITOR_CLOSE);
1293            
1294        }
1295        
1296        deferUpdates(true);
1297        try {
1298            if(modelManager!=null) {
1299                modelManager.postClose(postCloseInfo);
1300            }
1301            
1302            // Close all editors.
1303
for (int i = 0; i < editorRefs.length; i++) {
1304                IEditorReference ref = editorRefs[i];
1305                
1306                // Remove editor from the presentation
1307
editorPresentation.closeEditor(ref);
1308                
1309                partRemoved((WorkbenchPartReference)ref);
1310            }
1311        } finally {
1312            deferUpdates(false);
1313        }
1314                        
1315        // Notify interested listeners after the close
1316
window.firePerspectiveChanged(this, getPerspective(),
1317                CHANGE_EDITOR_CLOSE);
1318        
1319        // Return true on success.
1320
return true;
1321    }
1322    
1323    /**
1324     * Enables or disables listener notifications. This is used to delay listener notifications until the
1325     * end of a public method.
1326     *
1327     * @param shouldDefer
1328     */

1329    private void deferUpdates(boolean shouldDefer) {
1330        if (shouldDefer) {
1331            if (deferCount == 0) {
1332                startDeferring();
1333            }
1334            deferCount++;
1335        } else {
1336            deferCount--;
1337            if (deferCount == 0) {
1338                handleDeferredEvents();
1339            }
1340        }
1341    }
1342    
1343    private void startDeferring() {
1344        editorPresentation.getLayoutPart().deferUpdates(true);
1345    }
1346
1347    private void handleDeferredEvents() {
1348        editorPresentation.getLayoutPart().deferUpdates(false);
1349        updateActivePart();
1350        WorkbenchPartReference[] disposals = (WorkbenchPartReference[]) pendingDisposals.toArray(new WorkbenchPartReference[pendingDisposals.size()]);
1351        pendingDisposals.clear();
1352        for (int i = 0; i < disposals.length; i++) {
1353            WorkbenchPartReference reference = disposals[i];
1354            disposePart(reference);
1355        }
1356        
1357    }
1358    
1359    private boolean isDeferred() {
1360        return deferCount > 0;
1361    }
1362
1363    /**
1364     * See IWorkbenchPage#closeEditor
1365     */

1366    public boolean closeEditor(IEditorReference editorRef, boolean save) {
1367        return closeEditors(new IEditorReference[] {editorRef}, save);
1368    }
1369
1370    /**
1371     * See IWorkbenchPage#closeEditor
1372     */

1373    public boolean closeEditor(IEditorPart editor, boolean save) {
1374        IWorkbenchPartReference ref = getReference(editor);
1375        if (ref instanceof IEditorReference) {
1376            return closeEditors(new IEditorReference[] {(IEditorReference) ref}, save);
1377        }
1378        return false;
1379    }
1380
1381    /**
1382     * @see IWorkbenchPage#closePerspective(IPerspectiveDescriptor, boolean, boolean)
1383     */

1384    public void closePerspective(IPerspectiveDescriptor desc, boolean saveParts, boolean closePage) {
1385        Perspective persp = findPerspective(desc);
1386        if (persp != null) {
1387            closePerspective(persp, saveParts, closePage);
1388        }
1389    }
1390
1391    /**
1392     * Closes the specified perspective. If last perspective, then entire page
1393     * is closed.
1394     *
1395     * @param persp
1396     * the perspective to be closed
1397     * @param saveParts
1398     * whether the parts that are being closed should be saved
1399     * (editors if last perspective, views if not shown in other
1400     * parspectives)
1401     */

1402    /* package */
1403    void closePerspective(Perspective persp, boolean saveParts, boolean closePage) {
1404
1405        // Always unzoom
1406
if (isZoomed()) {
1407            zoomOut();
1408        }
1409
1410        List JavaDoc partsToSave = new ArrayList JavaDoc();
1411        List JavaDoc viewsToClose = new ArrayList JavaDoc();
1412        // collect views that will go away and views that are dirty
1413
IViewReference[] viewReferences = persp.getViewReferences();
1414        for (int i = 0; i < viewReferences.length; i++) {
1415            IViewReference reference = viewReferences[i];
1416            if (getViewFactory().getReferenceCount(reference) == 1) {
1417                IViewPart viewPart = reference.getView(false);
1418                if (viewPart != null) {
1419                    viewsToClose.add(viewPart);
1420                    if (saveParts && reference.isDirty()) {
1421                        partsToSave.add(viewPart);
1422                    }
1423                }
1424            }
1425        }
1426        if (saveParts && perspList.size() == 1) {
1427            // collect editors that are dirty
1428
IEditorReference[] editorReferences = getEditorReferences();
1429            for (int i = 0; i < editorReferences.length; i++) {
1430                IEditorReference reference = editorReferences[i];
1431                    if (reference.isDirty()) {
1432                        IEditorPart editorPart = reference.getEditor(false);
1433                        if (editorPart != null) {
1434                            partsToSave.add(editorPart);
1435                        }
1436                    }
1437            }
1438        }
1439        if (saveParts && !partsToSave.isEmpty()) {
1440            if (!EditorManager.saveAll(partsToSave, true, true, false, window)) {
1441                // user canceled
1442
return;
1443            }
1444        }
1445        // Close all editors on last perspective close
1446
if (perspList.size() == 1 && getEditorManager().getEditorCount() > 0) {
1447            // Close all editors
1448
if (!closeAllEditors(false)) {
1449                return;
1450            }
1451        }
1452        
1453        // closeAllEditors already notified the saveables list about the editors.
1454
SaveablesList saveablesList = (SaveablesList) getWorkbenchWindow().getWorkbench().getService(ISaveablesLifecycleListener.class);
1455        // we took care of the saving already, so pass in false (postCloseInfo will be non-null)
1456
Object JavaDoc postCloseInfo = saveablesList.preCloseParts(viewsToClose, false, getWorkbenchWindow());
1457        saveablesList.postClose(postCloseInfo);
1458
1459        // Dispose of the perspective
1460
boolean isActive = (perspList.getActive() == persp);
1461        if (isActive) {
1462            setPerspective(perspList.getNextActive());
1463        }
1464        disposePerspective(persp, true);
1465        if (closePage && perspList.size() == 0) {
1466            close();
1467        }
1468    }
1469
1470    /**
1471     * Forces all perspectives on the page to zoom out.
1472     */

1473    public void unzoomAllPerspectives() {
1474        for (Iterator JavaDoc perspIter = perspList.iterator(); perspIter.hasNext();) {
1475            Perspective persp = (Perspective) perspIter.next();
1476            persp.getPresentation().forceNoZoom();
1477        }
1478    }
1479    
1480    /**
1481     * @see IWorkbenchPage#closeAllPerspectives(boolean, boolean)
1482     */

1483    public void closeAllPerspectives(boolean saveEditors, boolean closePage) {
1484
1485        if (perspList.isEmpty()) {
1486            return;
1487        }
1488
1489        // Always unzoom
1490
if (isZoomed()) {
1491            zoomOut();
1492        }
1493
1494        if(saveEditors) {
1495            if (!saveAllEditors(true)) {
1496                return;
1497            }
1498        }
1499        // Close all editors
1500
if (!closeAllEditors(false)) {
1501            return;
1502        }
1503
1504        // Deactivate the active perspective and part
1505
setPerspective((Perspective) null);
1506
1507        // Close each perspective in turn
1508
PerspectiveList oldList = perspList;
1509        perspList = new PerspectiveList();
1510        Iterator JavaDoc itr = oldList.iterator();
1511        while (itr.hasNext()) {
1512            closePerspective((Perspective) itr.next(), false, false);
1513        }
1514        if (closePage) {
1515            close();
1516        }
1517    }
1518
1519    /**
1520     * Creates the client composite.
1521     */

1522    private void createClientComposite() {
1523        final Composite parent = window.getPageComposite();
1524        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1525
1526            public void runWithException() {
1527                composite = new Composite(parent, SWT.NONE);
1528                composite.setVisible(false); // Make visible on activate.
1529
// force the client composite to be layed out
1530
parent.layout();
1531            }
1532        });
1533       
1534    }
1535
1536    /**
1537     * Creates a new view set. Return null on failure.
1538     *
1539     * @param desc the perspective descriptor
1540     * @param notify whether to fire a perspective opened event
1541     */

1542    private Perspective createPerspective(PerspectiveDescriptor desc, boolean notify) {
1543        String JavaDoc label = desc.getId(); // debugging only
1544
try {
1545            UIStats.start(UIStats.CREATE_PERSPECTIVE, label);
1546            Perspective persp = new Perspective(desc, this);
1547            perspList.add(persp);
1548            if (notify) {
1549                window.firePerspectiveOpened(this, desc);
1550            }
1551            //if the perspective is fresh and uncustomzied then it is not dirty
1552
//no reset will be prompted for
1553
if (!desc.hasCustomDefinition()) {
1554                dirtyPerspectives.remove(desc.getId());
1555            }
1556            return persp;
1557        } catch (WorkbenchException e) {
1558            if (!((Workbench) window.getWorkbench()).isStarting()) {
1559                MessageDialog
1560                        .openError(
1561                                window.getShell(),
1562                                WorkbenchMessages.Error,
1563                                NLS.bind(WorkbenchMessages.Workbench_showPerspectiveError,desc.getId() ));
1564            }
1565            return null;
1566        } finally {
1567            UIStats.end(UIStats.CREATE_PERSPECTIVE, desc.getId(), label);
1568        }
1569    }
1570
1571    /**
1572     * This is called by child objects after a part has been added to the page.
1573     * The page will in turn notify its listeners.
1574     */

1575    /* package */ void partAdded(WorkbenchPartReference ref) {
1576        activationList.add(ref);
1577        partList.addPart(ref);
1578        
1579        // If we're adding a new editor then allow fast views
1580
// to remain open
1581
if (ref instanceof IEditorReference) {
1582            includeActiveFastViews = true;
1583            updateActivePart();
1584            includeActiveFastViews = false;
1585        }
1586        else
1587            updateActivePart();
1588    }
1589    
1590    /**
1591     * This is called by child objects after a part has been added to the page.
1592     * The part will be queued for disposal after all listeners have been notified
1593     */

1594    /* package */ void partRemoved(WorkbenchPartReference ref) {
1595        activationList.remove(ref);
1596        disposePart(ref);
1597    }
1598    
1599    private void disposePart(WorkbenchPartReference ref) {
1600        if (isDeferred()) {
1601            pendingDisposals.add(ref);
1602        } else {
1603            partList.removePart(ref);
1604            ref.dispose();
1605        }
1606    }
1607    
1608    /**
1609     * Deactivates a part. The pane is unhilighted.
1610     */

1611    private void deactivatePart(IWorkbenchPart part) {
1612        if (part != null) {
1613            PartSite site = (PartSite) part.getSite();
1614            site.getPane().showFocus(false);
1615        }
1616    }
1617    
1618    /**
1619     * Detaches a view from the WorkbenchWindow.
1620     */

1621    public void detachView(IViewReference ref){
1622        Perspective persp = getActivePerspective();
1623        if(persp == null) {
1624            return;
1625        }
1626        
1627        PerspectiveHelper presentation = persp.getPresentation();
1628        presentation.detachPart(ref);
1629    }
1630    
1631    /**
1632     * Removes a detachedwindow.
1633     */

1634    public void attachView(IViewReference ref){
1635        PerspectiveHelper presentation = getPerspectivePresentation();
1636        presentation.attachPart(ref);
1637    }
1638
1639    /**
1640     * Cleanup.
1641     */

1642    public void dispose() {
1643
1644        // Always unzoom
1645
if (isZoomed()) {
1646            zoomOut();
1647        }
1648
1649        makeActiveEditor(null);
1650        makeActive(null);
1651        
1652        // Close and dispose the editors.
1653
closeAllEditors(false);
1654        
1655        // Need to make sure model data is cleaned up when the page is
1656
// disposed. Collect all the views on the page and notify the
1657
// saveable list of a pre/post close. This will free model data.
1658
IWorkbenchPartReference[] partsToClose = getOpenParts();
1659        List JavaDoc dirtyParts = new ArrayList JavaDoc(partsToClose.length);
1660        for (int i = 0; i < partsToClose.length; i++) {
1661            IWorkbenchPart part = partsToClose[i].getPart(false);
1662            if (part != null && part instanceof IViewPart) {
1663                dirtyParts.add(part);
1664            }
1665        }
1666        SaveablesList saveablesList = (SaveablesList) getWorkbenchWindow().getWorkbench().getService(ISaveablesLifecycleListener.class);
1667        Object JavaDoc postCloseInfo = saveablesList.preCloseParts(dirtyParts, false,getWorkbenchWindow());
1668        saveablesList.postClose(postCloseInfo);
1669
1670        // Get rid of perspectives. This will close the views.
1671
Iterator JavaDoc itr = perspList.iterator();
1672        while (itr.hasNext()) {
1673            Perspective perspective = (Perspective) itr.next();
1674            window.firePerspectiveClosed(this, perspective.getDesc());
1675            perspective.dispose();
1676        }
1677        perspList = new PerspectiveList();
1678
1679        // Capture views.
1680
IViewReference refs[] = viewFactory.getViews();
1681
1682        if (refs.length > 0) {
1683            // Dispose views.
1684
for (int i = 0; i < refs.length; i++) {
1685                final WorkbenchPartReference ref = (WorkbenchPartReference) refs[i];
1686                //partList.removePart(ref);
1687
//firePartClosed(refs[i]);
1688
Platform.run(new SafeRunnable() {
1689                    public void run() {
1690// WorkbenchPlugin.log(new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH,
1691
// Status.OK, "WorkbenchPage leaked a refcount for view " + ref.getId(), null)); //$NON-NLS-1$//$NON-NLS-2$
1692

1693                        ref.dispose();
1694                    }
1695    
1696                    public void handleException(Throwable JavaDoc e) {
1697                    }
1698                });
1699            }
1700        }
1701        
1702        activationList = new ActivationList();
1703
1704        // Get rid of editor presentation.
1705
editorPresentation.dispose();
1706
1707        // Get rid of composite.
1708
composite.dispose();
1709
1710        navigationHistory.dispose();
1711
1712        stickyViewMan.clear();
1713        
1714        if (tracker != null) {
1715            tracker.close();
1716        }
1717        
1718        // if we're destroying a window in a non-shutdown situation then we should
1719
// clean up the working set we made.
1720
if (!window.getWorkbench().isClosing()) {
1721                if (aggregateWorkingSet != null) {
1722                    PlatformUI.getWorkbench().getWorkingSetManager().removeWorkingSet(aggregateWorkingSet);
1723                }
1724        }
1725    }
1726
1727    /**
1728     * Dispose a perspective.
1729     *
1730     * @param persp the perspective descriptor
1731     * @param notify whether to fire a perspective closed event
1732     */

1733    private void disposePerspective(Perspective persp, boolean notify) {
1734        // Get rid of perspective.
1735
perspList.remove(persp);
1736        if (notify) {
1737            window.firePerspectiveClosed(this, persp.getDesc());
1738        }
1739        persp.dispose();
1740
1741        stickyViewMan.remove(persp.getDesc().getId());
1742    }
1743
1744    /**
1745     * @return NavigationHistory
1746     */

1747    public INavigationHistory getNavigationHistory() {
1748        return navigationHistory;
1749    }
1750
1751    /**
1752     * Edits the action sets.
1753     */

1754    public boolean editActionSets() {
1755        Perspective persp = getActivePerspective();
1756        if (persp == null) {
1757            return false;
1758        }
1759
1760        // Create list dialog.
1761
CustomizePerspectiveDialog dlg = window.createCustomizePerspectiveDialog(persp);
1762        
1763        // Open.
1764
boolean ret = (dlg.open() == Window.OK);
1765        if (ret) {
1766            window.updateActionSets();
1767            window.firePerspectiveChanged(this, getPerspective(), CHANGE_RESET);
1768            window.firePerspectiveChanged(this, getPerspective(),
1769                    CHANGE_RESET_COMPLETE);
1770        }
1771        return ret;
1772    }
1773
1774    /**
1775     * Returns the first view manager with given ID.
1776     */

1777    public Perspective findPerspective(IPerspectiveDescriptor desc) {
1778        Iterator JavaDoc itr = perspList.iterator();
1779        while (itr.hasNext()) {
1780            Perspective mgr = (Perspective) itr.next();
1781            if (desc.getId().equals(mgr.getDesc().getId())) {
1782                return mgr;
1783            }
1784        }
1785        return null;
1786    }
1787
1788    /**
1789     * See IWorkbenchPage@findView.
1790     */

1791    public IViewPart findView(String JavaDoc id) {
1792        IViewReference ref = findViewReference(id);
1793        if (ref == null) {
1794            return null;
1795        }
1796        return ref.getView(true);
1797    }
1798
1799    /*
1800     * (non-Javadoc)
1801     *
1802     * @see org.eclipse.ui.IWorkbenchPage
1803     */

1804    public IViewReference findViewReference(String JavaDoc viewId) {
1805        return findViewReference(viewId, null);
1806    }
1807
1808    /*
1809     * (non-Javadoc)
1810     *
1811     * @see org.eclipse.ui.IWorkbenchPage
1812     */

1813    public IViewReference findViewReference(String JavaDoc viewId, String JavaDoc secondaryId) {
1814        Perspective persp = getActivePerspective();
1815        if (persp == null) {
1816            return null;
1817        }
1818        return persp.findView(viewId, secondaryId);
1819    }
1820
1821
1822    /**
1823     * Notify property change listeners about a property change.
1824     *
1825     * @param changeId
1826     * the change id
1827     * @param oldValue
1828     * old property value
1829     * @param newValue
1830     * new property value
1831     */

1832    private void firePropertyChange(String JavaDoc changeId, Object JavaDoc oldValue,
1833            Object JavaDoc newValue) {
1834        
1835        UIListenerLogging.logPagePropertyChanged(this, changeId, oldValue, newValue);
1836        
1837        Object JavaDoc[] listeners = propertyChangeListeners.getListeners();
1838        PropertyChangeEvent event = new PropertyChangeEvent(this, changeId,
1839                oldValue, newValue);
1840
1841        for (int i = 0; i < listeners.length; i++) {
1842            ((IPropertyChangeListener) listeners[i]).propertyChange(event);
1843        }
1844    }
1845
1846    /*
1847     * Returns the action bars.
1848     */

1849    public IActionBars getActionBars() {
1850        if (actionBars == null) {
1851            actionBars = new WWinActionBars(window);
1852        }
1853        return actionBars;
1854    }
1855
1856    /**
1857     * Returns an array of the visible action sets.
1858     */

1859    public IActionSetDescriptor[] getActionSets() {
1860        Collection JavaDoc collection = actionSets.getVisibleItems();
1861        
1862        return (IActionSetDescriptor[]) collection.toArray(new IActionSetDescriptor[collection.size()]);
1863    }
1864
1865    /**
1866     * @see IWorkbenchPage
1867     */

1868    public IEditorPart getActiveEditor() {
1869        return partList.getActiveEditor();
1870    }
1871
1872    /**
1873     * Returns the reference for the active editor, or <code>null</code>
1874     * if there is no active editor.
1875     *
1876     * @return the active editor reference or <code>null</code>
1877     */

1878    public IEditorReference getActiveEditorReference() {
1879        return partList.getActiveEditorReference();
1880    }
1881    
1882    /*
1883     * (non-Javadoc) Method declared on IPartService
1884     */

1885    public IWorkbenchPart getActivePart() {
1886        return partList.getActivePart();
1887    }
1888
1889    /*
1890     * (non-Javadoc) Method declared on IPartService
1891     */

1892    public IWorkbenchPartReference getActivePartReference() {
1893        return partList.getActivePartReference();
1894    }
1895
1896    /**
1897     * Returns the active perspective for the page, <code>null</code> if
1898     * none.
1899     */

1900    public Perspective getActivePerspective() {
1901        return perspList.getActive();
1902    }
1903
1904    /**
1905     * Returns the client composite.
1906     */

1907    public Composite getClientComposite() {
1908        return composite;
1909    }
1910
1911    // for dynamic UI - change access from private to protected
1912
// for testing purposes only, changed from protected to public
1913
/**
1914     * Answer the editor manager for this window.
1915     */

1916    public EditorManager getEditorManager() {
1917        return editorMgr;
1918    }
1919
1920    /**
1921     * Answer the perspective presentation.
1922     */

1923    public PerspectiveHelper getPerspectivePresentation() {
1924        if (getActivePerspective() != null) {
1925            return getActivePerspective().getPresentation();
1926        }
1927        return null;
1928    }
1929
1930    /**
1931     * Answer the editor presentation.
1932     */

1933    public EditorAreaHelper getEditorPresentation() {
1934        return editorPresentation;
1935    }
1936
1937    /**
1938     * See IWorkbenchPage.
1939     */

1940    public IEditorPart[] getEditors() {
1941        final IEditorReference refs[] = getEditorReferences();
1942        final ArrayList JavaDoc result = new ArrayList JavaDoc(refs.length);
1943        Display d = getWorkbenchWindow().getShell().getDisplay();
1944        //Must be backward compatible.
1945
d.syncExec(new Runnable JavaDoc() {
1946            public void run() {
1947                for (int i = 0; i < refs.length; i++) {
1948                    IWorkbenchPart part = refs[i].getPart(true);
1949                    if (part != null) {
1950                        result.add(part);
1951                    }
1952                }
1953            }
1954        });
1955        final IEditorPart editors[] = new IEditorPart[result.size()];
1956        return (IEditorPart[]) result.toArray(editors);
1957    }
1958
1959    public IEditorPart[] getDirtyEditors() {
1960        return getEditorManager().getDirtyEditors();
1961    }
1962    
1963    public ISaveablePart[] getDirtyParts() {
1964        List JavaDoc result = new ArrayList JavaDoc(3);
1965        IWorkbenchPartReference[] allParts = getAllParts();
1966        for (int i = 0; i < allParts.length; i++) {
1967            IWorkbenchPartReference reference = allParts[i];
1968            
1969            IWorkbenchPart part = reference.getPart(false);
1970            if (part != null && part instanceof ISaveablePart) {
1971                ISaveablePart saveable = (ISaveablePart)part;
1972                if (saveable.isDirty()) {
1973                    result.add(saveable);
1974                }
1975            }
1976        }
1977        
1978        return (ISaveablePart[]) result.toArray(new ISaveablePart[result.size()]);
1979    }
1980  
1981    /**
1982     * See IWorkbenchPage.
1983     */

1984    public IEditorPart findEditor(IEditorInput input) {
1985        return getEditorManager().findEditor(input);
1986    }
1987
1988    /**
1989     * See IWorkbenchPage.
1990     */

1991    public IEditorReference[] findEditors(IEditorInput input, String JavaDoc editorId, int matchFlags) {
1992        return getEditorManager().findEditors(input, editorId, matchFlags);
1993    }
1994    
1995    /**
1996     * See IWorkbenchPage.
1997     */

1998    public IEditorReference[] getEditorReferences() {
1999        return editorPresentation.getEditors();
2000    }
2001
2002    /**
2003     * Returns the docked views.
2004     */

2005    public IViewReference[] getFastViews() {
2006        Perspective persp = getActivePerspective();
2007        if (persp != null) {
2008            return persp.getFastViews();
2009        } else {
2010            return new IViewReference[0];
2011        }
2012    }
2013
2014    /**
2015     * @see IWorkbenchPage
2016     */

2017    public IAdaptable getInput() {
2018        return input;
2019    }
2020
2021    /**
2022     * Returns the page label. This is a combination of the page input and
2023     * active perspective.
2024     */

2025    public String JavaDoc getLabel() {
2026        String JavaDoc label = WorkbenchMessages.WorkbenchPage_UnknownLabel;
2027        IWorkbenchAdapter adapter = (IWorkbenchAdapter) Util.getAdapter(input,
2028                IWorkbenchAdapter.class);
2029        if (adapter != null) {
2030            label = adapter.getLabel(input);
2031        }
2032        Perspective persp = getActivePerspective();
2033        if (persp != null) {
2034            label = NLS.bind(WorkbenchMessages.WorkbenchPage_PerspectiveFormat, label, persp.getDesc().getLabel());
2035        } else if (deferredActivePersp != null) {
2036            label = NLS.bind(WorkbenchMessages.WorkbenchPage_PerspectiveFormat,label, deferredActivePersp.getLabel());
2037        }
2038        return label;
2039    }
2040
2041    /**
2042     * Returns the perspective.
2043     */

2044    public IPerspectiveDescriptor getPerspective() {
2045        if (deferredActivePersp != null) {
2046            return deferredActivePersp;
2047        }
2048        Perspective persp = getActivePerspective();
2049        if (persp != null) {
2050            return persp.getDesc();
2051        } else {
2052            return null;
2053        }
2054    }
2055
2056    /*
2057     * (non-Javadoc) Method declared on ISelectionService
2058     */

2059    public ISelection getSelection() {
2060        return selectionService.getSelection();
2061    }
2062
2063    /*
2064     * (non-Javadoc) Method declared on ISelectionService
2065     */

2066    public ISelection getSelection(String JavaDoc partId) {
2067        return selectionService.getSelection(partId);
2068    }
2069
2070    /**
2071     * Returns the ids of the parts to list in the Show In... prompter. This is
2072     * a List of Strings.
2073     */

2074    public ArrayList JavaDoc getShowInPartIds() {
2075        Perspective persp = getActivePerspective();
2076        if (persp != null) {
2077            return persp.getShowInPartIds();
2078        } else {
2079            return new ArrayList JavaDoc();
2080        }
2081    }
2082
2083    /**
2084     * The user successfully performed a Show In... action on the specified
2085     * part. Update the list of Show In items accordingly.
2086     */

2087    public void performedShowIn(String JavaDoc partId) {
2088        Perspective persp = getActivePerspective();
2089        if (persp != null) {
2090            persp.performedShowIn(partId);
2091        }
2092    }
2093
2094    /**
2095     * Sorts the given collection of show in target part ids in MRU order.
2096     */

2097    public void sortShowInPartIds(ArrayList JavaDoc partIds) {
2098        final Perspective persp = getActivePerspective();
2099        if (persp != null) {
2100            Collections.sort(partIds, new Comparator JavaDoc() {
2101                public int compare(Object JavaDoc a, Object JavaDoc b) {
2102                    long ta = persp.getShowInTime((String JavaDoc) a);
2103                    long tb = persp.getShowInTime((String JavaDoc) b);
2104                    return (ta == tb) ? 0 : ((ta > tb) ? -1 : 1);
2105                }
2106            });
2107        }
2108    }
2109
2110    /*
2111     * Returns the view factory.
2112     */

2113    public ViewFactory getViewFactory() {
2114        if (viewFactory == null) {
2115            viewFactory = new ViewFactory(this, WorkbenchPlugin.getDefault()
2116                    .getViewRegistry());
2117        }
2118        return viewFactory;
2119    }
2120
2121    /**
2122     * See IWorkbenchPage.
2123     */

2124    public IViewReference[] getViewReferences() {
2125        Perspective persp = getActivePerspective();
2126        if (persp != null) {
2127            return persp.getViewReferences();
2128        } else {
2129            return new IViewReference[0];
2130        }
2131    }
2132
2133    /**
2134     * See IWorkbenchPage.
2135     */

2136    public IViewPart[] getViews() {
2137        return getViews(null, true);
2138    }
2139    
2140    /**
2141     * Returns all view parts in the specified perspective
2142     *
2143     * @param persp the perspective
2144     * @return an array of view parts
2145     * @since 3.1
2146     */

2147    /*package*/IViewPart[] getViews(Perspective persp, boolean restore) {
2148        if (persp == null) {
2149            persp = getActivePerspective();
2150        }
2151        
2152        if (persp != null) {
2153            IViewReference refs[] = persp.getViewReferences();
2154            ArrayList JavaDoc parts = new ArrayList JavaDoc(refs.length);
2155            for (int i = 0; i < refs.length; i++) {
2156                IWorkbenchPart part = refs[i].getPart(restore);
2157                if (part != null) {
2158                    parts.add(part);
2159                }
2160            }
2161            IViewPart[] result = new IViewPart[parts.size()];
2162            return (IViewPart[]) parts.toArray(result);
2163        }
2164        return new IViewPart[0];
2165    }
2166
2167    /**
2168     * See IWorkbenchPage.
2169     */

2170    public IWorkbenchWindow getWorkbenchWindow() {
2171        return window;
2172    }
2173
2174    /**
2175     * Implements IWorkbenchPage
2176     *
2177     * @see org.eclipse.ui.IWorkbenchPage#getWorkingSet()
2178     * @since 2.0
2179     * @deprecated individual views should store a working set if needed
2180     */

2181    public IWorkingSet getWorkingSet() {
2182        return workingSet;
2183    }
2184
2185    /**
2186     * @see IWorkbenchPage
2187     */

2188    public void hideActionSet(String JavaDoc actionSetID) {
2189        Perspective persp = getActivePerspective();
2190        if (persp != null) {
2191            persp.removeActionSet(actionSetID);
2192            window.updateActionSets();
2193            window.firePerspectiveChanged(this, getPerspective(),
2194                    CHANGE_ACTION_SET_HIDE);
2195        }
2196    }
2197
2198    /*
2199     * (non-Javadoc)
2200     *
2201     * @see org.eclipse.ui.IWorkbenchPage#hideView(org.eclipse.ui.IViewReference)
2202     */

2203    public void hideView(IViewReference ref) {
2204        
2205        // Sanity check.
2206
if (ref == null) {
2207            return;
2208        }
2209
2210        Perspective persp = getActivePerspective();
2211        if (persp == null) {
2212            return;
2213        }
2214
2215        boolean promptedForSave = false;
2216        IViewPart view = ref.getView(false);
2217        if (view != null) {
2218
2219            if (!certifyPart(view)) {
2220                return;
2221            }
2222            
2223            // Confirm.
2224
if (view instanceof ISaveablePart) {
2225                ISaveablePart saveable = (ISaveablePart)view;
2226                if (saveable.isSaveOnCloseNeeded()) {
2227                    IWorkbenchWindow window = view.getSite().getWorkbenchWindow();
2228                    boolean success = EditorManager.saveAll(Collections.singletonList(view), true, true, false, window);
2229                    if (!success) {
2230                        // the user cancelled.
2231
return;
2232                    }
2233                    promptedForSave = true;
2234                }
2235            }
2236        }
2237        
2238        int refCount = getViewFactory().getReferenceCount(ref);
2239        SaveablesList saveablesList = null;
2240        Object JavaDoc postCloseInfo = null;
2241        if (refCount == 1) {
2242            IWorkbenchPart actualPart = ref.getPart(false);
2243            if (actualPart != null) {
2244                saveablesList = (SaveablesList) actualPart
2245                        .getSite().getService(ISaveablesLifecycleListener.class);
2246                postCloseInfo = saveablesList.preCloseParts(Collections
2247                        .singletonList(actualPart), !promptedForSave, this
2248                        .getWorkbenchWindow());
2249                if (postCloseInfo==null) {
2250                    // cancel
2251
return;
2252                }
2253            }
2254        }
2255        
2256        // Notify interested listeners before the hide
2257
window.firePerspectiveChanged(this, persp.getDesc(), ref,
2258                CHANGE_VIEW_HIDE);
2259
2260        PartPane pane = getPane(ref);
2261        pane.setInLayout(false);
2262        
2263        updateActivePart();
2264        
2265        if (saveablesList != null) {
2266            saveablesList.postClose(postCloseInfo);
2267        }
2268
2269        // Hide the part.
2270
persp.hideView(ref);
2271
2272        // Notify interested listeners after the hide
2273
window.firePerspectiveChanged(this, getPerspective(), CHANGE_VIEW_HIDE);
2274    }
2275
2276    /* package */void refreshActiveView() {
2277        updateActivePart();
2278    }
2279
2280    /**
2281     * See IPerspective
2282     */

2283    public void hideView(IViewPart view) {
2284        hideView((IViewReference)getReference(view));
2285    }
2286
2287    /**
2288     * Initialize the page.
2289     *
2290     * @param w
2291     * the parent window
2292     * @param layoutID
2293     * may be <code>null</code> if restoring from file
2294     * @param input
2295     * the page input
2296     * @param openExtras
2297     * whether to process the perspective extras preference
2298     */

2299    private void init(WorkbenchWindow w, String JavaDoc layoutID, IAdaptable input, boolean openExtras)
2300            throws WorkbenchException {
2301        // Save args.
2302
this.window = w;
2303        this.input = input;
2304        actionSets = new ActionSetManager(w);
2305
2306        // Create presentation.
2307
createClientComposite();
2308        editorPresentation = new EditorAreaHelper(this);
2309        editorMgr = new EditorManager(window, this, editorPresentation);
2310
2311        // add this page as a client to be notified when the UI has re-orded perspectives
2312
// so that the order can be properly maintained in the receiver.
2313
// E.g. a UI might support drag-and-drop and will need to make this known to ensure
2314
// #saveState and #restoreState do not lose this re-ordering
2315
w.addPerspectiveReorderListener(new IReorderListener() {
2316            public void reorder(Object JavaDoc perspective, int newLoc) {
2317                perspList.reorder((IPerspectiveDescriptor)perspective, newLoc);
2318            }
2319        });
2320        
2321        if (openExtras) {
2322            openPerspectiveExtras();
2323        }
2324        
2325        // Get perspective descriptor.
2326
if (layoutID != null) {
2327            PerspectiveDescriptor desc = (PerspectiveDescriptor) WorkbenchPlugin
2328                    .getDefault().getPerspectiveRegistry()
2329                    .findPerspectiveWithId(layoutID);
2330            if (desc == null) {
2331                throw new WorkbenchException(
2332                        NLS.bind(WorkbenchMessages.WorkbenchPage_ErrorCreatingPerspective,layoutID ));
2333            }
2334            Perspective persp = findPerspective(desc);
2335            if (persp == null) {
2336                persp = createPerspective(desc, true);
2337            }
2338            perspList.setActive(persp);
2339            window.firePerspectiveActivated(this, desc);
2340        }
2341        
2342        getExtensionTracker()
2343                .registerHandler(
2344                        perspectiveChangeHandler,
2345                        ExtensionTracker
2346                                .createExtensionPointFilter(getPerspectiveExtensionPoint()));
2347    }
2348    
2349    /**
2350     * Opens the perspectives specified in the PERSPECTIVE_BAR_EXTRAS preference (see bug 84226).
2351     */

2352    public void openPerspectiveExtras() {
2353        String JavaDoc extras = PrefUtil.getAPIPreferenceStore().getString(
2354                IWorkbenchPreferenceConstants.PERSPECTIVE_BAR_EXTRAS);
2355        StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(extras, ", "); //$NON-NLS-1$
2356
ArrayList JavaDoc descs = new ArrayList JavaDoc();
2357        while (tok.hasMoreTokens()) {
2358            String JavaDoc id = tok.nextToken();
2359            IPerspectiveDescriptor desc = WorkbenchPlugin.getDefault().getPerspectiveRegistry().findPerspectiveWithId(id);
2360            if (desc != null) {
2361                descs.add(desc);
2362            }
2363        }
2364        // HACK: The perspective switcher currently adds the button for a new perspective to the beginning of the list.
2365
// So, we process the extra perspectives in reverse order here to have their buttons appear in the order declared.
2366
for (int i = descs.size(); --i >= 0;) {
2367            PerspectiveDescriptor desc = (PerspectiveDescriptor) descs.get(i);
2368            if (findPerspective(desc) == null) {
2369                createPerspective(desc, true);
2370            }
2371        }
2372    }
2373
2374    /**
2375     * See IWorkbenchPage.
2376     */

2377    public boolean isPartVisible(IWorkbenchPart part) {
2378        PartPane pane = getPane(part);
2379        return pane != null && pane.getVisible();
2380    }
2381    
2382    /**
2383     * See IWorkbenchPage.
2384     */

2385    public boolean isEditorAreaVisible() {
2386        Perspective persp = getActivePerspective();
2387        if (persp == null) {
2388            return false;
2389        }
2390        return persp.isEditorAreaVisible();
2391    }
2392
2393    /**
2394     * Returns whether the view is fast.
2395     */

2396    public boolean isFastView(IViewReference ref) {
2397        Perspective persp = getActivePerspective();
2398        if (persp != null) {
2399            return persp.isFastView(ref);
2400        } else {
2401            return false;
2402        }
2403    }
2404    
2405    /**
2406     * Return whether the view is closeable or not.
2407     *
2408     * @param ref the view reference to check. Must not be <code>null</code>.
2409     * @return true if the part is closeable.
2410     * @since 3.1.1
2411     */

2412    public boolean isCloseable(IViewReference ref) {
2413        Perspective persp = getActivePerspective();
2414        if (persp != null) {
2415            return persp.isCloseable(ref);
2416        }
2417        return false;
2418    }
2419
2420    /**
2421     * Return whether the view is moveable or not.
2422     *
2423     * @param ref the view reference to check. Must not be <code>null</code>.
2424     * @return true if the part is moveable.
2425     * @since 3.1.1
2426     */

2427    public boolean isMoveable(IViewReference ref) {
2428        Perspective persp = getActivePerspective();
2429        if (persp != null) {
2430            return persp.isMoveable(ref);
2431        }
2432        return false;
2433    }
2434
2435    /**
2436     * Returns whether the layout of the active
2437     * perspective is fixed.
2438     */

2439    public boolean isFixedLayout() {
2440        Perspective persp = getActivePerspective();
2441        if (persp != null) {
2442            return persp.isFixedLayout();
2443        } else {
2444            return false;
2445        }
2446    }
2447
2448    /**
2449     * Return the active fast view or null if there are no fast views or if
2450     * there are all minimized.
2451     */

2452    public IViewReference getActiveFastView() {
2453        Perspective persp = getActivePerspective();
2454        if (persp != null) {
2455            return persp.getActiveFastView();
2456        } else {
2457            return null;
2458        }
2459    }
2460
2461    /**
2462     * Return true if the perspective has a dirty editor.
2463     */

2464    protected boolean isSaveNeeded() {
2465        return getEditorManager().isSaveAllNeeded();
2466    }
2467
2468    /* (non-Javadoc)
2469     * @see org.eclipse.ui.IWorkbenchPage#isPageZoomed()
2470     */

2471    public boolean isPageZoomed() {
2472        Perspective persp = getActivePerspective();
2473        if (persp == null) {
2474            return false;
2475        }
2476        if (persp.getPresentation() == null) {
2477            return false;
2478        }
2479        
2480        if (Perspective.useNewMinMax(persp))
2481            return persp.getPresentation().getMaximizedStack() != null;
2482        
2483        // Default to the legacy code
2484
return isZoomed();
2485    }
2486    
2487    /**
2488     * Returns whether the page is zoomed.
2489     * @return <code>true</code> if the page is zoomed.
2490     *
2491     * <strong>NOTE:</strong> As of 3.3 this method should always return 'false'
2492     * when using the new min/max behavior. It is only used for
2493     * legacy 'zoom' handling.
2494     *
2495     */

2496   public boolean isZoomed() {
2497        Perspective persp = getActivePerspective();
2498        if (persp == null) {
2499            return false;
2500        }
2501        if (persp.getPresentation() == null) {
2502            return false;
2503        }
2504        return persp.getPresentation().isZoomed();
2505    }
2506
2507    /**
2508     * This method is called when the page is activated.
2509     */

2510    protected void onActivate() {
2511        composite.setVisible(true);
2512        Perspective persp = getActivePerspective();
2513
2514        if (persp != null) {
2515            persp.onActivate();
2516            updateVisibility(null, persp);
2517        }
2518    }
2519
2520    /**
2521     * This method is called when the page is deactivated.
2522     */

2523    protected void onDeactivate() {
2524        makeActiveEditor(null);
2525        makeActive(null);
2526        if (getActivePerspective() != null) {
2527            getActivePerspective().onDeactivate();
2528        }
2529        composite.setVisible(false);
2530    }
2531
2532    /**
2533     * See IWorkbenchPage.
2534     */

2535    public void reuseEditor(IReusableEditor editor, IEditorInput input) {
2536        
2537        // Rather than calling editor.setInput on the editor directly, we do it through the part reference.
2538
// This case lets us detect badly behaved editors that are not firing a PROP_INPUT event in response
2539
// to the input change... but if all editors obeyed their API contract, the "else" branch would be
2540
// sufficient.
2541
IWorkbenchPartReference ref = getReference(editor);
2542        if (ref instanceof EditorReference) {
2543            EditorReference editorRef = (EditorReference) ref;
2544            
2545            editorRef.setInput(input);
2546        } else {
2547            editor.setInput(input);
2548        }
2549        navigationHistory.markEditor(editor);
2550    }
2551
2552    /**
2553     * See IWorkbenchPage.
2554     */

2555    public IEditorPart openEditor(IEditorInput input, String JavaDoc editorID)
2556            throws PartInitException {
2557        return openEditor(input, editorID, true, MATCH_INPUT);
2558    }
2559
2560    /**
2561     * See IWorkbenchPage.
2562     */

2563    public IEditorPart openEditor(IEditorInput input, String JavaDoc editorID,
2564            boolean activate) throws PartInitException {
2565        return openEditor(input, editorID, activate, MATCH_INPUT);
2566    }
2567    
2568    /**
2569     * See IWorkbenchPage.
2570     */

2571    public IEditorPart openEditor(final IEditorInput input,
2572            final String JavaDoc editorID, final boolean activate, final int matchFlags)
2573            throws PartInitException {
2574        return openEditor(input, editorID, activate, matchFlags, null);
2575    }
2576    
2577    /**
2578     * This is not public API but for use internally. editorState can be <code>null</code>.
2579     */

2580    public IEditorPart openEditor(final IEditorInput input,
2581            final String JavaDoc editorID, final boolean activate, final int matchFlags,
2582            final IMemento editorState)
2583            throws PartInitException {
2584        if (input == null || editorID == null) {
2585            throw new IllegalArgumentException JavaDoc();
2586        }
2587
2588        final IEditorPart result[] = new IEditorPart[1];
2589        final PartInitException ex[] = new PartInitException[1];
2590        BusyIndicator.showWhile(window.getWorkbench().getDisplay(),
2591                new Runnable JavaDoc() {
2592                    public void run() {
2593                        try {
2594                            result[0] = busyOpenEditor(input, editorID,
2595                                    activate, matchFlags, editorState);
2596                        } catch (PartInitException e) {
2597                            ex[0] = e;
2598                        }
2599                    }
2600                });
2601        if (ex[0] != null) {
2602            throw ex[0];
2603        }
2604        return result[0];
2605    }
2606
2607    
2608    /*
2609     * Added to fix Bug 178235 [EditorMgmt] DBCS 3.3 - Cannot open file with external program.
2610     * Opens a new editor using the given input and descriptor. (Normally, editors are opened using
2611     * an editor ID and an input.)
2612     */

2613    public IEditorPart openEditorFromDescriptor(final IEditorInput input,
2614            final IEditorDescriptor editorDescriptor, final boolean activate,
2615            final IMemento editorState)
2616    throws PartInitException {
2617        if (input == null || !(editorDescriptor instanceof EditorDescriptor)) {
2618            throw new IllegalArgumentException JavaDoc();
2619        }
2620        
2621        final IEditorPart result[] = new IEditorPart[1];
2622        final PartInitException ex[] = new PartInitException[1];
2623        BusyIndicator.showWhile(window.getWorkbench().getDisplay(),
2624                new Runnable JavaDoc() {
2625            public void run() {
2626                try {
2627                    result[0] = busyOpenEditorFromDescriptor(input, (EditorDescriptor)editorDescriptor,
2628                            activate, editorState);
2629                } catch (PartInitException e) {
2630                    ex[0] = e;
2631                }
2632            }
2633        });
2634        if (ex[0] != null) {
2635            throw ex[0];
2636        }
2637        return result[0];
2638    }
2639    
2640    /**
2641     * @see #openEditor(IEditorInput, String, boolean, int)
2642     */

2643    private IEditorPart busyOpenEditor(IEditorInput input, String JavaDoc editorID,
2644            boolean activate, int matchFlags, IMemento editorState) throws PartInitException {
2645
2646        final Workbench workbench = (Workbench) getWorkbenchWindow()
2647                .getWorkbench();
2648        workbench.largeUpdateStart();
2649
2650        try {
2651            return busyOpenEditorBatched(input, editorID, activate, matchFlags, editorState);
2652
2653        } finally {
2654            workbench.largeUpdateEnd();
2655        }
2656    }
2657
2658    /*
2659     * Added to fix Bug 178235 [EditorMgmt] DBCS 3.3 - Cannot open file with external program.
2660     * See openEditorFromDescriptor().
2661     */

2662    private IEditorPart busyOpenEditorFromDescriptor(IEditorInput input, EditorDescriptor editorDescriptor,
2663            boolean activate, IMemento editorState) throws PartInitException {
2664        
2665        final Workbench workbench = (Workbench) getWorkbenchWindow()
2666        .getWorkbench();
2667        workbench.largeUpdateStart();
2668        
2669        try {
2670            return busyOpenEditorFromDescriptorBatched(input, editorDescriptor, activate, editorState);
2671            
2672        } finally {
2673            workbench.largeUpdateEnd();
2674        }
2675    }
2676    
2677    /**
2678     * Do not call this method. Use <code>busyOpenEditor</code>.
2679     *
2680     * @see IWorkbenchPage#openEditor(IEditorInput, String, boolean)
2681     */

2682    private IEditorPart busyOpenEditorBatched(IEditorInput input,
2683            String JavaDoc editorID, boolean activate, int matchFlags, IMemento editorState) throws PartInitException {
2684
2685        // If an editor already exists for the input, use it.
2686
IEditorPart editor = null;
2687        // Reuse an existing open editor, unless we are in "new editor tab management" mode
2688
editor = getEditorManager().findEditor(editorID, input, ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).getReuseEditorMatchFlags(matchFlags));
2689        if (editor != null) {
2690            if (IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID.equals(editorID)) {
2691                if (editor.isDirty()) {
2692                    MessageDialog dialog = new MessageDialog(
2693                            getWorkbenchWindow().getShell(),
2694                            WorkbenchMessages.Save,
2695                            null, // accept the default window icon
2696
NLS.bind(WorkbenchMessages.WorkbenchPage_editorAlreadyOpenedMsg, input.getName()),
2697                            MessageDialog.QUESTION, new String JavaDoc[] {
2698                                    IDialogConstants.YES_LABEL,
2699                                    IDialogConstants.NO_LABEL,
2700                                    IDialogConstants.CANCEL_LABEL }, 0);
2701                    int saveFile = dialog.open();
2702                    if (saveFile == 0) {
2703                        try {
2704                            final IEditorPart editorToSave = editor;
2705                            getWorkbenchWindow().run(false, false,
2706                                    new IRunnableWithProgress() {
2707                                        public void run(IProgressMonitor monitor)
2708                                                throws InvocationTargetException JavaDoc,
2709                                                InterruptedException JavaDoc {
2710                                            editorToSave.doSave(monitor);
2711                                        }
2712                                    });
2713                        } catch (InvocationTargetException JavaDoc e) {
2714                            throw (RuntimeException JavaDoc) e.getTargetException();
2715                        } catch (InterruptedException JavaDoc e) {
2716                            return null;
2717                        }
2718                    } else if (saveFile == 2) {
2719                        return null;
2720                    }
2721                }
2722            } else {
2723                // do the IShowEditorInput notification before showing the editor
2724
// to reduce flicker
2725
if (editor instanceof IShowEditorInput) {
2726                    ((IShowEditorInput) editor).showEditorInput(input);
2727                }
2728                showEditor(activate, editor);
2729                return editor;
2730            }
2731        }
2732
2733
2734        // Otherwise, create a new one. This may cause the new editor to
2735
// become the visible (i.e top) editor.
2736
IEditorReference ref = null;
2737        ref = getEditorManager().openEditor(editorID, input, true, editorState);
2738        if (ref != null) {
2739            editor = ref.getEditor(true);
2740        }
2741
2742        if (editor != null) {
2743            setEditorAreaVisible(true);
2744            if (activate) {
2745                if (editor instanceof MultiEditor) {
2746                    activate(((MultiEditor) editor).getActiveEditor());
2747                } else {
2748                    activate(editor);
2749                }
2750            } else {
2751                bringToTop(editor);
2752            }
2753            window.firePerspectiveChanged(this, getPerspective(), ref,
2754                    CHANGE_EDITOR_OPEN);
2755            window.firePerspectiveChanged(this, getPerspective(),
2756                    CHANGE_EDITOR_OPEN);
2757        }
2758
2759        return editor;
2760    }
2761    
2762    /*
2763     * Added to fix Bug 178235 [EditorMgmt] DBCS 3.3 - Cannot open file with external program.
2764     * See openEditorFromDescriptor().
2765     */

2766    private IEditorPart busyOpenEditorFromDescriptorBatched(IEditorInput input,
2767            EditorDescriptor editorDescriptor, boolean activate, IMemento editorState) throws PartInitException {
2768
2769        IEditorPart editor = null;
2770        // Create a new one. This may cause the new editor to
2771
// become the visible (i.e top) editor.
2772
IEditorReference ref = null;
2773        ref = getEditorManager().openEditorFromDescriptor(editorDescriptor, input, editorState);
2774        if (ref != null) {
2775            editor = ref.getEditor(true);
2776        }
2777
2778        if (editor != null) {
2779            setEditorAreaVisible(true);
2780            if (activate) {
2781                if (editor instanceof MultiEditor) {
2782                    activate(((MultiEditor) editor).getActiveEditor());
2783                } else {
2784                    activate(editor);
2785                }
2786            } else {
2787                bringToTop(editor);
2788            }
2789            window.firePerspectiveChanged(this, getPerspective(), ref,
2790                    CHANGE_EDITOR_OPEN);
2791            window.firePerspectiveChanged(this, getPerspective(),
2792                    CHANGE_EDITOR_OPEN);
2793        }
2794
2795        return editor;
2796    }
2797    
2798    public void openEmptyTab() {
2799        IEditorPart editor = null;
2800        EditorReference ref = null;
2801        ref = (EditorReference) getEditorManager().openEmptyTab();
2802        if (ref != null) {
2803            editor = ref.getEmptyEditor((EditorDescriptor) ((EditorRegistry) WorkbenchPlugin
2804                    .getDefault().getEditorRegistry())
2805                    .findEditor(EditorRegistry.EMPTY_EDITOR_ID));
2806        }
2807
2808        if (editor != null) {
2809            setEditorAreaVisible(true);
2810            activate(editor);
2811            window.firePerspectiveChanged(this, getPerspective(), ref,
2812                    CHANGE_EDITOR_OPEN);
2813            window.firePerspectiveChanged(this, getPerspective(),
2814                    CHANGE_EDITOR_OPEN);
2815        }
2816    }
2817
2818    private void showEditor(boolean activate, IEditorPart editor) {
2819        setEditorAreaVisible(true);
2820        if (activate) {
2821            zoomOutIfNecessary(editor);
2822            activate(editor);
2823        } else {
2824            bringToTop(editor);
2825        }
2826    }
2827
2828    /**
2829     * See IWorkbenchPage.
2830     */

2831    public boolean isEditorPinned(IEditorPart editor) {
2832        WorkbenchPartReference ref = (WorkbenchPartReference)getReference(editor);
2833        return ref != null && ref.isPinned();
2834    }
2835    
2836    /**
2837     * Returns whether changes to a part will affect zoom. There are a few
2838     * conditions for this .. - we are zoomed. - the part is contained in the
2839     * main window. - the part is not the zoom part - the part is not a fast
2840     * view - the part and the zoom part are not in the same editor workbook
2841     */

2842    private boolean partChangeAffectsZoom(IWorkbenchPartReference ref) {
2843        PartPane pane = ((WorkbenchPartReference) ref).getPane();
2844        if (pane instanceof MultiEditorInnerPane) {
2845            pane = ((MultiEditorInnerPane) pane).getParentPane();
2846        }
2847        return getActivePerspective().getPresentation().partChangeAffectsZoom(
2848                pane);
2849    }
2850
2851    /**
2852     * Removes a fast view.
2853     */

2854    public void removeFastView(IViewReference ref) {
2855        Perspective persp = getActivePerspective();
2856        if (persp == null) {
2857            return;
2858        }
2859
2860        // Do real work.
2861
persp.removeFastView(ref);
2862
2863        // Notify listeners.
2864
window.firePerspectiveChanged(this, getPerspective(), ref,
2865                CHANGE_FAST_VIEW_REMOVE);
2866        window.firePerspectiveChanged(this, getPerspective(),
2867                CHANGE_FAST_VIEW_REMOVE);
2868    }
2869
2870    /**
2871     * Removes an IPartListener from the part service.
2872     */

2873    public void removePartListener(IPartListener l) {
2874        partList.getPartService().removePartListener(l);
2875    }
2876
2877    /**
2878     * Removes an IPartListener from the part service.
2879     */

2880    public void removePartListener(IPartListener2 l) {
2881        partList.getPartService().removePartListener(l);
2882    }
2883
2884    /**
2885     * Implements IWorkbenchPage
2886     *
2887     * @see org.eclipse.ui.IWorkbenchPage#removePropertyChangeListener(IPropertyChangeListener)
2888     * @since 2.0
2889     * @deprecated individual views should store a working set if needed and
2890     * register a property change listener directly with the
2891     * working set manager to receive notification when the view
2892     * working set is removed.
2893     */

2894    public void removePropertyChangeListener(IPropertyChangeListener listener) {
2895        propertyChangeListeners.remove(listener);
2896    }
2897
2898    /*
2899     * (non-Javadoc) Method declared on ISelectionListener.
2900     */

2901    public void removeSelectionListener(ISelectionListener listener) {
2902        selectionService.removeSelectionListener(listener);
2903    }
2904
2905    /*
2906     * (non-Javadoc) Method declared on ISelectionListener.
2907     */

2908    public void removeSelectionListener(String JavaDoc partId,
2909            ISelectionListener listener) {
2910        selectionService.removeSelectionListener(partId, listener);
2911    }
2912
2913    /*
2914     * (non-Javadoc) Method declared on ISelectionListener.
2915     */

2916    public void removePostSelectionListener(ISelectionListener listener) {
2917        selectionService.removePostSelectionListener(listener);
2918    }
2919
2920    /*
2921     * (non-Javadoc) Method declared on ISelectionListener.
2922     */

2923    public void removePostSelectionListener(String JavaDoc partId,
2924            ISelectionListener listener) {
2925        selectionService.removePostSelectionListener(partId, listener);
2926    }
2927
2928    /**
2929     * This method is called when a part is activated by clicking within it. In
2930     * response, the part, the pane, and all of its actions will be activated.
2931     *
2932     * In the current design this method is invoked by the part pane when the
2933     * pane, the part, or any children gain focus.
2934     */

2935    public void requestActivation(IWorkbenchPart part) {
2936        // Sanity check.
2937
if (!certifyPart(part)) {
2938            return;
2939        }
2940
2941        if (part instanceof MultiEditor) {
2942            part = ((MultiEditor) part).getActiveEditor();
2943        }
2944
2945        // Real work.
2946
setActivePart(part);
2947    }
2948
2949    /**
2950     * Resets the layout for the perspective. The active part in the old layout
2951     * is activated in the new layout for consistent user context.
2952     */

2953    public void resetPerspective() {
2954        // Run op in busy cursor.
2955
// Use set redraw to eliminate the "flash" that can occur in the
2956
// coolbar as the perspective is reset.
2957
ICoolBarManager2 mgr = (ICoolBarManager2) window.getCoolBarManager2();
2958        try {
2959            mgr.getControl2().setRedraw(false);
2960            BusyIndicator.showWhile(null, new Runnable JavaDoc() {
2961                public void run() {
2962                    busyResetPerspective();
2963                }
2964            });
2965        } finally {
2966            mgr.getControl2().setRedraw(true);
2967        }
2968    }
2969
2970    /**
2971     * Restore this page from the memento and ensure that the active
2972     * perspective is equals the active descriptor otherwise create a new
2973     * perspective for that descriptor. If activeDescriptor is null active the
2974     * old perspective.
2975     */

2976    public IStatus restoreState(IMemento memento,
2977            final IPerspectiveDescriptor activeDescriptor) {
2978        StartupThreading.runWithoutExceptions(new StartupRunnable() {
2979
2980            public void runWithException() throws Throwable JavaDoc {
2981                deferUpdates(true);
2982            }});
2983        
2984        try {
2985            // Restore working set
2986
String JavaDoc pageName = memento.getString(IWorkbenchConstants.TAG_LABEL);
2987            
2988            String JavaDoc label = null; // debugging only
2989
if (UIStats.isDebugging(UIStats.RESTORE_WORKBENCH)) {
2990                label = pageName == null ? "" : "::" + pageName; //$NON-NLS-1$ //$NON-NLS-2$
2991
}
2992    
2993            try {
2994                UIStats.start(UIStats.RESTORE_WORKBENCH, "WorkbenchPage" + label); //$NON-NLS-1$
2995
if (pageName == null) {
2996                    pageName = ""; //$NON-NLS-1$
2997
}
2998                final MultiStatus result = new MultiStatus(
2999                        PlatformUI.PLUGIN_ID,
3000                        IStatus.OK,
3001                        NLS.bind(WorkbenchMessages.WorkbenchPage_unableToRestorePerspective, pageName ),
3002                        null);
3003    
3004                String JavaDoc workingSetName = memento
3005                        .getString(IWorkbenchConstants.TAG_WORKING_SET);
3006                if (workingSetName != null) {
3007                    AbstractWorkingSetManager workingSetManager = (AbstractWorkingSetManager) getWorkbenchWindow()
3008                            .getWorkbench().getWorkingSetManager();
3009                    setWorkingSet(workingSetManager.getWorkingSet(workingSetName));
3010                }
3011                
3012                IMemento workingSetMem = memento
3013                        .getChild(IWorkbenchConstants.TAG_WORKING_SETS);
3014                if (workingSetMem != null) {
3015                    IMemento[] workingSetChildren = workingSetMem
3016                            .getChildren(IWorkbenchConstants.TAG_WORKING_SET);
3017                    List JavaDoc workingSetList = new ArrayList JavaDoc(
3018                            workingSetChildren.length);
3019                    for (int i = 0; i < workingSetChildren.length; i++) {
3020                        IWorkingSet set = getWorkbenchWindow().getWorkbench()
3021                                .getWorkingSetManager().getWorkingSet(
3022                                        workingSetChildren[i].getID());
3023                        if (set != null) {
3024                            workingSetList.add(set);
3025                        }
3026                    }
3027
3028                    workingSets = (IWorkingSet[]) workingSetList
3029                            .toArray(new IWorkingSet[workingSetList.size()]);
3030                }
3031                
3032                aggregateWorkingSetId = memento.getString(ATT_AGGREGATE_WORKING_SET_ID);
3033                
3034                IWorkingSet setWithId = window.getWorkbench().getWorkingSetManager().getWorkingSet(aggregateWorkingSetId);
3035                
3036                // check to see if the set has already been made and assign it if it has
3037
if (setWithId instanceof AggregateWorkingSet) {
3038                    aggregateWorkingSet = (AggregateWorkingSet) setWithId;
3039                }
3040                // Restore editor manager.
3041
IMemento childMem = memento
3042                        .getChild(IWorkbenchConstants.TAG_EDITORS);
3043                result.merge(getEditorManager().restoreState(childMem));
3044    
3045                childMem = memento.getChild(IWorkbenchConstants.TAG_VIEWS);
3046                if (childMem != null) {
3047                    result.merge(getViewFactory().restoreState(childMem));
3048                }
3049    
3050                // Get persp block.
3051
childMem = memento.getChild(IWorkbenchConstants.TAG_PERSPECTIVES);
3052                String JavaDoc activePartID = childMem
3053                        .getString(IWorkbenchConstants.TAG_ACTIVE_PART);
3054                String JavaDoc activePartSecondaryID = null;
3055                if (activePartID != null) {
3056                    activePartSecondaryID = ViewFactory
3057                            .extractSecondaryId(activePartID);
3058                    if (activePartSecondaryID != null) {
3059                        activePartID = ViewFactory.extractPrimaryId(activePartID);
3060                    }
3061                }
3062                final String JavaDoc activePerspectiveID = childMem
3063                        .getString(IWorkbenchConstants.TAG_ACTIVE_PERSPECTIVE);
3064    
3065                // Restore perspectives.
3066
final IMemento perspMems[] = childMem
3067                        .getChildren(IWorkbenchConstants.TAG_PERSPECTIVE);
3068                final Perspective activePerspectiveArray [] = new Perspective[1];
3069                
3070                for (int i = 0; i < perspMems.length; i++) {
3071                    
3072                        final IMemento current = perspMems[i];
3073                    StartupThreading
3074                            .runWithoutExceptions(new StartupRunnable() {
3075
3076                                public void runWithException() throws Throwable JavaDoc {
3077                                    Perspective persp = new Perspective(null,
3078                                            WorkbenchPage.this);
3079                                    result.merge(persp.restoreState(current));
3080                                    final IPerspectiveDescriptor desc = persp
3081                                            .getDesc();
3082                                    if (desc.equals(activeDescriptor)) {
3083                                        activePerspectiveArray[0] = persp;
3084                                    } else if ((activePerspectiveArray[0] == null)
3085                                            && desc.getId().equals(
3086                                                    activePerspectiveID)) {
3087                                        activePerspectiveArray[0] = persp;
3088                                    }
3089                                    perspList.add(persp);
3090                                    window.firePerspectiveOpened(
3091                                            WorkbenchPage.this, desc);
3092                                }
3093                            });
3094                }
3095                Perspective activePerspective = activePerspectiveArray[0];
3096                boolean restoreActivePerspective = false;
3097                if (activeDescriptor == null) {
3098                    restoreActivePerspective = true;
3099
3100                } else if (activePerspective != null
3101                        && activePerspective.getDesc().equals(activeDescriptor)) {
3102                    restoreActivePerspective = true;
3103                } else {
3104                    restoreActivePerspective = false;
3105                    activePerspective = createPerspective((PerspectiveDescriptor) activeDescriptor, true);
3106                    if (activePerspective == null) {
3107                        result
3108                                .merge(new Status(
3109                                        IStatus.ERROR,
3110                                        PlatformUI.PLUGIN_ID,
3111                                        0,
3112                                        NLS.bind(WorkbenchMessages.Workbench_showPerspectiveError, activeDescriptor.getId() ),
3113                                        null));
3114                    }
3115                }
3116    
3117                perspList.setActive(activePerspective);
3118    
3119                // Make sure we have a valid perspective to work with,
3120
// otherwise return.
3121
activePerspective = perspList.getActive();
3122                if (activePerspective == null) {
3123                    activePerspective = perspList.getNextActive();
3124                    perspList.setActive(activePerspective);
3125                }
3126                if (activePerspective != null && restoreActivePerspective) {
3127                    result.merge(activePerspective.restoreState());
3128                }
3129    
3130                if (activePerspective != null) {
3131                    final Perspective myPerspective = activePerspective;
3132                    final String JavaDoc myActivePartId = activePartID, mySecondaryId = activePartSecondaryID;
3133                    StartupThreading.runWithoutExceptions(new StartupRunnable() {
3134
3135                        public void runWithException() throws Throwable JavaDoc {
3136                            window.firePerspectiveActivated(WorkbenchPage.this, myPerspective
3137                                    .getDesc());
3138            
3139                            // Restore active part.
3140
if (myActivePartId != null) {
3141                                IViewReference ref = myPerspective.findView(
3142                                        myActivePartId, mySecondaryId);
3143                                
3144                                if (ref != null) {
3145                                    activationList.setActive(ref);
3146                                }
3147                            }
3148                        }});
3149                    
3150                }
3151    
3152                childMem = memento
3153                        .getChild(IWorkbenchConstants.TAG_NAVIGATION_HISTORY);
3154                if (childMem != null) {
3155                    navigationHistory.restoreState(childMem);
3156                } else if (getActiveEditor() != null) {
3157                    navigationHistory.markEditor(getActiveEditor());
3158                }
3159                
3160                // restore sticky view state
3161
stickyViewMan.restore(memento);
3162                    
3163                return result;
3164            } finally {
3165                String JavaDoc blame = activeDescriptor == null ? pageName : activeDescriptor.getId();
3166                UIStats.end(UIStats.RESTORE_WORKBENCH, blame, "WorkbenchPage" + label); //$NON-NLS-1$
3167
}
3168        } finally {
3169            StartupThreading.runWithoutExceptions(new StartupRunnable() {
3170
3171                public void runWithException() throws Throwable JavaDoc {
3172                    deferUpdates(false);
3173                }
3174            });
3175        }
3176    }
3177
3178    /**
3179     * See IWorkbenchPage
3180     */

3181    public boolean saveAllEditors(boolean confirm) {
3182        return saveAllEditors(confirm, false);
3183    }
3184
3185    /**
3186     * @param confirm
3187     * @param addNonPartSources true if saveables from non-part sources should be saved too
3188     * @return false if the user cancelled
3189     *
3190     */

3191    public boolean saveAllEditors(boolean confirm, boolean addNonPartSources) {
3192        return getEditorManager().saveAll(confirm, false, addNonPartSources);
3193    }
3194
3195    /*
3196     * Saves the workbench part.
3197     */

3198    protected boolean savePart(ISaveablePart saveable, IWorkbenchPart part,
3199            boolean confirm) {
3200        // Do not certify part do allow editors inside a multipageeditor to
3201
// call this.
3202
return getEditorManager().savePart(saveable, part, confirm);
3203    }
3204
3205    /**
3206     * Saves an editors in the workbench. If <code>confirm</code> is <code>true</code>
3207     * the user is prompted to confirm the command.
3208     *
3209     * @param confirm
3210     * if user confirmation should be sought
3211     * @return <code>true</code> if the command succeeded, or <code>false</code>
3212     * if the user cancels the command
3213     */

3214    public boolean saveEditor(IEditorPart editor, boolean confirm) {
3215        return savePart(editor, editor, confirm);
3216    }
3217
3218    /**
3219     * Saves the current perspective.
3220     */

3221    public void savePerspective() {
3222        Perspective persp = getActivePerspective();
3223        if (persp == null) {
3224            return;
3225        }
3226
3227        // Always unzoom.
3228
if (isZoomed()) {
3229            zoomOut();
3230        }
3231
3232        persp.saveDesc();
3233    }
3234
3235    /**
3236     * Saves the perspective.
3237     */

3238    public void savePerspectiveAs(IPerspectiveDescriptor newDesc) {
3239        Perspective persp = getActivePerspective();
3240        if (persp == null) {
3241            return;
3242        }
3243        IPerspectiveDescriptor oldDesc = persp.getDesc();
3244
3245        // Always unzoom.
3246
if (isZoomed()) {
3247            zoomOut();
3248        }
3249
3250        persp.saveDescAs(newDesc);
3251        window.firePerspectiveSavedAs(this, oldDesc, newDesc);
3252    }
3253
3254    /**
3255     * Save the state of the page.
3256     */

3257    public IStatus saveState(IMemento memento) {
3258        // We must unzoom to get correct layout.
3259
if (isZoomed()) {
3260            zoomOut();
3261        }
3262
3263        MultiStatus result = new MultiStatus(
3264                PlatformUI.PLUGIN_ID,
3265                IStatus.OK,
3266                NLS.bind(WorkbenchMessages.WorkbenchPage_unableToSavePerspective, getLabel()),
3267                null);
3268
3269        // Save editor manager.
3270
IMemento childMem = memento
3271                .createChild(IWorkbenchConstants.TAG_EDITORS);
3272        result.merge(editorMgr.saveState(childMem));
3273
3274        childMem = memento.createChild(IWorkbenchConstants.TAG_VIEWS);
3275        result.merge(getViewFactory().saveState(childMem));
3276
3277        // Create persp block.
3278
childMem = memento.createChild(IWorkbenchConstants.TAG_PERSPECTIVES);
3279        if (getPerspective() != null) {
3280            childMem.putString(IWorkbenchConstants.TAG_ACTIVE_PERSPECTIVE,
3281                    getPerspective().getId());
3282        }
3283        if (getActivePart() != null) {
3284            if (getActivePart() instanceof IViewPart) {
3285                IViewReference ref = (IViewReference) getReference(getActivePart());
3286                if (ref != null) {
3287                    childMem.putString(IWorkbenchConstants.TAG_ACTIVE_PART,
3288                            ViewFactory.getKey(ref));
3289                }
3290            } else {
3291                childMem.putString(IWorkbenchConstants.TAG_ACTIVE_PART,
3292                        getActivePart().getSite().getId());
3293            }
3294        }
3295
3296        // Save each perspective in opened order
3297
Iterator JavaDoc itr = perspList.iterator();
3298        while (itr.hasNext()) {
3299            Perspective persp = (Perspective) itr.next();
3300            IMemento gChildMem = childMem
3301                    .createChild(IWorkbenchConstants.TAG_PERSPECTIVE);
3302            result.merge(persp.saveState(gChildMem));
3303        }
3304        // Save working set if set
3305
if (workingSet != null) {
3306            memento.putString(IWorkbenchConstants.TAG_WORKING_SET, workingSet
3307                    .getName());
3308        }
3309        
3310        IMemento workingSetMem = memento
3311                .createChild(IWorkbenchConstants.TAG_WORKING_SETS);
3312        for (int i = 0; i < workingSets.length; i++) {
3313            workingSetMem.createChild(IWorkbenchConstants.TAG_WORKING_SET,
3314                    workingSets[i].getName());
3315        }
3316        
3317        if (aggregateWorkingSetId != null) {
3318            memento.putString(ATT_AGGREGATE_WORKING_SET_ID, aggregateWorkingSetId);
3319        }
3320
3321        navigationHistory.saveState(memento
3322                .createChild(IWorkbenchConstants.TAG_NAVIGATION_HISTORY));
3323        
3324        
3325        // save the sticky activation state
3326
stickyViewMan.save(memento);
3327        
3328        return result;
3329    }
3330    
3331    private String JavaDoc getId(IWorkbenchPart part) {
3332        return getId(getReference(part));
3333    }
3334    
3335    private String JavaDoc getId(IWorkbenchPartReference ref) {
3336        if (ref == null) {
3337            return "null"; //$NON-NLS-1$
3338
} return ref.getId();
3339    }
3340
3341    /**
3342     * Sets the active part.
3343     */

3344    private void setActivePart(IWorkbenchPart newPart) {
3345        // Optimize it.
3346
if (getActivePart() == newPart) {
3347            return;
3348        }
3349        
3350        if (partBeingActivated != null) {
3351            if (partBeingActivated.getPart(false) != newPart) {
3352                WorkbenchPlugin.log(new RuntimeException JavaDoc(NLS.bind(
3353                        "WARNING: Prevented recursive attempt to activate part {0} while still in the middle of activating part {1}", //$NON-NLS-1$
3354
getId(newPart), getId(partBeingActivated))));
3355            }
3356            return;
3357        }
3358
3359        //No need to change the history if the active editor is becoming the
3360
// active part
3361
String JavaDoc label = null; // debugging only
3362
if (UIStats.isDebugging(UIStats.ACTIVATE_PART)) {
3363            label = newPart != null ? newPart.getTitle() : "none"; //$NON-NLS-1$
3364
}
3365        try {
3366            IWorkbenchPartReference partref = getReference(newPart);
3367            IWorkbenchPartReference realPartRef = null;
3368            if (newPart != null) {
3369                IWorkbenchPartSite site = newPart.getSite();
3370                if (site instanceof PartSite) {
3371                    realPartRef = ((PartSite) site).getPane()
3372                            .getPartReference();
3373                }
3374            }
3375
3376            partBeingActivated = realPartRef;
3377            
3378            UIStats.start(UIStats.ACTIVATE_PART, label);
3379            // Notify perspective. It may deactivate fast view.
3380
Perspective persp = getActivePerspective();
3381            if (persp != null) {
3382                persp.partActivated(newPart);
3383            }
3384
3385            // Deactivate old part
3386
IWorkbenchPart oldPart = getActivePart();
3387            if (oldPart != null) {
3388                deactivatePart(oldPart);
3389            }
3390            
3391            // Set active part.
3392
if (newPart != null) {
3393                activationList.setActive(newPart);
3394                if (newPart instanceof IEditorPart) {
3395                    makeActiveEditor((IEditorReference)realPartRef);
3396                }
3397            }
3398            activatePart(newPart);
3399            
3400            actionSwitcher.updateActivePart(newPart);
3401            
3402            partList.setActivePart(partref);
3403        } finally {
3404            partBeingActivated = null;
3405            Object JavaDoc blame = newPart == null ? (Object JavaDoc)this : newPart;
3406            UIStats.end(UIStats.ACTIVATE_PART, blame, label);
3407        }
3408    }
3409
3410    /**
3411     * See IWorkbenchPage.
3412     */

3413    public void setEditorAreaVisible(boolean showEditorArea) {
3414        Perspective persp = getActivePerspective();
3415        if (persp == null) {
3416            return;
3417        }
3418        if (showEditorArea == persp.isEditorAreaVisible()) {
3419            return;
3420        }
3421        // If parts change always update zoom.
3422
if (isZoomed()) {
3423            zoomOut();
3424        }
3425        // Update editor area visibility.
3426
if (showEditorArea) {
3427            persp.showEditorArea();
3428            window.firePerspectiveChanged(this, getPerspective(),
3429                    CHANGE_EDITOR_AREA_SHOW);
3430        } else {
3431            persp.hideEditorArea();
3432            updateActivePart();
3433            window.firePerspectiveChanged(this, getPerspective(),
3434                    CHANGE_EDITOR_AREA_HIDE);
3435        }
3436    }
3437
3438    /**
3439     * Sets the layout of the page. Assumes the new perspective is not null.
3440     * Keeps the active part if possible. Updates the window menubar and
3441     * toolbar if necessary.
3442     */

3443    private void setPerspective(Perspective newPersp) {
3444        // Don't do anything if already active layout
3445
Perspective oldPersp = getActivePerspective();
3446        if (oldPersp == newPersp) {
3447            return;
3448        }
3449
3450        window.largeUpdateStart();
3451        try {
3452            if (oldPersp != null) {
3453                // fire the pre-deactivate
3454
window.firePerspectivePreDeactivate(this, oldPersp.getDesc());
3455            }
3456            
3457            if (newPersp != null) {
3458                IStatus status = newPersp.restoreState();
3459                if (status.getSeverity() != IStatus.OK) {
3460                    String JavaDoc title = WorkbenchMessages.WorkbenchPage_problemRestoringTitle;
3461                    String JavaDoc msg = WorkbenchMessages.WorkbenchPage_errorReadingState;
3462                    ErrorDialog.openError(getWorkbenchWindow().getShell(), title,
3463                            msg, status);
3464                }
3465            }
3466    
3467    
3468            // Deactivate the old layout
3469
if (oldPersp != null) {
3470                oldPersp.onDeactivate();
3471
3472                // Notify listeners of deactivation
3473
window.firePerspectiveDeactivated(this, oldPersp.getDesc());
3474            }
3475    
3476            // Activate the new layout
3477
perspList.setActive(newPersp);
3478            if (newPersp != null) {
3479                newPersp.onActivate();
3480    
3481                // Notify listeners of activation
3482
window.firePerspectiveActivated(this, newPersp.getDesc());
3483            }
3484    
3485            updateVisibility(oldPersp, newPersp);
3486    
3487            // Update the window
3488
window.updateActionSets();
3489
3490            // Update sticky views
3491
stickyViewMan.update(oldPersp, newPersp);
3492            
3493        } finally {
3494            window.largeUpdateEnd();
3495            if (newPersp == null) {
3496                return;
3497            }
3498            IPerspectiveDescriptor desc = newPersp.getDesc();
3499            if (desc == null) {
3500                return;
3501            }
3502            if (dirtyPerspectives.remove(desc.getId())) {
3503                suggestReset();
3504            }
3505        }
3506    }
3507
3508    void perspectiveActionSetChanged(Perspective perspective, IActionSetDescriptor descriptor, int changeType) {
3509        if (perspective == getActivePerspective()) {
3510            actionSets.change(descriptor, changeType);
3511        }
3512    }
3513    
3514    /*
3515     * Update visibility state of all views.
3516     */

3517    private void updateVisibility(Perspective oldPersp, Perspective newPersp) {
3518        
3519        // Flag all parts in the old perspective
3520
IWorkbenchPartReference[] oldRefs = new IWorkbenchPartReference[0];
3521        if (oldPersp != null) {
3522            oldRefs = oldPersp.getViewReferences();
3523            for (int i = 0; i < oldRefs.length; i++) {
3524                PartPane pane = ((WorkbenchPartReference) oldRefs[i]).getPane();
3525                pane.setInLayout(false);
3526            }
3527        }
3528        
3529        PerspectiveHelper pres = null;
3530        // Make parts in the new perspective visible
3531
if (newPersp != null) {
3532            pres = newPersp.getPresentation();
3533            IWorkbenchPartReference[] newRefs = newPersp.getViewReferences();
3534            for (int i = 0; i < newRefs.length; i++) {
3535                WorkbenchPartReference ref = (WorkbenchPartReference)newRefs[i];
3536                PartPane pane = ref.getPane();
3537                if (pres.isPartVisible(ref)) {
3538                    activationList.bringToTop(ref);
3539                }
3540
3541                pane.setInLayout(true);
3542            }
3543        }
3544
3545        updateActivePart();
3546
3547        // Hide any parts in the old perspective that are no longer visible
3548
for (int i = 0; i < oldRefs.length; i++) {
3549            WorkbenchPartReference ref = (WorkbenchPartReference)oldRefs[i];
3550               
3551            PartPane pane = ref.getPane();
3552            if (pres == null || !pres.isPartVisible(ref)) {
3553                pane.setVisible(false);
3554            }
3555        }
3556    }
3557
3558    /**
3559     * Sets the perspective.
3560     *
3561     * @param desc
3562     * identifies the new perspective.
3563     */

3564    public void setPerspective(final IPerspectiveDescriptor desc) {
3565        if (Util.equals(getPerspective(), desc)) {
3566            return;
3567        }
3568        // Going from multiple to single rows can make the coolbar
3569
// and its adjacent views appear jumpy as perspectives are
3570
// switched. Turn off redraw to help with this.
3571
ICoolBarManager2 mgr = (ICoolBarManager2) window.getCoolBarManager2();
3572        try {
3573            mgr.getControl2().setRedraw(false);
3574            getClientComposite().setRedraw(false);
3575            // Run op in busy cursor.
3576
BusyIndicator.showWhile(null, new Runnable JavaDoc() {
3577                public void run() {
3578                    busySetPerspective(desc);
3579                }
3580            });
3581        } finally {
3582            getClientComposite().setRedraw(true);
3583            mgr.getControl2().setRedraw(true);
3584            IWorkbenchPart part = getActivePart();
3585            if (part != null) {
3586                part.setFocus();
3587            }
3588        }
3589    }
3590    
3591    /**
3592     * Allow access to the part service for this page ... used internally to
3593     * propogate certain types of events to the page part listeners.
3594     * @return the part service for this page.
3595     */

3596    public PartService getPartService() {
3597        return (PartService)partList.getPartService();
3598    }
3599
3600    /**
3601     * Restore the toolbar layout for the active perspective.
3602     */

3603    protected void resetToolBarLayout() {
3604        ICoolBarManager2 mgr = (ICoolBarManager2) window.getCoolBarManager2();
3605        mgr.resetItemOrder();
3606    }
3607
3608    /**
3609     * Sets the active working set for the workbench page. Notifies property
3610     * change listener about the change.
3611     *
3612     * @param newWorkingSet
3613     * the active working set for the page. May be null.
3614     * @since 2.0
3615     * @deprecated individual views should store a working set if needed
3616     */

3617    public void setWorkingSet(IWorkingSet newWorkingSet) {
3618        IWorkingSet oldWorkingSet = workingSet;
3619
3620        workingSet = newWorkingSet;
3621        if (oldWorkingSet != newWorkingSet) {
3622            firePropertyChange(CHANGE_WORKING_SET_REPLACE, oldWorkingSet,
3623                    newWorkingSet);
3624        }
3625        if (newWorkingSet != null) {
3626            WorkbenchPlugin.getDefault().getWorkingSetManager()
3627                    .addPropertyChangeListener(workingSetPropertyChangeListener);
3628        } else {
3629            WorkbenchPlugin.getDefault().getWorkingSetManager()
3630                    .removePropertyChangeListener(workingSetPropertyChangeListener);
3631        }
3632    }
3633
3634    /**
3635     * @see IWorkbenchPage
3636     */

3637    public void showActionSet(String JavaDoc actionSetID) {
3638        Perspective persp = getActivePerspective();
3639        if (persp != null) {
3640            ActionSetRegistry reg = WorkbenchPlugin.getDefault()
3641                 .getActionSetRegistry();
3642            
3643            IActionSetDescriptor desc = reg.findActionSet(actionSetID);
3644            if (desc != null) {
3645                persp.addActionSet(desc);
3646                window.updateActionSets();
3647                window.firePerspectiveChanged(this, getPerspective(),
3648                        CHANGE_ACTION_SET_SHOW);
3649            }
3650        }
3651    }
3652
3653    /**
3654     * See IWorkbenchPage.
3655     */

3656    public IViewPart showView(String JavaDoc viewID) throws PartInitException {
3657        return showView(viewID, null, VIEW_ACTIVATE);
3658    }
3659
3660    /*
3661     * (non-Javadoc)
3662     *
3663     * @see org.eclipse.ui.IWorkbenchPage#showView(java.lang.String,
3664     * java.lang.String, int)
3665     */

3666    public IViewPart showView(final String JavaDoc viewID, final String JavaDoc secondaryID,
3667            final int mode) throws PartInitException {
3668
3669        if (secondaryID != null) {
3670            if (secondaryID.length() == 0
3671                    || secondaryID.indexOf(ViewFactory.ID_SEP) != -1) {
3672                throw new IllegalArgumentException JavaDoc(WorkbenchMessages.WorkbenchPage_IllegalSecondaryId);
3673            }
3674        }
3675        if (!certifyMode(mode)) {
3676            throw new IllegalArgumentException JavaDoc(WorkbenchMessages.WorkbenchPage_IllegalViewMode);
3677        }
3678
3679        // Run op in busy cursor.
3680
final Object JavaDoc[] result = new Object JavaDoc[1];
3681        BusyIndicator.showWhile(null, new Runnable JavaDoc() {
3682            public void run() {
3683                try {
3684                    result[0] = busyShowView(viewID, secondaryID, mode);
3685                } catch (PartInitException e) {
3686                    result[0] = e;
3687                }
3688            }
3689        });
3690        if (result[0] instanceof IViewPart) {
3691            return (IViewPart) result[0];
3692        } else if (result[0] instanceof PartInitException) {
3693            throw (PartInitException) result[0];
3694        } else {
3695            throw new PartInitException(WorkbenchMessages.WorkbenchPage_AbnormalWorkbenchCondition);
3696        }
3697    }
3698
3699    /**
3700     * @param mode the mode to test
3701     * @return whether the mode is recognized
3702     * @since 3.0
3703     */

3704    private boolean certifyMode(int mode) {
3705        switch (mode) {
3706        case VIEW_ACTIVATE:
3707        case VIEW_VISIBLE:
3708        case VIEW_CREATE:
3709            return true;
3710        default:
3711            return false;
3712        }
3713    }
3714
3715    /**
3716     * Hides the active fast view. Has no effect if there is no fast view active.
3717     */

3718    public void hideFastView() {
3719        Perspective persp = getActivePerspective();
3720        if (persp != null) {
3721            IViewReference ref = persp.getActiveFastView();
3722            if (ref != null) {
3723                toggleFastView(ref);
3724            }
3725        }
3726    }
3727
3728    /**
3729     * Toggles the visibility of a fast view. If the view is active it is
3730     * deactivated. Otherwise, it is activated.
3731     */

3732    public void toggleFastView(IViewReference ref) {
3733        Perspective persp = getActivePerspective();
3734        if (persp != null) {
3735            persp.toggleFastView(ref);
3736            // if the fast view has been deactivated
3737
if (ref != persp.getActiveFastView()) {
3738                IWorkbenchPart previouslyActive = activationList
3739                        .getPreviouslyActive();
3740                IEditorPart activeEditor = getActiveEditor();
3741                if (activeEditor != null
3742                        && previouslyActive instanceof IEditorPart) {
3743                    setActivePart(activeEditor);
3744                } else {
3745                    setActivePart(previouslyActive);
3746                }
3747            }
3748        }
3749    }
3750
3751    /**
3752     * Sets the state of the given part.
3753     *
3754     * @param ref part whose state should be modified (not null)
3755     * @param newState one of the IStackPresentationSite.STATE_* constants
3756     */

3757    public void setState(IWorkbenchPartReference ref, int newState) {
3758        Perspective persp = getActivePerspective();
3759        if (persp == null) {
3760            return;
3761        }
3762
3763        PartPane pane = ((WorkbenchPartReference) ref).getPane();
3764
3765        // If target part is detached fire the zoom event. Note this doesn't
3766
// actually cause any changes in size and is required to support
3767
// intro state changes. We may want to introduce the notion of a zoomed
3768
// (fullscreen) detached view at a later time.
3769
if (!pane.isDocked()) {
3770            pane.setZoomed(newState == IStackPresentationSite.STATE_MAXIMIZED);
3771            return;
3772        }
3773
3774        if (ref instanceof IViewReference
3775                && persp.isFastView((IViewReference) ref)) {
3776            persp.setFastViewState(newState);
3777            return;
3778        }
3779
3780        if (Perspective.useNewMinMax(persp)) {
3781            // set the container's state to the new one
3782
PartStack parent = ((PartStack)pane.getContainer());
3783            parent.setState(newState);
3784            return;
3785        }
3786        
3787        boolean wasZoomed = isZoomed();
3788        boolean isZoomed = newState == IStackPresentationSite.STATE_MAXIMIZED;
3789        
3790        // Update zoom status.
3791
if (wasZoomed && !isZoomed) {
3792            zoomOut();
3793        } else if (!wasZoomed && isZoomed) {
3794            persp.getPresentation().zoomIn(ref);
3795            activate(ref.getPart(true));
3796        }
3797        
3798        PartStack parent = ((PartStack)pane.getContainer());
3799        
3800        if (parent != null) {
3801            parent.setMinimized(newState == IStackPresentationSite.STATE_MINIMIZED);
3802        }
3803}
3804    
3805    /* (non-Javadoc)
3806     * @see org.eclipse.ui.IWorkbenchPage#setPartState(org.eclipse.ui.IWorkbenchPartReference, int)
3807     */

3808    public void setPartState(IWorkbenchPartReference ref, int state) {
3809        setState(ref, state);
3810    }
3811    
3812    /**
3813     * Returns the maximized/minimized/restored state of the given part reference
3814     *
3815     * @param ref part to query (not null)
3816     * @return one of the IStackPresentationSite.STATE_* constants
3817     */

3818    int getState(IWorkbenchPartReference ref) {
3819        Perspective persp = getActivePerspective();
3820        if (persp == null) {
3821            return IStackPresentationSite.STATE_RESTORED;
3822        }
3823
3824        PartPane pane = ((WorkbenchPartReference) ref).getPane();
3825        
3826        if (ref instanceof IViewReference
3827                && persp.isFastView((IViewReference) ref)) {
3828            return persp.getFastViewState();
3829        }
3830        
3831        PartStack parent = ((PartStack)pane.getContainer());
3832        
3833        if (parent != null) {
3834            return parent.getState();
3835        }
3836        
3837        return IStackPresentationSite.STATE_RESTORED;
3838    }
3839    
3840    /* (non-Javadoc)
3841     * @see org.eclipse.ui.IWorkbenchPage#getPartState(org.eclipse.ui.IWorkbenchPartReference)
3842     */

3843    public int getPartState(IWorkbenchPartReference ref) {
3844        return getState(ref);
3845    }
3846    
3847    /* (non-Javadoc)
3848     * @see org.eclipse.ui.IWorkbenchPage#toggleZoom(org.eclipse.ui.IWorkbenchPartReference)
3849     */

3850    public void toggleZoom(IWorkbenchPartReference ref) {
3851        int oldState = getState(ref);
3852        boolean shouldZoom = oldState != IStackPresentationSite.STATE_MAXIMIZED;
3853        int newState = shouldZoom ? IStackPresentationSite.STATE_MAXIMIZED : IStackPresentationSite.STATE_RESTORED;
3854        
3855        setState(ref, newState);
3856    }
3857
3858    /**
3859     * updateActionBars method comment.
3860     */

3861    public void updateActionBars() {
3862        window.updateActionBars();
3863    }
3864
3865    /**
3866     * Sets the tab list of this page's composite appropriately when a part is
3867     * activated.
3868     */

3869    private void updateTabList(IWorkbenchPart part) {
3870        PartSite site = (PartSite) part.getSite();
3871        PartPane pane = site.getPane();
3872        if (pane instanceof ViewPane) {
3873            ViewPane viewPane = (ViewPane) pane;
3874            Control[] tabList = viewPane.getTabList();
3875            if (!pane.isDocked()) {
3876                viewPane.getControl().getShell().setTabList(tabList);
3877            } else {
3878                getClientComposite().setTabList(tabList);
3879            }
3880        } else if (pane instanceof EditorPane) {
3881            EditorSashContainer ea = ((EditorPane) pane).getWorkbook()
3882                    .getEditorArea();
3883            ea.updateTabList();
3884            getClientComposite().setTabList(new Control[] { ea.getParent() });
3885        }
3886    }
3887
3888    
3889    /* (non-Javadoc)
3890     * @see org.eclipse.ui.IWorkbenchPage#zoomOut()
3891     */

3892    public void zoomOut() {
3893        Perspective persp = getActivePerspective();
3894        if (persp != null) {
3895            persp.getPresentation().zoomOut();
3896        }
3897    }
3898
3899    /**
3900     * Zooms out a zoomed in part if it is necessary to do so for the user to
3901     * view the IWorkbenchPart that is the argument. Otherwise, does nothing.
3902     *
3903     * @param part
3904     * the part to be made viewable
3905     */

3906    private void zoomOutIfNecessary(IWorkbenchPart part) {
3907        if (isZoomed() && partChangeAffectsZoom(((PartSite)part.getSite()).getPartReference())) {
3908            zoomOut();
3909        }
3910    }
3911
3912    /**
3913     *
3914     */

3915    public int getEditorReuseThreshold() {
3916        return ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).getEditorReuseThreshold();
3917    }
3918
3919    /**
3920     *
3921     */

3922    public void setEditorReuseThreshold(int openEditors) {
3923    }
3924
3925    /*
3926     * Returns the editors in activation order (oldest first).
3927     */

3928    public IEditorReference[] getSortedEditors() {
3929        return activationList.getEditors();
3930    }
3931
3932    /**
3933     * @see IWorkbenchPage#getOpenPerspectives()
3934     */

3935    public IPerspectiveDescriptor[] getOpenPerspectives() {
3936        Perspective opened[] = perspList.getOpenedPerspectives();
3937        IPerspectiveDescriptor[] result = new IPerspectiveDescriptor[opened.length];
3938        for (int i = 0; i < result.length; i++) {
3939            result[i] = opened[i].getDesc();
3940        }
3941        return result;
3942    }
3943    
3944    /**
3945     * Return all open Perspective objects.
3946     *
3947     * @return all open Perspective objects
3948     * @since 3.1
3949     */

3950    /*package*/Perspective [] getOpenInternalPerspectives() {
3951        return perspList.getOpenedPerspectives();
3952    }
3953    
3954    /**
3955     * Checks perspectives in the order they were activiated
3956     * for the specfied part. The first sorted perspective
3957     * that contains the specified part is returned.
3958     *
3959     * @param part specified part to search for
3960     * @return the first sorted perspespective containing the part
3961     * @since 3.1
3962     */

3963    /*package*/Perspective getFirstPerspectiveWithView(IViewPart part) {
3964        Perspective [] perspectives = perspList.getSortedPerspectives();
3965        for (int i=perspectives.length - 1; i >= 0; i--) {
3966            if (perspectives[i].containsView(part)) {
3967                return perspectives[i];
3968            }
3969        }
3970        // we should never get here
3971
return null;
3972    }
3973
3974    /**
3975     * Returns the perspectives in activation order (oldest first).
3976     */

3977    public IPerspectiveDescriptor[] getSortedPerspectives() {
3978        Perspective sortedArray[] = perspList.getSortedPerspectives();
3979        IPerspectiveDescriptor[] result = new IPerspectiveDescriptor[sortedArray.length];
3980        for (int i = 0; i < result.length; i++) {
3981            result[i] = sortedArray[i].getDesc();
3982        }
3983        return result;
3984    }
3985
3986    /*
3987     * Returns the parts in activation order (oldest first).
3988     */

3989    public IWorkbenchPartReference[] getSortedParts() {
3990        return activationList.getParts();
3991    }
3992
3993    /**
3994     * Returns the reference to the given part, or <code>null</code> if it has no reference
3995     * (i.e. it is not a top-level part in this workbench page).
3996     *
3997     * @param part the part
3998     * @return the part's reference or <code>null</code> if the given part does not belong
3999     * to this workbench page
4000     */

4001    public IWorkbenchPartReference getReference(IWorkbenchPart part) {
4002        if (part == null) {
4003            return null;
4004        }
4005        IWorkbenchPartSite site = part.getSite();
4006        if (!(site instanceof PartSite)) {
4007            return null;
4008        }
4009        PartSite partSite = ((PartSite) site);
4010        PartPane pane = partSite.getPane();
4011        if (pane instanceof MultiEditorInnerPane) {
4012            MultiEditorInnerPane innerPane = (MultiEditorInnerPane) pane;
4013            return innerPane.getParentPane().getPartReference();
4014        }
4015        return partSite.getPartReference();
4016    }
4017
4018    private class ActivationList {
4019        //List of parts in the activation order (oldest first)
4020
List JavaDoc parts = new ArrayList JavaDoc();
4021
4022        /*
4023         * Add/Move the active part to end of the list;
4024         */

4025        void setActive(IWorkbenchPart part) {
4026            if (parts.size() <= 0) {
4027                return;
4028            }
4029            IWorkbenchPartReference ref = getReference(part);
4030            if (ref != null) {
4031                if (ref == parts.get(parts.size() - 1)) {
4032                    return;
4033                }
4034                parts.remove(ref);
4035                parts.add(ref);
4036            }
4037        }
4038        
4039        /*
4040         * Ensures that the given part appears AFTER any other part in the same
4041         * container.
4042         */

4043        void bringToTop(IWorkbenchPartReference ref) {
4044            ILayoutContainer targetContainer = getContainer(ref);
4045            
4046            int newIndex = lastIndexOfContainer(targetContainer);
4047            
4048            //New index can be -1 if there is no last index
4049
if (newIndex >= 0 && ref == parts.get(newIndex))
4050                return;
4051            
4052            parts.remove(ref);
4053            if(newIndex >= 0)
4054                parts.add(newIndex, ref);
4055            else
4056                parts.add(ref);
4057        }
4058        
4059        /*
4060         * Returns the last (most recent) index of the given container in the activation list, or returns
4061         * -1 if the given container does not appear in the activation list.
4062         */

4063        int lastIndexOfContainer(ILayoutContainer container) {
4064            for (int i = parts.size() - 1; i >= 0; i--) {
4065                IWorkbenchPartReference ref = (IWorkbenchPartReference)parts.get(i);
4066
4067                ILayoutContainer cnt = getContainer(ref);
4068                if (cnt == container) {
4069                    return i;
4070                }
4071            }
4072            
4073            return -1;
4074        }
4075
4076        /*
4077         * Add/Move the active part to end of the list;
4078         */

4079        void setActive(IWorkbenchPartReference ref) {
4080            setActive(ref.getPart(true));
4081        }
4082
4083        /*
4084         * Add the active part to the beginning of the list.
4085         */

4086        void add(IWorkbenchPartReference ref) {
4087            if (parts.indexOf(ref) >= 0) {
4088                return;
4089            }
4090
4091            IWorkbenchPart part = ref.getPart(false);
4092            if (part != null) {
4093                PartPane pane = ((PartSite) part.getSite()).getPane();
4094                if (pane instanceof MultiEditorInnerPane) {
4095                    MultiEditorInnerPane innerPane = (MultiEditorInnerPane) pane;
4096                    add(innerPane.getParentPane().getPartReference());
4097                    return;
4098                }
4099            }
4100            parts.add(0, ref);
4101        }
4102
4103        /*
4104         * Return the active part. Filter fast views.
4105         */

4106        IWorkbenchPart getActive() {
4107            if (parts.isEmpty()) {
4108                return null;
4109            }
4110            return getActive(parts.size() - 1);
4111        }
4112
4113        /*
4114         * Return the previously active part. Filter fast views.
4115         */

4116        IWorkbenchPart getPreviouslyActive() {
4117            if (parts.size() < 2) {
4118                return null;
4119            }
4120            return getActive(parts.size() - 2);
4121        }
4122
4123        private IWorkbenchPart getActive(int start) {
4124            IWorkbenchPartReference ref = getActiveReference(start, false);
4125            
4126            if (ref == null) {
4127                return null;
4128            }
4129            
4130            return ref.getPart(true);
4131        }
4132        
4133        public IWorkbenchPartReference getActiveReference(boolean editorsOnly) {
4134            return getActiveReference(parts.size() - 1, editorsOnly);
4135        }
4136        
4137        private IWorkbenchPartReference getActiveReference(int start, boolean editorsOnly) {
4138            // First look for parts that aren't obscured by the current zoom state
4139
IWorkbenchPartReference nonObscured = getActiveReference(start, editorsOnly, true);
4140            
4141            if (nonObscured != null) {
4142                return nonObscured;
4143            }
4144            
4145            // Now try all the rest of the parts
4146
return getActiveReference(start, editorsOnly, false);
4147        }
4148        
4149        /*
4150         * Find a part in the list starting from the end and filter fast views
4151         * and views from other perspectives.
4152         */

4153        private IWorkbenchPartReference getActiveReference(int start, boolean editorsOnly, boolean skipPartsObscuredByZoom) {
4154            IWorkbenchPartReference[] views = getViewReferences();
4155            for (int i = start; i >= 0; i--) {
4156                WorkbenchPartReference ref = (WorkbenchPartReference) parts
4157                        .get(i);
4158
4159                if (editorsOnly && !(ref instanceof IEditorReference)) {
4160                    continue;
4161                }
4162                
4163                // Skip parts whose containers have disabled auto-focus
4164
PartPane pane = ref.getPane();
4165
4166                if (pane != null) {
4167                    if (!pane.allowsAutoFocus()) {
4168                        continue;
4169                    }
4170                    
4171                    if (skipPartsObscuredByZoom) {
4172                        if (pane.isObscuredByZoom()) {
4173                            continue;
4174                        }
4175                    }
4176                }
4177
4178                // Skip fast views (unless overridden)
4179
if (ref instanceof IViewReference) {
4180                    if (includeActiveFastViews || !((IViewReference) ref).isFastView()) {
4181                        for (int j = 0; j < views.length; j++) {
4182                            if (views[j] == ref) {
4183                                return ref;
4184                            }
4185                        }
4186                    }
4187                } else {
4188                    return ref;
4189                }
4190            }
4191            return null;
4192        }
4193
4194        /*
4195         * Retuns the index of the part within the activation list. The higher
4196         * the index, the more recently it was used.
4197         */

4198        int indexOf(IWorkbenchPart part) {
4199            IWorkbenchPartReference ref = getReference(part);
4200            if (ref == null) {
4201                return -1;
4202            }
4203            return parts.indexOf(ref);
4204        }
4205
4206        /*
4207         * Returns the index of the part reference within the activation list.
4208         * The higher the index, the more recent it was used.
4209         */

4210        int indexOf(IWorkbenchPartReference ref) {
4211            return parts.indexOf(ref);
4212        }
4213
4214        /*
4215         * Remove a part from the list
4216         */

4217        boolean remove(IWorkbenchPartReference ref) {
4218            return parts.remove(ref);
4219        }
4220
4221        /*
4222         * Returns the editors in activation order (oldest first).
4223         */

4224        private IEditorReference[] getEditors() {
4225            ArrayList JavaDoc editors = new ArrayList JavaDoc(parts.size());
4226            for (Iterator JavaDoc i = parts.iterator(); i.hasNext();) {
4227                IWorkbenchPartReference part = (IWorkbenchPartReference) i
4228                        .next();
4229                if (part instanceof IEditorReference) {
4230                    editors.add(part);
4231                }
4232            }
4233            return (IEditorReference[]) editors
4234                    .toArray(new IEditorReference[editors.size()]);
4235        }
4236
4237        /*
4238         * Return a list with all parts (editors and views).
4239         */

4240        private IWorkbenchPartReference[] getParts() {
4241            IWorkbenchPartReference[] views = getViewReferences();
4242            ArrayList JavaDoc resultList = new ArrayList JavaDoc(parts.size());
4243            for (Iterator JavaDoc iterator = parts.iterator(); iterator.hasNext();) {
4244                IWorkbenchPartReference ref = (IWorkbenchPartReference) iterator
4245                        .next();
4246                if (ref instanceof IViewReference) {
4247                    //Filter views from other perspectives
4248
for (int i = 0; i < views.length; i++) {
4249                        if (views[i] == ref) {
4250                            resultList.add(ref);
4251                            break;
4252                        }
4253                    }
4254                } else {
4255                    resultList.add(ref);
4256                }
4257            }
4258            IWorkbenchPartReference[] result = new IWorkbenchPartReference[resultList
4259                    .size()];
4260            return (IWorkbenchPartReference[]) resultList.toArray(result);
4261        }
4262
4263        /*
4264         * Returns the topmost editor on the stack, or null if none.
4265         */

4266        IEditorPart getTopEditor() {
4267            IEditorReference editor = (IEditorReference)getActiveReference(parts.size() - 1, true);
4268            
4269            if (editor == null) {
4270                return null;
4271            }
4272            
4273            return editor.getEditor(true);
4274        }
4275    }
4276
4277    /**
4278     * Helper class to keep track of all opened perspective. Both the opened
4279     * and used order is kept.
4280     */

4281    private class PerspectiveList {
4282        /**
4283         * List of perspectives in the order they were opened;
4284         */

4285        private List JavaDoc openedList;
4286
4287        /**
4288         * List of perspectives in the order they were used. Last element is
4289         * the most recently used, and first element is the least recently
4290         * used.
4291         */

4292        private List JavaDoc usedList;
4293
4294        /**
4295         * The perspective explicitly set as being the active one
4296         */

4297        private Perspective active;
4298
4299        /**
4300         * Creates an empty instance of the perspective list
4301         */

4302        public PerspectiveList() {
4303            openedList = new ArrayList JavaDoc();
4304            usedList = new ArrayList JavaDoc();
4305        }
4306
4307        /**
4308         * Update the order of the perspectives in the opened list
4309         *
4310         * @param perspective
4311         * @param newLoc
4312         */

4313        public void reorder(IPerspectiveDescriptor perspective, int newLoc) {
4314            int oldLocation = 0;
4315            Perspective movedPerspective = null;
4316            for (Iterator JavaDoc iterator = openedList.iterator(); iterator.hasNext();) {
4317                Perspective openPerspective = (Perspective) iterator.next();
4318                if (openPerspective.getDesc().equals(perspective)) {
4319                    oldLocation = openedList.indexOf(openPerspective);
4320                    movedPerspective = openPerspective;
4321                }
4322            }
4323            
4324            if (oldLocation == newLoc) {
4325                return;
4326            }
4327            
4328            openedList.remove(oldLocation);
4329            openedList.add(newLoc, movedPerspective);
4330            
4331        }
4332
4333        /**
4334         * Return all perspectives in the order they were activated.
4335         *
4336         * @return an array of perspectives sorted by activation order, least
4337         * recently activated perspective last.
4338         */

4339        public Perspective[] getSortedPerspectives() {
4340            Perspective[] result = new Perspective[usedList.size()];
4341            return (Perspective[]) usedList.toArray(result);
4342        }
4343
4344        /**
4345         * Adds a perspective to the list. No check is done for a duplicate when
4346         * adding.
4347         * @param perspective the perspective to add
4348         * @return boolean <code>true</code> if the perspective was added
4349         */

4350        public boolean add(Perspective perspective) {
4351            openedList.add(perspective);
4352            usedList.add(0, perspective);
4353            //It will be moved to top only when activated.
4354
return true;
4355        }
4356
4357        /**
4358         * Returns an iterator on the perspective list in the order they were
4359         * opened.
4360         */

4361        public Iterator JavaDoc iterator() {
4362            return openedList.iterator();
4363        }
4364
4365        /**
4366         * Returns an array with all opened perspectives
4367         */

4368        public Perspective[] getOpenedPerspectives() {
4369            Perspective[] result = new Perspective[openedList.size()];
4370            return (Perspective[]) openedList.toArray(result);
4371        }
4372
4373        /**
4374         * Removes a perspective from the list.
4375         */

4376        public boolean remove(Perspective perspective) {
4377            if (active == perspective) {
4378                updateActionSets(active, null);
4379                active = null;
4380            }
4381            usedList.remove(perspective);
4382            return openedList.remove(perspective);
4383        }
4384
4385        /**
4386         * Swap the opened order of old perspective with the new perspective.
4387         */

4388        public void swap(Perspective oldPerspective, Perspective newPerspective) {
4389            int oldIndex = openedList.indexOf(oldPerspective);
4390            int newIndex = openedList.indexOf(newPerspective);
4391
4392            if (oldIndex < 0 || newIndex < 0) {
4393                return;
4394            }
4395
4396            openedList.set(oldIndex, newPerspective);
4397            openedList.set(newIndex, oldPerspective);
4398        }
4399
4400        /**
4401         * Returns whether the list contains any perspectives
4402         */

4403        public boolean isEmpty() {
4404            return openedList.isEmpty();
4405        }
4406
4407        /**
4408         * Returns the most recently used perspective in the list.
4409         */

4410        public Perspective getActive() {
4411            return active;
4412        }
4413
4414        /**
4415         * Returns the next most recently used perspective in the list.
4416         */

4417        public Perspective getNextActive() {
4418            if (active == null) {
4419                if (usedList.isEmpty()) {
4420                    return null;
4421                } else {
4422                    return (Perspective) usedList.get(usedList.size() - 1);
4423                }
4424            } else {
4425                if (usedList.size() < 2) {
4426                    return null;
4427                } else {
4428                    return (Perspective) usedList.get(usedList.size() - 2);
4429                }
4430            }
4431        }
4432
4433        /**
4434         * Returns the number of perspectives opened
4435         */

4436        public int size() {
4437            return openedList.size();
4438        }
4439
4440        /**
4441         * Marks the specified perspective as the most recently used one in the
4442         * list.
4443         */

4444        public void setActive(Perspective perspective) {
4445            if (perspective == active) {
4446                return;
4447            }
4448
4449            updateActionSets(active, perspective);
4450            active = perspective;
4451
4452            if (perspective != null) {
4453                usedList.remove(perspective);
4454                usedList.add(perspective);
4455            }
4456        }
4457        
4458        private void updateActionSets(Perspective oldPersp, Perspective newPersp) {
4459            // Update action sets
4460

4461            IContextService service = (IContextService) window
4462                    .getService(IContextService.class);
4463            try {
4464                service.activateContext(ContextAuthority.DEFER_EVENTS);
4465                if (newPersp != null) {
4466                    IActionSetDescriptor[] newAlwaysOn = newPersp
4467                            .getAlwaysOnActionSets();
4468                    for (int i = 0; i < newAlwaysOn.length; i++) {
4469                        IActionSetDescriptor descriptor = newAlwaysOn[i];
4470
4471                        actionSets.showAction(descriptor);
4472                    }
4473
4474                    IActionSetDescriptor[] newAlwaysOff = newPersp
4475                            .getAlwaysOffActionSets();
4476                    for (int i = 0; i < newAlwaysOff.length; i++) {
4477                        IActionSetDescriptor descriptor = newAlwaysOff[i];
4478
4479                        actionSets.maskAction(descriptor);
4480                    }
4481                }
4482
4483                if (oldPersp != null) {
4484                    IActionSetDescriptor[] newAlwaysOn = oldPersp
4485                            .getAlwaysOnActionSets();
4486                    for (int i = 0; i < newAlwaysOn.length; i++) {
4487                        IActionSetDescriptor descriptor = newAlwaysOn[i];
4488
4489                        actionSets.hideAction(descriptor);
4490                    }
4491
4492                    IActionSetDescriptor[] newAlwaysOff = oldPersp
4493                            .getAlwaysOffActionSets();
4494                    for (int i = 0; i < newAlwaysOff.length; i++) {
4495                        IActionSetDescriptor descriptor = newAlwaysOff[i];
4496
4497                        actionSets.unmaskAction(descriptor);
4498                    }
4499                }
4500            } finally {
4501                service.activateContext(ContextAuthority.SEND_EVENTS);
4502            }
4503        }
4504    }
4505
4506    // for dynamic UI
4507
protected void addPerspective(Perspective persp) {
4508        perspList.add(persp);
4509        window.firePerspectiveOpened(this, persp.getDesc());
4510    }
4511
4512    /**
4513     * Find the stack of view references stacked with this view part.
4514     *
4515     * @param part
4516     * the part
4517     * @return the stack of references
4518     * @since 3.0
4519     */

4520    private IViewReference[] getViewReferenceStack(IViewPart part) {
4521        // Sanity check.
4522
Perspective persp = getActivePerspective();
4523        if (persp == null || !certifyPart(part)) {
4524            return null;
4525        }
4526
4527        ILayoutContainer container = ((PartSite) part.getSite()).getPane()
4528                .getContainer();
4529        if (container instanceof ViewStack) {
4530            ViewStack folder = (ViewStack) container;
4531            final ArrayList JavaDoc list = new ArrayList JavaDoc(folder.getChildren().length);
4532            for (int i = 0; i < folder.getChildren().length; i++) {
4533                LayoutPart layoutPart = folder.getChildren()[i];
4534                if (layoutPart instanceof ViewPane) {
4535                    IViewReference view = ((ViewPane) layoutPart)
4536                            .getViewReference();
4537                    if (view != null) {
4538                        list.add(view);
4539                    }
4540                }
4541            }
4542
4543            // sort the list by activation order (most recently activated first)
4544
Collections.sort(list, new Comparator JavaDoc() {
4545                public int compare(Object JavaDoc o1, Object JavaDoc o2) {
4546                    int pos1 = (-1)
4547                            * activationList
4548                                    .indexOf((IWorkbenchPartReference) o1);
4549                    int pos2 = (-1)
4550                            * activationList
4551                                    .indexOf((IWorkbenchPartReference) o2);
4552                    return pos1 - pos2;
4553                }
4554            });
4555
4556            return (IViewReference[]) list.toArray(new IViewReference[list
4557                    .size()]);
4558        }
4559
4560        return new IViewReference[] { (IViewReference) getReference(part) };
4561    }
4562
4563    /*
4564     * (non-Javadoc)
4565     *
4566     * @see org.eclipse.ui.IWorkbenchPage#getViewStack(org.eclipse.ui.IViewPart)
4567     */

4568    public IViewPart[] getViewStack(IViewPart part) {
4569        IViewReference[] refStack = getViewReferenceStack(part);
4570        if (refStack == null) {
4571            return null;
4572        }
4573
4574        List JavaDoc result = new ArrayList JavaDoc();
4575       
4576        for (int i = 0; i < refStack.length; i++) {
4577            IViewPart next = refStack[i].getView(false);
4578            if (next != null) {
4579                result.add(next);
4580            }
4581        }
4582
4583        return (IViewPart[]) result.toArray(new IViewPart[result.size()]);
4584    }
4585
4586    /**
4587     * Allow for programmatically resizing a part.
4588     * <p>
4589     * <em>EXPERIMENTAL</em>
4590     * </p>
4591     * <p>
4592     * Known limitations:
4593     * <ul>
4594     * <li>currently applies only to views</li>
4595     * <li>has no effect when view is zoomed</li>
4596     * </ul>
4597     */

4598    public void resizeView(IViewPart part, int width, int height) {
4599        SashInfo sashInfo = new SashInfo();
4600        PartPane pane = ((PartSite) part.getSite()).getPane();
4601        ILayoutContainer container = pane.getContainer();
4602        LayoutTree tree = getPerspectivePresentation().getLayout().root
4603                .find(((ViewStack) container));
4604
4605        // retrieve our layout sashes from the layout tree
4606
findSashParts(tree, pane.findSashes(), sashInfo);
4607
4608        // first set the width
4609
float deltaWidth = width - pane.getBounds().width;
4610        if (sashInfo.right != null) {
4611            Rectangle rightBounds = sashInfo.rightNode.getBounds();
4612            // set the new ratio
4613
sashInfo.right.setRatio(((deltaWidth + sashInfo.right
4614                    .getBounds().x) - rightBounds.x)
4615                    / rightBounds.width);
4616            // complete the resize
4617
sashInfo.rightNode.setBounds(rightBounds);
4618        } else if (sashInfo.left != null) {
4619            Rectangle leftBounds = sashInfo.leftNode.getBounds();
4620            // set the ratio
4621
sashInfo.left
4622                    .setRatio(((sashInfo.left.getBounds().x - deltaWidth) - leftBounds.x)
4623                            / leftBounds.width);
4624            // complete the resize
4625
sashInfo.leftNode.setBounds(sashInfo.leftNode.getBounds());
4626        }
4627
4628        // next set the height
4629
float deltaHeight = height - pane.getBounds().height;
4630        if (sashInfo.bottom != null) {
4631            Rectangle bottomBounds = sashInfo.bottomNode.getBounds();
4632            // set the new ratio
4633
sashInfo.bottom.setRatio(((deltaHeight + sashInfo.bottom
4634                    .getBounds().y) - bottomBounds.y)
4635                    / bottomBounds.height);
4636            // complete the resize
4637
sashInfo.bottomNode.setBounds(bottomBounds);
4638        } else if (sashInfo.top != null) {
4639            Rectangle topBounds = sashInfo.topNode.getBounds();
4640            // set the ratio
4641
sashInfo.top
4642                    .setRatio(((sashInfo.top.getBounds().y - deltaHeight) - topBounds.y)
4643                            / topBounds.height);
4644            // complete the resize
4645
sashInfo.topNode.setBounds(topBounds);
4646        }
4647
4648    }
4649
4650    // provides sash information for the given pane
4651
private class SashInfo {
4652        private LayoutPartSash right;
4653
4654        private LayoutPartSash left;
4655
4656        private LayoutPartSash top;
4657
4658        private LayoutPartSash bottom;
4659
4660        private LayoutTreeNode rightNode;
4661
4662        private LayoutTreeNode leftNode;
4663
4664        private LayoutTreeNode topNode;
4665
4666        private LayoutTreeNode bottomNode;
4667    }
4668
4669    private void findSashParts(LayoutTree tree, PartPane.Sashes sashes,
4670            SashInfo info) {
4671        LayoutTree parent = tree.getParent();
4672        if (parent == null) {
4673            return;
4674        }
4675
4676        if (parent.part instanceof LayoutPartSash) {
4677            // get the layout part sash from this tree node
4678
LayoutPartSash sash = (LayoutPartSash) parent.part;
4679            // make sure it has a sash control
4680
Control control = sash.getControl();
4681            if (control != null) {
4682                // check for a vertical sash
4683
if (sash.isVertical()) {
4684                    if (sashes.left == control) {
4685                        info.left = sash;
4686                        info.leftNode = parent.findSash(sash);
4687                    } else if (sashes.right == control) {
4688                        info.right = sash;
4689                        info.rightNode = parent.findSash(sash);
4690                    }
4691                }
4692                // check for a horizontal sash
4693
else {
4694                    if (sashes.top == control) {
4695                        info.top = sash;
4696                        info.topNode = parent.findSash(sash);
4697                    } else if (sashes.bottom == control) {
4698                        info.bottom = sash;
4699                        info.bottomNode = parent.findSash(sash);
4700                    }
4701                }
4702            }
4703        }
4704        // recursive call to continue up the tree
4705
findSashParts(parent, sashes, info);
4706    }
4707    
4708    /**
4709     * Returns all parts that are owned by this page
4710     *
4711     * @return
4712     */

4713    IWorkbenchPartReference[] getAllParts() {
4714        IViewReference[] views = viewFactory.getViews();
4715        IEditorReference[] editors = getEditorReferences();
4716        
4717        IWorkbenchPartReference[] result = new IWorkbenchPartReference[views.length + editors.length];
4718        int resultIdx = 0;
4719        
4720        for (int i = 0; i < views.length; i++) {
4721            result[resultIdx++] = views[i];
4722        }
4723        
4724        for (int i = 0; i < editors.length; i++) {
4725            result[resultIdx++] = editors[i];
4726        }
4727        
4728        return result;
4729    }
4730    
4731    /**
4732     * Returns all open parts that are owned by this page (that is, all parts
4733     * for which a part opened event would have been sent -- these would be
4734     * activated parts whose controls have already been created.
4735     */

4736    IWorkbenchPartReference[] getOpenParts() {
4737        IWorkbenchPartReference[] refs = getAllParts();
4738        List JavaDoc result = new ArrayList JavaDoc();
4739        
4740        for (int i = 0; i < refs.length; i++) {
4741            IWorkbenchPartReference reference = refs[i];
4742            
4743            IWorkbenchPart part = reference.getPart(false);
4744            if (part != null) {
4745                result.add(reference);
4746            }
4747        }
4748        
4749        return (IWorkbenchPartReference[]) result.toArray(new IWorkbenchPartReference[result.size()]);
4750    }
4751    
4752    /**
4753     * Sanity-checks the objects in this page. Throws an Assertation exception
4754     * if an object's internal state is invalid. ONLY INTENDED FOR USE IN THE
4755     * UI TEST SUITES.
4756     */

4757    public void testInvariants() {
4758        Perspective persp = getActivePerspective();
4759        
4760        if (persp != null) {
4761
4762            persp.testInvariants();
4763            
4764            // When we have widgets, ensure that there is no situation where the editor area is visible
4765
// and the perspective doesn't want an editor area.
4766
if (!SwtUtil.isDisposed(getClientComposite()) && editorPresentation.getLayoutPart().isVisible()) {
4767                Assert.isTrue(persp.isEditorAreaVisible());
4768            }
4769        }
4770        
4771    }
4772
4773    /* (non-Javadoc)
4774     * @see org.eclipse.ui.IWorkbenchPage#getExtensionTracker()
4775     */

4776    public IExtensionTracker getExtensionTracker() {
4777        if (tracker == null) {
4778            tracker = new UIExtensionTracker(getWorkbenchWindow().getWorkbench().getDisplay());
4779        }
4780        return tracker;
4781    }
4782
4783    /*
4784     * (non-Javadoc)
4785     *
4786     * @see org.eclipse.ui.IWorkbenchPage#getNewWizardShortcuts()
4787     */

4788    public String JavaDoc[] getNewWizardShortcuts() {
4789        Perspective persp = getActivePerspective();
4790        if (persp == null) {
4791            return new String JavaDoc[0];
4792        }
4793        return persp.getNewWizardShortcuts();
4794    }
4795
4796    /*
4797     * (non-Javadoc)
4798     *
4799     * @see org.eclipse.ui.IWorkbenchPage#getPerspectiveShortcuts()
4800     */

4801    public String JavaDoc[] getPerspectiveShortcuts() {
4802        Perspective persp = getActivePerspective();
4803        if (persp == null) {
4804            return new String JavaDoc[0];
4805        }
4806        return persp.getPerspectiveShortcuts();
4807    }
4808
4809    /*
4810     * (non-Javadoc)
4811     *
4812     * @see org.eclipse.ui.IWorkbenchPage#getShowViewShortcuts()
4813     */

4814    public String JavaDoc[] getShowViewShortcuts() {
4815        Perspective persp = getActivePerspective();
4816        if (persp == null) {
4817            return new String JavaDoc[0];
4818        }
4819        return persp.getShowViewShortcuts();
4820    }
4821    
4822    /**
4823     * @since 3.1
4824     */

4825    private void suggestReset() {
4826        final IWorkbench workbench = getWorkbenchWindow().getWorkbench();
4827        workbench.getDisplay().asyncExec(new Runnable JavaDoc() {
4828            public void run() {
4829                Shell parentShell = null;
4830                
4831                IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
4832                if (window == null) {
4833                    if (workbench.getWorkbenchWindowCount() == 0) {
4834                        return;
4835                    }
4836                    window = workbench.getWorkbenchWindows()[0];
4837                }
4838
4839                parentShell = window.getShell();
4840
4841                if (MessageDialog
4842                        .openQuestion(
4843                                parentShell,
4844                                WorkbenchMessages.Dynamic_resetPerspectiveTitle,
4845                                WorkbenchMessages.Dynamic_resetPerspectiveMessage)) {
4846                    IWorkbenchPage page = window.getActivePage();
4847                    if (page == null) {
4848                        return;
4849                    }
4850                    page.resetPerspective();
4851                }
4852            }
4853        });
4854
4855        
4856    }
4857    
4858    public boolean isPartVisible(IWorkbenchPartReference reference) {
4859        IWorkbenchPart part = reference.getPart(false);
4860        // Can't be visible if it isn't created yet
4861
if (part == null) {
4862            return false;
4863        }
4864        
4865        return isPartVisible(part);
4866    }
4867
4868    public IWorkingSet[] getWorkingSets() {
4869        return workingSets;
4870    }
4871
4872    public void setWorkingSets(IWorkingSet[] newWorkingSets) {
4873        if (newWorkingSets == null) {
4874            newWorkingSets = new IWorkingSet[0];
4875        }
4876
4877        IWorkingSet[] oldWorkingSets = workingSets;
4878        
4879        // filter out any duplicates if necessary
4880
if (newWorkingSets.length > 1) {
4881            Set JavaDoc setOfSets = new HashSet JavaDoc();
4882            for (int i = 0; i < newWorkingSets.length; i++) {
4883                if (newWorkingSets[i] == null) {
4884                    throw new IllegalArgumentException JavaDoc();
4885                }
4886                setOfSets.add(newWorkingSets[i]);
4887            }
4888            newWorkingSets = (IWorkingSet[]) setOfSets
4889                    .toArray(new IWorkingSet[setOfSets.size()]);
4890        }
4891
4892        workingSets = newWorkingSets;
4893        if (!Arrays.equals(oldWorkingSets, newWorkingSets)) {
4894            firePropertyChange(CHANGE_WORKING_SETS_REPLACE, oldWorkingSets,
4895                    newWorkingSets);
4896            if (aggregateWorkingSet != null) {
4897                aggregateWorkingSet.setComponents(workingSets);
4898            }
4899        }
4900        if (newWorkingSets != null) {
4901            WorkbenchPlugin
4902                    .getDefault()
4903                    .getWorkingSetManager()
4904                    .addPropertyChangeListener(workingSetPropertyChangeListener);
4905        } else {
4906            WorkbenchPlugin.getDefault().getWorkingSetManager()
4907                    .removePropertyChangeListener(
4908                            workingSetPropertyChangeListener);
4909        }
4910    }
4911    
4912    public IWorkingSet getAggregateWorkingSet() {
4913        if (aggregateWorkingSet == null) {
4914            IWorkingSetManager workingSetManager = PlatformUI.getWorkbench()
4915                    .getWorkingSetManager();
4916            aggregateWorkingSet = (AggregateWorkingSet) workingSetManager.getWorkingSet(
4917                            getAggregateWorkingSetId());
4918            if (aggregateWorkingSet == null) {
4919                aggregateWorkingSet = (AggregateWorkingSet) workingSetManager
4920                        .createAggregateWorkingSet(
4921                                getAggregateWorkingSetId(),
4922                                WorkbenchMessages.WorkbenchPage_workingSet_default_label,
4923                                getWorkingSets());
4924                workingSetManager.addWorkingSet(aggregateWorkingSet);
4925            }
4926        }
4927        return aggregateWorkingSet;
4928    }
4929
4930    private String JavaDoc getAggregateWorkingSetId() {
4931        if (aggregateWorkingSetId == null) {
4932            aggregateWorkingSetId = "Aggregate for window " + System.currentTimeMillis(); //$NON-NLS-1$
4933
}
4934        return aggregateWorkingSetId;
4935    }
4936}
4937
Popular Tags