Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/eclipse/ui/internal/WorkbenchPage.java


1   /*******************************************************************************
2    * Copyright (c) 2000, 2004 IBM Corporation and others.
3    * All rights reserved. This program and the accompanying materials 
4    * are made available under the terms of the Common Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/cpl-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;
15  import java.util.ArrayList;
16  import java.util.Collections;
17  import java.util.Comparator;
18  import java.util.HashMap;
19  import java.util.HashSet;
20  import java.util.Iterator;
21  import java.util.List;
22  import java.util.Set;
23  
24  import org.eclipse.core.runtime.IAdaptable;
25  import org.eclipse.core.runtime.IProgressMonitor;
26  import org.eclipse.core.runtime.IStatus;
27  import org.eclipse.core.runtime.MultiStatus;
28  import org.eclipse.core.runtime.Platform;
29  import org.eclipse.core.runtime.Status;
30  import org.eclipse.jface.action.CoolBarManager;
31  import org.eclipse.jface.action.IContributionItem;
32  import org.eclipse.jface.dialogs.ErrorDialog;
33  import org.eclipse.jface.dialogs.IDialogConstants;
34  import org.eclipse.jface.dialogs.MessageDialog;
35  import org.eclipse.jface.operation.IRunnableWithProgress;
36  import org.eclipse.jface.preference.IPreferenceStore;
37  import org.eclipse.jface.util.IPropertyChangeListener;
38  import org.eclipse.jface.util.ListenerList;
39  import org.eclipse.jface.util.PropertyChangeEvent;
40  import org.eclipse.jface.util.SafeRunnable;
41  import org.eclipse.jface.viewers.ISelection;
42  import org.eclipse.jface.window.Window;
43  import org.eclipse.swt.SWT;
44  import org.eclipse.swt.custom.BusyIndicator;
45  import org.eclipse.swt.events.ControlAdapter;
46  import org.eclipse.swt.events.ControlEvent;
47  import org.eclipse.swt.events.ControlListener;
48  import org.eclipse.swt.graphics.Rectangle;
49  import org.eclipse.swt.widgets.Composite;
50  import org.eclipse.swt.widgets.Control;
51  import org.eclipse.swt.widgets.Display;
52  import org.eclipse.ui.IActionBars;
53  import org.eclipse.ui.IEditorInput;
54  import org.eclipse.ui.IEditorPart;
55  import org.eclipse.ui.IEditorReference;
56  import org.eclipse.ui.IEditorRegistry;
57  import org.eclipse.ui.IMemento;
58  import org.eclipse.ui.INavigationHistory;
59  import org.eclipse.ui.IPartListener;
60  import org.eclipse.ui.IPartListener2;
61  import org.eclipse.ui.IPerspectiveDescriptor;
62  import org.eclipse.ui.IPerspectiveRegistry;
63  import org.eclipse.ui.IReusableEditor;
64  import org.eclipse.ui.ISaveablePart;
65  import org.eclipse.ui.ISelectionListener;
66  import org.eclipse.ui.IViewPart;
67  import org.eclipse.ui.IViewReference;
68  import org.eclipse.ui.IWorkbenchPage;
69  import org.eclipse.ui.IWorkbenchPart;
70  import org.eclipse.ui.IWorkbenchPartReference;
71  import org.eclipse.ui.IWorkbenchPartSite;
72  import org.eclipse.ui.IWorkbenchWindow;
73  import org.eclipse.ui.IWorkingSet;
74  import org.eclipse.ui.IWorkingSetManager;
75  import org.eclipse.ui.PartInitException;
76  import org.eclipse.ui.PlatformUI;
77  import org.eclipse.ui.SubActionBars;
78  import org.eclipse.ui.WorkbenchException;
79  import org.eclipse.ui.internal.dialogs.CustomizePerspectiveDialog;
80  import org.eclipse.ui.internal.intro.IIntroConstants;
81  import org.eclipse.ui.internal.misc.StatusUtil;
82  import org.eclipse.ui.internal.misc.UIStats;
83  import org.eclipse.ui.internal.registry.IActionSetDescriptor;
84  import org.eclipse.ui.internal.registry.IStickyViewDescriptor;
85  import org.eclipse.ui.internal.registry.IViewRegistry;
86  import org.eclipse.ui.internal.registry.PerspectiveDescriptor;
87  import org.eclipse.ui.model.IWorkbenchAdapter;
88  import org.eclipse.ui.part.MultiEditor;
89  
90  /**
91   * A collection of views and editors in a workbench.
92   */
93  public class WorkbenchPage extends CompatibleWorkbenchPage implements IWorkbenchPage {
94    private WorkbenchWindow window;
95    private IAdaptable input;
96    private IWorkingSet workingSet;
97    private Composite composite;
98    private ControlListener resizeListener;
99    private IWorkbenchPart activePart;
100   //Could be delete. This information is in the active part list;
101   private ActivationList activationList = new ActivationList();
102   private IEditorPart lastActiveEditor;
103   private EditorManager editorMgr;
104   private EditorAreaHelper editorPresentation;
105   private PartListenerList partListeners = new PartListenerList();
106   private PartListenerList2 partListeners2 = new PartListenerList2();
107   private ListenerList propertyChangeListeners = new ListenerList();
108   private PageSelectionService selectionService =
109     new PageSelectionService(this);
110   private IActionBars actionBars;
111   private ViewFactory viewFactory;
112   private PerspectiveList perspList = new PerspectiveList();
113   private PerspectiveDescriptor deferredActivePersp;
114   private NavigationHistory navigationHistory = new NavigationHistory(this);
115   //for dynamic UI - saving state for editors, views and perspectives
116   private HashMap stateMap = new HashMap();
117   private IPropertyChangeListener propertyChangeListener =
118     new IPropertyChangeListener() {
119     /*
120      * Remove the working set from the page if the working set is deleted.
121      */
122     public void propertyChange(PropertyChangeEvent event) {
123       String property = event.getProperty();
124       if (IWorkingSetManager.CHANGE_WORKING_SET_REMOVE.equals(property)
125         && event.getOldValue().equals(workingSet)) {
126         setWorkingSet(null);
127       } else if (LayoutPart.PROP_VISIBILITY.equals(property)) {
128         WorkbenchPartReference ref =
129           (WorkbenchPartReference) ((PartPane) event.getSource())
130             .getPartReference();
131         //Make sure the new visible part is restored.
132         ref.getPart(Boolean.TRUE.equals(event.getNewValue()));
133         if (ref == null)
134           return;
135         if (Boolean.TRUE.equals(event.getNewValue())) {
136           String label = "visible::" + ref.getTitle(); //$NON-NLS-1$
137           try {
138             UIStats.start(UIStats.NOTIFY_PART_LISTENERS, label);
139             partListeners2.firePartVisible(ref);
140           } finally {
141             UIStats.end(UIStats.NOTIFY_PART_LISTENERS, label);
142           }
143         } else {
144           String label = "hidden::" + ref.getTitle(); //$NON-NLS-1$
145           try {
146             UIStats.start(UIStats.NOTIFY_PART_LISTENERS, label);
147             partListeners2.firePartHidden(ref);
148           } finally {
149             UIStats.end(UIStats.NOTIFY_PART_LISTENERS, label);
150           }
151         }
152       }
153     }
154   };
155   
156   // a set of perspectives in which sticky views have already been created.
157   private Set stickyPerspectives = new HashSet(7);
158   
159   private ActionSwitcher actionSwitcher = new ActionSwitcher();
160   /**
161    * Manages editor contributions and action set part associations.
162    */
163   private class ActionSwitcher {
164     private IWorkbenchPart activePart;
165     private IEditorPart topEditor;
166     private ArrayList actionSets = new ArrayList();
167 
168     /**
169      * Updates the contributions given the new part as the active part.
170      * 
171      * @param newPart
172      *            the new active part, may be <code>null</code>
173      */
174     public void updateActivePart(IWorkbenchPart newPart) {
175       if (activePart == newPart)
176         return;
177 
178       boolean isNewPartAnEditor = newPart instanceof IEditorPart;
179       if (isNewPartAnEditor) {
180         String oldId = null;
181         if (topEditor != null)
182           oldId = topEditor.getSite().getId();
183         String newId = newPart.getSite().getId();
184 
185         // if the active part is an editor and the new editor
186         // is the same kind of editor, then we don't have to do
187         // anything
188         if (activePart == topEditor && newId.equals(oldId))
189           return;
190 
191         // remove the contributions of the old editor
192         // if it is a different kind of editor
193         if (oldId != null && !oldId.equals(newId))
194           deactivateContributions(topEditor, true);
195 
196         // if a view was the active part, disable its contributions
197         if (activePart != null && activePart != topEditor)
198           deactivateContributions(activePart, true);
199 
200         // show (and enable) the contributions of the new editor
201         // if it is a different kind of editor or if the
202         // old active part was a view
203         if (!newId.equals(oldId) || activePart != topEditor)
204           activateContributions(newPart, true);
205 
206       } else if (newPart == null) {
207         if (activePart != null)
208           // remove all contributions
209           deactivateContributions(activePart, true);
210       } else {
211         // new part is a view
212 
213         // if old active part is a view, remove all contributions,
214         // but if old part is an editor only disable
215         if (activePart != null)
216           deactivateContributions(
217             activePart,
218             activePart instanceof IViewPart);
219 
220         activateContributions(newPart, true);
221       }
222 
223       ArrayList newActionSets = null;
224       if (isNewPartAnEditor
225         || (activePart == topEditor && newPart == null))
226         newActionSets = calculateActionSets(newPart, null);
227       else
228         newActionSets = calculateActionSets(newPart, topEditor);
229 
230       if (!updateActionSets(newActionSets))
231         updateActionBars();
232 
233       if (isNewPartAnEditor) {
234         topEditor = (IEditorPart) newPart;
235       } else if (activePart == topEditor && newPart == null) {
236         // since we removed all the contributions, we clear the top
237         // editor
238         topEditor = null;
239       }
240 
241       activePart = newPart;
242     }
243 
244     /**
245      * Updates the contributions given the new part as the topEditor.
246      * 
247      * @param newEditor
248      *            the new top editor, may be <code>null</code>
249      */
250     public void updateTopEditor(IEditorPart newEditor) {
251       if (topEditor == newEditor)
252         return;
253 
254       String oldId = null;
255       if (topEditor != null)
256         oldId = topEditor.getSite().getId();
257       String newId = null;
258       if (newEditor != null)
259         newId = newEditor.getSite().getId();
260       if (oldId == null ? newId == null : oldId.equals(newId)) {
261         // we don't have to change anything
262         topEditor = newEditor;
263         return;
264       }
265 
266       // Remove the contributions of the old editor
267       if (topEditor != null)
268         deactivateContributions(topEditor, true);
269 
270       // Show (disabled) the contributions of the new editor
271       if (newEditor != null)
272         activateContributions(newEditor, false);
273 
274       ArrayList newActionSets =
275         calculateActionSets(activePart, newEditor);
276       if (!updateActionSets(newActionSets))
277         updateActionBars();
278 
279       topEditor = newEditor;
280     }
281 
282     /**
283      * Activates the contributions of the given part. If <code>enable</code>
284      * is <code>true</code> the contributions are visible and enabled,
285      * otherwise they are disabled.
286      * 
287      * @param part
288      *            the part whose contributions are to be activated
289      * @param enable
290      *            <code>true</code> the contributions are to be enabled,
291      *            not just visible.
292      */
293     private void activateContributions(
294       IWorkbenchPart part,
295       boolean enable) {
296       PartSite site = (PartSite) part.getSite();
297       SubActionBars actionBars = (SubActionBars) site.getActionBars();
298       actionBars.activate(enable);
299     }
300 
301     /**
302      * Deactivates the contributions of the given part. If <code>remove</code>
303      * is <code>true</code> the contributions are removed, otherwise they
304      * are disabled.
305      * 
306      * @param part
307      *            the part whose contributions are to be deactivated
308      * @param remove
309      *            <code>true</code> the contributions are to be removed,
310      *            not just disabled.
311      */
312     private void deactivateContributions(
313       IWorkbenchPart part,
314       boolean remove) {
315       PartSite site = (PartSite) part.getSite();
316       SubActionBars actionBars = (SubActionBars) site.getActionBars();
317       actionBars.deactivate(remove);
318     }
319 
320     /**
321      * Calculates the action sets to show for the given part and editor
322      * 
323      * @param part
324      *            the active part, may be <code>null</code>
325      * @param editor
326      *            the current editor, may be <code>null</code>, may be
327      *            the active part
328      * @return the new action sets
329      */
330     private ArrayList calculateActionSets(
331       IWorkbenchPart part,
332       IEditorPart editor) {
333       ArrayList newActionSets = new ArrayList();
334       if (part != null) {
335         IActionSetDescriptor[] partActionSets =
336           WorkbenchPlugin
337             .getDefault()
338             .getActionSetRegistry()
339             .getActionSetsFor(
340             part.getSite().getId());
341         for (int i = 0; i < partActionSets.length; i++) {
342           newActionSets.add(partActionSets[i]);
343         }
344       }
345       if (editor != null && editor != part) {
346         IActionSetDescriptor[] editorActionSets =
347           WorkbenchPlugin
348             .getDefault()
349             .getActionSetRegistry()
350             .getActionSetsFor(
351             editor.getSite().getId());
352         for (int i = 0; i < editorActionSets.length; i++) {
353           newActionSets.add(editorActionSets[i]);
354         }
355       }
356       return newActionSets;
357     }
358 
359     /**
360      * Updates the actions we are showing for the active part and current
361      * editor.
362      * 
363      * @param newActionSets
364      *            the action sets to show
365      * @return <code>true</code> if the action sets changed
366      */
367     private boolean updateActionSets(ArrayList newActionSets) {
368       if (actionSets.equals(newActionSets))
369         return false;
370 
371       Perspective persp = getActivePerspective();
372       if (persp == null) {
373         actionSets = newActionSets;
374         return false;
375       }
376 
377       // hide the old
378       for (int i = 0; i < actionSets.size(); i++) {
379         persp.hideActionSet(
380           ((IActionSetDescriptor) actionSets.get(i)).getId());
381       }
382 
383       // show the new
384       for (int i = 0; i < newActionSets.size(); i++) {
385         persp.showActionSet(
386           ((IActionSetDescriptor) newActionSets.get(i)).getId());
387       }
388 
389       actionSets = newActionSets;
390 
391       window.updateActionSets(); // this calls updateActionBars
392       window.firePerspectiveChanged(
393         WorkbenchPage.this,
394         getPerspective(),
395         CHANGE_ACTION_SET_SHOW);
396       return true;
397     }
398 
399   }
400 
401   /**
402    * Constructs a new page with a given perspective and input.
403    * 
404    * @param w
405    *            the parent window
406    * @param layoutID
407    *            must not be <code>null</code>
408    * @param input
409    *            the page input
410    */
411   public WorkbenchPage(WorkbenchWindow w, String layoutID, IAdaptable input)
412     throws WorkbenchException {
413     super();
414     if (layoutID == null)
415       throw new WorkbenchException(WorkbenchMessages.getString("WorkbenchPage.UndefinedPerspective")); //$NON-NLS-1$
416     init(w, layoutID, input);
417   }
418   /**
419    * Constructs a page. <code>restoreState(IMemento)</code> should be
420    * called to restore this page from data stored in a persistance file.
421    * 
422    * @param w
423    *            the parent window
424    * @param input
425    *            the page input
426    */
427   public WorkbenchPage(WorkbenchWindow w, IAdaptable input)
428     throws WorkbenchException {
429     super();
430     init(w, null, input);
431   }
432 
433   /**
434    * Activates a part. The part will be brought to the front and given focus.
435    * 
436    * @param part
437    *            the part to activate
438    */
439   public void activate(IWorkbenchPart part) {
440     // Sanity check.
441     if (!certifyPart(part))
442       return;
443 
444     if (window.isClosing())
445       return;
446 
447     // If zoomed, unzoom.
448     if (isZoomed() && partChangeAffectsZoom(getReference(part)))
449       zoomOut();
450 
451     if (part instanceof MultiEditor) {
452       part = ((MultiEditor) part).getActiveEditor();
453     }
454     // Activate part.
455     if (window.getActivePage() == this) {
456       bringToTop(part);
457       setActivePart(part);
458     } else {
459       activationList.setActive(part);
460       activePart = part;
461     }
462   }
463 
464   /**
465    * Activates a part. The part is given focus, the pane is hilighted.
466    */
467   private void activatePart(final IWorkbenchPart part) {
468     Platform.run(new SafeRunnable(WorkbenchMessages.getString("WorkbenchPage.ErrorActivatingView")) { //$NON-NLS-1$
469       public void run() {
470         if (part != null) {
471           part.setFocus();
472           PartSite site = (PartSite) part.getSite();
473           site.getPane().showFocus(true);
474           updateTabList(part);
475           SubActionBars bars = (SubActionBars) site.getActionBars();
476           bars.partChanged(part);
477         }
478       }
479     });
480   }
481   /**
482    * Add a fast view.
483    */
484   public void addFastView(IViewReference ref) {
485     Perspective persp = getActivePerspective();
486     if (persp == null)
487       return;
488 
489     // If view is zoomed unzoom.
490     if (isZoomed() && partChangeAffectsZoom(ref))
491       zoomOut();
492 
493     // Do real work.
494     persp.addFastView(ref);
495 
496     // The view is now invisible.
497     // If it is active then deactivate it.
498     if (ref.getPart(false) == activePart) {
499       activate(activationList.getActive());
500     }
501 
502     // Notify listeners.
503     window.updateFastViewBar();
504     window.firePerspectiveChanged(
505         this,
506         getPerspective(),
507         ref,
508         CHANGE_FAST_VIEW_ADD);
509     window.firePerspectiveChanged(
510       this,
511       getPerspective(),
512       CHANGE_FAST_VIEW_ADD);
513   }
514   /**
515    * Adds an IPartListener to the part service.
516    */
517   public void addPartListener(IPartListener l) {
518     partListeners.addPartListener(l);
519   }
520   /**
521    * Adds an IPartListener to the part service.
522    */
523   public void addPartListener(IPartListener2 l) {
524     partListeners2.addPartListener(l);
525   }
526   /**
527    * Implements IWorkbenchPage
528    * 
529    * @see org.eclipse.ui.IWorkbenchPage#addPropertyChangeListener(IPropertyChangeListener)
530    * @since 2.0
531    * @deprecated individual views should store a working set if needed and
532    *             register a property change listener directly with the
533    *             working set manager to receive notification when the view
534    *             working set is removed.
535    */
536   public void addPropertyChangeListener(IPropertyChangeListener listener) {
537     propertyChangeListeners.add(listener);
538   }
539   /*
540    * (non-Javadoc) Method declared on ISelectionListener.
541    */
542   public void addSelectionListener(ISelectionListener listener) {
543     selectionService.addSelectionListener(listener);
544   }
545 
546   /*
547    * (non-Javadoc) Method declared on ISelectionListener.
548    */
549   public void addSelectionListener(
550     String partId,
551     ISelectionListener listener) {
552     selectionService.addSelectionListener(partId, listener);
553   }
554   /*
555    * (non-Javadoc) Method declared on ISelectionListener.
556    */
557   public void addPostSelectionListener(ISelectionListener listener) {
558     selectionService.addPostSelectionListener(listener);
559   }
560 
561   /*
562    * (non-Javadoc) Method declared on ISelectionListener.
563    */
564   public void addPostSelectionListener(
565     String partId,
566     ISelectionListener listener) {
567     selectionService.addPostSelectionListener(partId, listener);
568   }
569 
570   /**
571    * Moves a part forward in the Z order of a perspective so it is visible.
572    * 
573    * @param part
574    *            the part to bring to move forward
575    */
576   public void bringToTop(IWorkbenchPart part) {
577     // Sanity check.
578     Perspective persp = getActivePerspective();
579     if (persp == null || !certifyPart(part))
580       return;
581 
582     // If zoomed then ignore.
583     if (isZoomed() && partChangeAffectsZoom(getReference(part)))
584       return;
585 
586     String label = part != null ? part.getTitle() : "none"; //$NON-NLS-1$
587     boolean broughtToTop = false;
588     try {
589       UIStats.start(UIStats.BRING_PART_TO_TOP, label);
590       // Move part.
591       if (part instanceof IEditorPart) {
592         IEditorReference ref = (IEditorReference) getReference(part);
593         broughtToTop = getEditorManager().setVisibleEditor(ref, false);
594         actionSwitcher.updateTopEditor((IEditorPart) part);
595         if (broughtToTop) {
596           lastActiveEditor = null;
597         }
598       } else if (part instanceof IViewPart) {
599         IViewReference ref = (IViewReference) getReference(part);
600         broughtToTop = persp.bringToTop(ref);
601       }
602 
603       if (broughtToTop) {
604         // Need to make sure that the part lists are sorted correctly.
605         activationList.setActive(part);
606         firePartBroughtToTop(part);
607       }
608     } finally {
609       UIStats.end(UIStats.BRING_PART_TO_TOP, label);
610     }
611   }
612   /**
613    * Resets the layout for the perspective. The active part in the old layout
614    * is activated in the new layout for consistent user context.
615    * 
616    * Assumes the busy cursor is active.
617    */
618   private void busyResetPerspective() {
619 
620       ViewIntroAdapterPart introViewAdapter = ((WorkbenchIntroManager)getWorkbenchWindow().getWorkbench().getIntroManager()).getViewIntroAdapterPart();
621       PartPane introPane = null;
622       boolean introFullScreen = false;
623       if (introViewAdapter != null) {
624           introPane = ((PartSite)introViewAdapter.getSite()).getPane();
625           introViewAdapter.setHandleZoomEvents(false);
626           introFullScreen = introPane.isZoomed();
627       }
628       
629       //try to prevent intro flicker.
630       if (introFullScreen)
631           window.getShell().setRedraw(false);
632       
633       try {
634           
635       // Always unzoom
636       if (isZoomed())
637         zoomOut();
638   
639       // Get the current perspective.
640       // This describes the working layout of the page and differs from
641       // the original template.
642       Perspective oldPersp = getActivePerspective();
643   
644       // Map the current perspective to the original template.
645       // If the original template cannot be found then it has been deleted.
646       // In
647       // that case just return. (PR#1GDSABU).
648       IPerspectiveRegistry reg =
649         WorkbenchPlugin.getDefault().getPerspectiveRegistry();
650       PerspectiveDescriptor desc =
651         (PerspectiveDescriptor) reg.findPerspectiveWithId(
652           oldPersp.getDesc().getId());
653       if (desc == null)
654         desc =
655           (PerspectiveDescriptor) reg.findPerspectiveWithId(
656             ((PerspectiveDescriptor) oldPersp.getDesc())
657               .getOriginalId());
658       if (desc == null)
659         return;
660   
661       // Notify listeners that we are doing a reset.
662       window.firePerspectiveChanged(this, desc, CHANGE_RESET);
663   
664       // Create new persp from original template.
665       Perspective newPersp = createPerspective(desc);
666       if (newPersp == null) {
667         // We're not going through with the reset, so it is complete.
668         window.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE);
669         return;
670       }
671   
672       // Update the perspective list and shortcut
673       perspList.swap(oldPersp, newPersp);
674   
675       IContributionItem item =
676         window.findPerspectiveShortcut(oldPersp.getDesc(), this);
677       if (item != null) {
678         ((PerspectiveBarContributionItem) item).setPerspective(newPersp.getDesc());
679       }
680   
681       // Install new persp.
682       setPerspective(newPersp);
683   
684       // Destroy old persp.
685       disposePerspective(oldPersp);
686   
687       // Update the Coolbar layout.
688       resetToolBarLayout();
689       
690       // restore the maximized intro
691       if (introViewAdapter != null) {
692         try {
693           // ensure that the intro is visible in the new perspective
694           showView(IIntroConstants.INTRO_VIEW_ID);
695             if (introFullScreen)         
696               toggleZoom(introPane.getPartReference());
697         } catch (PartInitException e) {
698           WorkbenchPlugin.log("Could not restore intro", //$NON-NLS-1$
699               StatusUtil.newStatus(IStatus.ERROR, e.getMessage(), e));
700         }
701         finally {
702             // we want the intro back to a normal state before we fire the event
703             introViewAdapter.setHandleZoomEvents(true);
704         }
705       }
706       // Notify listeners that we have completed our reset.
707       window.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE);
708       }
709       finally {
710           // reset the handling of zoom events (possibly for the second time) in case there was 
711           // an exception thrown
712           if (introViewAdapter != null)
713               introViewAdapter.setHandleZoomEvents(true);
714 
715           if (introFullScreen)
716               window.getShell().setRedraw(true);
717       }
718     
719   }
720   /**
721    * Implements <code>setPerspective</code>.
722    * 
723    * Assumes that busy cursor is active.
724    * 
725    * @param persp
726    *            identifies the new perspective.
727    */
728   private void busySetPerspective(IPerspectiveDescriptor desc) {
729     // Create new layout.
730     String label = desc.getId();
731     try {
732       UIStats.start(UIStats.SWITCH_PERSPECTIVE, label);
733       PerspectiveDescriptor realDesc = (PerspectiveDescriptor) desc;
734       Perspective newPersp = findPerspective(realDesc);
735       if (newPersp == null) {
736         newPersp = createPerspective(realDesc);
737         if (newPersp == null)
738           return;
739         window.addPerspectiveShortcut(realDesc, this);
740       }
741 
742       // Change layout.
743       setPerspective(newPersp);
744     } finally {
745       UIStats.end(UIStats.SWITCH_PERSPECTIVE, label);
746     }
747   }
748   /**
749    * Shows a view.
750    * 
751    * Assumes that a busy cursor is active.
752    */
753   private IViewPart busyShowView(
754       String viewID, 
755       String secondaryID, 
756       int mode)
757     throws PartInitException {
758     Perspective persp = getActivePerspective();
759     if (persp == null)
760       return null;
761 
762     // If this view is already visible just return.
763     IViewReference ref = persp.findView(viewID, secondaryID);
764     IViewPart view = null;
765     if (ref != null)
766       view = ref.getView(true);
767     if (view != null) {
768       busyShowView(view, mode);
769       return view;
770     }
771 
772     // Show the view.
773     view = persp.showView(viewID, secondaryID);
774     if (view != null) {
775       zoomOutIfNecessary(view);      
776       busyShowView(view, mode);
777       
778       window.firePerspectiveChanged(
779           this,
780           getPerspective(),
781           getReference(view),
782           CHANGE_VIEW_SHOW);
783       window.firePerspectiveChanged(
784         this,
785         getPerspective(),
786         CHANGE_VIEW_SHOW);
787       // Just in case view was fast.
788       window.updateFastViewBar();
789     }
790     return view;
791   }
792   
793   /*
794    * Performs showing of the view in the given mode.
795    */
796   private void busyShowView(IViewPart part, int mode) {
797     if (mode == VIEW_ACTIVATE)      
798       activate(part);
799     else if (mode == VIEW_VISIBLE){
800         IWorkbenchPartReference ref = getActivePartReference();
801         // if there is no active part or it's not a view, bring to top
802         if (ref == null || !(ref instanceof IViewReference))
803             bringToTop(part);
804         else {
805           // otherwise check to see if the we're in the same stack as the active view
806             IViewReference activeView = (IViewReference) ref;
807           IViewReference [] viewStack = getViewReferenceStack(part);
808           for (int i = 0; i < viewStack.length; i++) {
809                     if (viewStack[i].equals(activeView))
810                         return;
811                 }
812           bringToTop(part);
813         }          
814     }
815   }
816   
817   /**
818    * Returns whether a part exists in the current page.
819    */
820   private boolean certifyPart(IWorkbenchPart part) {
821     //Workaround for bug 22325
822     if (part != null && !(part.getSite() instanceof PartSite))
823       return false;
824 
825     if (part instanceof IEditorPart) {
826       IEditorReference ref = (IEditorReference) getReference(part);
827       return getEditorManager().containsEditor(ref);
828     }
829     if (part instanceof IViewPart) {
830       Perspective persp = getActivePerspective();
831       return persp != null && persp.containsView((IViewPart) part);
832     }
833     return false;
834   }
835   /**
836    * Closes the perspective.
837    */
838   public boolean close() {
839     final boolean[] ret = new boolean[1];
840     BusyIndicator.showWhile(null, new Runnable() {
841       public void run() {
842         ret[0] = window.closePage(WorkbenchPage.this, true);
843       }
844     });
845     return ret[0];
846   }
847   /**
848    * See IWorkbenchPage
849    */
850   public boolean closeAllSavedEditors() {
851     // get the Saved editors
852     IEditorReference editors[] = getEditorReferences();
853     IEditorReference savedEditors[] = new IEditorReference[editors.length]; 
854     int j = 0;
855     for (int i = 0; i < editors.length; i++) {
856       IEditorReference editor = editors[i];
857       if (!editor.isDirty()) {
858         savedEditors[j++] = editor;
859       }
860     }
861     //there are no unsaved editors
862     if (j == 0)
863       return true;
864     IEditorReference[] newSaved = new IEditorReference[j];
865     System.arraycopy(savedEditors, 0, newSaved, 0, j);
866     return closeEditors(newSaved, false);
867   }
868   
869   /**
870    * See IWorkbenchPage
871    */
872   public boolean closeAllEditors(boolean save) {
873     return closeEditors(getEditorReferences(), save);
874   }
875   
876   /**
877    * See IWorkbenchPage
878    */
879   public boolean closeEditors(IEditorReference[] editorRefs, boolean save) {
880     if (save) {
881       // Intersect the dirty editors with the editors that are closing
882       IEditorPart[] dirty = getDirtyEditors();
883       List intersect = new ArrayList();
884       for (int i = 0; i < editorRefs.length; i++) {
885         IEditorReference reference = editorRefs[i];
886         IEditorPart refPart = reference.getEditor(false);
887         if (refPart != null) {
888           for (int j = 0; j < dirty.length; j++) {
889             if (refPart.equals(dirty[j])) {
890               intersect.add(refPart);
891               break;
892             }
893           }
894         }
895       }
896       // Save parts, exit the method if cancel is pressed.
897       if (intersect.size() > 0) {
898         if (!EditorManager.saveAll(intersect, true, getWorkbenchWindow()))
899           return false;
900       }
901     }
902     
903     // If the user has not cancelled a possible save request 
904     // and if part is added or removed always unzoom.
905     if (isZoomed())
906       zoomOut();
907 
908 
909     // Deactivate part if the active part is being closed.
910     boolean deactivated = false;
911     for (int i=0 ; i < editorRefs.length ; i++) {
912       IWorkbenchPart part = editorRefs[i].getPart(false);
913       if (part == activePart) {
914         deactivated = true;
915         setActivePart(null);
916       }
917       if (lastActiveEditor == part) {
918         lastActiveEditor = null;
919         actionSwitcher.updateTopEditor(null);
920       }
921     }
922     
923     // Close all editors.
924     for (int i = 0; i < editorRefs.length; i++) {
925       IEditorReference ref = editorRefs[i];
926       // Notify interested listeners before the close
927       window.firePerspectiveChanged(
928           this,
929           getPerspective(),
930           ref,
931           CHANGE_EDITOR_CLOSE);
932       // Close the editor.
933       getEditorManager().closeEditor(ref);
934       activationList.remove(ref);
935       firePartClosed(ref);
936       disposePart(ref);
937     }
938 
939     if (!window.isClosing() && deactivated) {
940       activate(activationList.getActive());
941     }
942 
943     // Notify interested listeners after the close
944     window.firePerspectiveChanged(
945       this,
946       getPerspective(),
947       CHANGE_EDITOR_CLOSE);
948 
949     // Return true on success.
950     return true;
951   }
952   
953   /**
954    * See IWorkbenchPage#closeEditor
955    */
956   public boolean closeEditor(IEditorReference editorRef, boolean save) {
957     IEditorPart editor = editorRef.getEditor(false);
958     if (editor != null)
959       return closeEditor(editor, save);
960     getEditorManager().closeEditor(editorRef);
961     activationList.remove(editorRef);
962     firePartClosed(editorRef);
963     return true;
964   }
965   /**
966    * See IWorkbenchPage#closeEditor
967    */
968   public boolean closeEditor(IEditorPart editor, boolean save) {
969     // Sanity check.
970     if (!certifyPart(editor))
971       return false;
972 
973     // Save part.
974     if (save && !getEditorManager().saveEditor(editor, true))
975       return false;
976 
977     boolean partWasVisible = (editor == getActiveEditor());
978     IEditorReference ref = (IEditorReference) getReference(editor);
979     activationList.remove(ref);
980     boolean partWasActive = (editor == activePart);
981 
982     // Removing following lines to fix:
983     // http://dev.eclipse.org/bugs/show_bug.cgi?id=28031
984     //  // Deactivate part.
985     //  if (partWasActive)
986     //    setActivePart(null);
987     //  if (lastActiveEditor == editor) {
988     //    actionSwitcher.updateTopEditor(null);
989     //    lastActiveEditor = null;
990     //  }
991 
992     // Notify interested listeners before the close
993     window.firePerspectiveChanged(
994         this,
995         getPerspective(),
996         ref,
997         CHANGE_EDITOR_CLOSE);
998     // Close the part.
999     getEditorManager().closeEditor(ref);
1000    firePartClosed(ref);
1001    disposePart(ref);
1002    // Notify interested listeners after the close
1003    window.firePerspectiveChanged(
1004      this,
1005      getPerspective(),
1006      CHANGE_EDITOR_CLOSE);
1007    // Activate new part.
1008    if (partWasActive) {
1009      IWorkbenchPart top = activationList.getTopEditor();
1010      zoomOutIfNecessary(top);
1011      if (top == null) {
1012        // Fix for bug #31122 (side effect from fix 28031 above)
1013        actionSwitcher.updateTopEditor(null);
1014        if (lastActiveEditor == editor)
1015          lastActiveEditor = null;
1016        // End - Fix for bug #31122
1017        top = activationList.getActive();
1018      }
1019      if (top != null)
1020        activate(top);
1021      else
1022        setActivePart(null);
1023    } else if (partWasVisible) {
1024      IEditorPart top = activationList.getTopEditor();
1025      zoomOutIfNecessary(top);
1026
1027      // The editor we are bringing to top may already the visible
1028      // editor (due to editor manager behavior when it closes and
1029      // editor).
1030      // If this is the case, bringToTop will not call
1031      // firePartBroughtToTop.
1032      // We must fire it from here.
1033      if (top != null) {
1034        boolean isTop = editorMgr.getVisibleEditor() == top;
1035        bringToTop(top);
1036        if (isTop)
1037          firePartBroughtToTop(top);
1038      } else
1039        actionSwitcher.updateTopEditor(top);
1040    }
1041
1042    // Return true on success.
1043    return true;
1044  }
1045  /**
1046   * Closes the specified perspective. If last perspective, then entire page
1047   * is closed.
1048   * 
1049   * @param desc
1050   *            the descriptor of the perspective to be closed
1051   * @param save
1052   *            whether the page's editors should be save if last perspective
1053   */
1054  /* package */
1055  void closePerspective(IPerspectiveDescriptor desc, boolean save) {
1056    Perspective persp = findPerspective(desc);
1057    if (persp != null)
1058      closePerspective(persp, save, true);
1059  }
1060
1061  /**
1062   * Closes the specified perspective. If last perspective, then entire page
1063   * is closed.
1064   * 
1065   * @param persp
1066   *            the perspective to be closed
1067   * @param save
1068   *            whether the page's editors should be save if last perspective
1069   */
1070  /* package */
1071  void closePerspective(Perspective persp, boolean save, boolean closePage) {
1072
1073    // Always unzoom
1074    if (isZoomed())
1075      zoomOut();
1076
1077    // Close all editors on last perspective close
1078    if (perspList.size() == 1 && getEditorManager().getEditorCount() > 0) {
1079      // Close all editors
1080      if (!closeAllEditors(save))
1081        return;
1082    }
1083
1084    // Dispose of the perspective
1085    boolean isActive = (perspList.getActive() == persp);
1086    window.removePerspectiveShortcut(persp.getDesc(), this);
1087    if (isActive)
1088      setPerspective(perspList.getNextActive());
1089    disposePerspective(persp);
1090    if (closePage && perspList.size() == 0)
1091      close();
1092  }
1093
1094  /**
1095   * Closes all perspectives in the page. The page is kept so as not to lose
1096   * the input.
1097   * 
1098   * @param save
1099   *            whether the page's editors should be saved
1100   */
1101  /* package */
1102  void closeAllPerspectives() {
1103
1104    if (perspList.isEmpty())
1105      return;
1106
1107    // Always unzoom
1108    if (isZoomed())
1109      zoomOut();
1110
1111    // Close all editors
1112    if (!closeAllEditors(true))
1113      return;
1114
1115    // Deactivate the active perspective and part
1116    setPerspective((Perspective) null);
1117
1118    // Close each perspective in turn
1119    PerspectiveList oldList = perspList;
1120    perspList = new PerspectiveList();
1121    Iterator enum = oldList.iterator();
1122    while (enum.hasNext())
1123      closePerspective((Perspective) enum.next(), false, false);
1124    close();
1125  }
1126  /**
1127   * Creates the client composite.
1128   */
1129  private void createClientComposite() {
1130    final Composite parent = window.getPageComposite();
1131    composite = new Composite(parent, SWT.NONE);
1132    composite.setVisible(false); // Make visible on activate.
1133    composite.setBounds(parent.getClientArea());
1134    resizeListener = new ControlAdapter() {
1135      public void controlResized(ControlEvent e) {
1136        composite.setBounds(parent.getClientArea());
1137      }
1138    };
1139    parent.addControlListener(resizeListener);
1140  }
1141  /**
1142   * Creates a new view set. Return null on failure.
1143   */
1144  private Perspective createPerspective(PerspectiveDescriptor desc) {
1145    String label = desc.getId();
1146    try {
1147      UIStats.start(UIStats.CREATE_PERSPECTIVE, label);
1148      Perspective persp = new Perspective(desc, this);
1149      perspList.add(persp);
1150      window.firePerspectiveOpened(this, desc);
1151      IViewReference refs[] = persp.getViewReferences();
1152      for (int i = 0; i < refs.length; i++) {
1153        IViewReference ref = refs[i];
1154        if (ref != null)
1155          addPart(ref);
1156      }
1157      return persp;
1158    } catch (WorkbenchException e) {
1159      if (!((Workbench) window.getWorkbench()).isStarting()) {
1160        MessageDialog.openError(window.getShell(), WorkbenchMessages.getString("Error"), //$NON-NLS-1$
1161        WorkbenchMessages.format("Workbench.showPerspectiveError", new String[] { desc.getId()})); //$NON-NLS-1$
1162      }
1163      return null;
1164    } finally {
1165      UIStats.end(UIStats.CREATE_PERSPECTIVE, label);
1166    }
1167  }
1168  /**
1169   * Open the tracker to allow the user to move the specified part using
1170   * keyboard.
1171   */
1172  public void openTracker(ViewPane pane) {
1173    Perspective persp = getActivePerspective();
1174    if (persp != null)
1175      persp.openTracker(pane);
1176  }
1177  /**
1178   * Add a part to the activation list.
1179   */
1180  protected void addPart(IWorkbenchPartReference ref) {
1181    activationList.add(ref);
1182  }
1183  /**
1184   * Remove a part from the activation list.
1185   */
1186  protected void removePart(IWorkbenchPartReference ref) {
1187    activationList.remove(ref);
1188  }
1189  /**
1190   * Deactivates a part. The pane is unhilighted.
1191   */
1192  private void deactivatePart(IWorkbenchPart part) {
1193    if (part != null) {
1194      PartSite site = (PartSite) part.getSite();
1195      site.getPane().showFocus(false);
1196    }
1197  }
1198  private void disposePart(IWorkbenchPartReference ref) {
1199    final WorkbenchPartReference ref0 = (WorkbenchPartReference) ref;
1200    Platform.run(new SafeRunnable() {
1201      public void run() {
1202        ref0.dispose();
1203      }
1204      public void handleException(Throwable e) {
1205        //Exception has already being logged by Core. Do nothing.
1206      }
1207    });
1208  }
1209  /**
1210   * Cleanup.
1211   */
1212  public void dispose() {
1213
1214    // Always unzoom
1215    if (isZoomed())
1216      zoomOut();
1217
1218    // Close and dispose the editors.
1219    closeAllEditors(false);
1220
1221    // Capture views.
1222    IViewReference refs[] = viewFactory.getViews();
1223
1224    // Get rid of perspectives. This will close the views.
1225    Iterator enum = perspList.iterator();
1226    while (enum.hasNext()) {
1227      Perspective perspective = (Perspective) enum.next();
1228      window.removePerspectiveShortcut(perspective.getDesc(), this);
1229      window.firePerspectiveClosed(this, perspective.getDesc());
1230      perspective.dispose();
1231    }
1232    perspList = new PerspectiveList();
1233
1234    // Dispose views.
1235    final int errors[] = { 0 };
1236    for (int i = 0; i < refs.length; i++) {
1237      final WorkbenchPartReference ref = (WorkbenchPartReference) refs[i];
1238      firePartClosed(refs[i]);
1239      Platform.run(new SafeRunnable() {
1240        public void run() {
1241          ref.dispose();
1242        }
1243        public void handleException(Throwable e) {
1244          errors[0]++;
1245        }
1246      });
1247    }
1248    if (errors[0] > 0) {
1249      String message;
1250      if (errors[0] == 1)
1251        message = WorkbenchMessages.getString("WorkbenchPage.oneErrorClosingPage"); //$NON-NLS-1$
1252      else
1253        message = WorkbenchMessages.getString("WorkbenchPage.multipleErrorsClosingPage"); //$NON-NLS-1$
1254      MessageDialog.openError(null, WorkbenchMessages.getString("Error"), message); //$NON-NLS-1$
1255    }
1256    activePart = null;
1257    activationList = new ActivationList();
1258
1259    // Get rid of editor presentation.
1260    editorPresentation.dispose();
1261
1262    // Get rid of composite.
1263    window.getPageComposite().removeControlListener(resizeListener);
1264    composite.dispose();
1265
1266    navigationHistory.dispose();
1267    
1268    stickyPerspectives.clear();
1269  }
1270  /**
1271   * Dispose a perspective.
1272   */
1273  private void disposePerspective(Perspective persp) {
1274    // Get views.
1275    IViewReference refs[] = persp.getViewReferences();
1276
1277    // Get rid of perspective.
1278    perspList.remove(persp);
1279    window.firePerspectiveClosed(this, persp.getDesc());
1280    persp.dispose();
1281
1282    // Loop through the views.
1283    for (int i = 0; i < refs.length; i++) {
1284      IViewReference ref = refs[i];
1285
1286      //If the part is no longer reference then dispose it.
1287      boolean exists = viewFactory.hasView(ref);
1288      if (!exists) {
1289        firePartClosed(ref);
1290        activationList.remove(ref);
1291        disposePart(ref);
1292      }
1293    }
1294    stickyPerspectives.remove(persp.getDesc());
1295  }
1296  /**
1297   * @return NavigationHistory
1298   */
1299  public INavigationHistory getNavigationHistory() {
1300    return navigationHistory;
1301  }
1302
1303  /**
1304   * Edits the action sets.
1305   */
1306  public boolean editActionSets() {
1307    Perspective persp = getActivePerspective();
1308    if (persp == null)
1309      return false;
1310
1311    // Create list dialog.
1312    CustomizePerspectiveDialog dlg =
1313      new CustomizePerspectiveDialog(window.getShell(), persp);
1314
1315    // Open.
1316    boolean ret = (dlg.open() == Window.OK);
1317    if (ret) {
1318      window.updateActionSets();
1319      window.firePerspectiveChanged(this, getPerspective(), CHANGE_RESET);
1320      window.firePerspectiveChanged(this, getPerspective(), CHANGE_RESET_COMPLETE);
1321    }
1322    return ret;
1323  }
1324  /**
1325   * Returns the first view manager with given ID.
1326   */
1327  public Perspective findPerspective(IPerspectiveDescriptor desc) {
1328    Iterator enum = perspList.iterator();
1329    while (enum.hasNext()) {
1330      Perspective mgr = (Perspective) enum.next();
1331      if (desc.getId().equals(mgr.getDesc().getId()))
1332        return mgr;
1333    }
1334    return null;
1335  }
1336  /**
1337   * See IWorkbenchPage@findView.
1338   */
1339  public IViewPart findView(String id) {
1340    IViewReference ref = findViewReference(id);
1341    if (ref == null)
1342      return null;
1343    return ref.getView(true);
1344  }
1345  
1346  /* (non-Javadoc)
1347   * @see org.eclipse.ui.IWorkbenchPage
1348   */
1349  public IViewReference findViewReference(String viewId) {
1350      return findViewReference(viewId, null);
1351  }
1352
1353  /* (non-Javadoc)
1354   * @see org.eclipse.ui.IWorkbenchPage
1355   */
1356  public IViewReference findViewReference(String viewId, String secondaryId) {
1357    Perspective persp = getActivePerspective();
1358    if (persp == null)
1359      return null;
1360    return persp.findView(viewId, secondaryId);
1361  }
1362
1363  /**
1364   * Fire part activation out.
1365   */
1366  private void firePartActivated(IWorkbenchPart part) {
1367    String label = "activate::" + (part != null ? part.getTitle() : "none"); //$NON-NLS-1$ //$NON-NLS-2$
1368    try {
1369      UIStats.start(UIStats.NOTIFY_PART_LISTENERS, label);
1370      partListeners.firePartActivated(part);
1371      partListeners2.firePartActivated(getReference(part));
1372      selectionService.partActivated(part);
1373    } finally {
1374      UIStats.end(UIStats.NOTIFY_PART_LISTENERS, label);
1375    }
1376  }
1377  /**
1378   * Fire part brought to top out.
1379   */
1380  private void firePartBroughtToTop(IWorkbenchPart part) {
1381    String label = "bringToTop::" + (part != null ? part.getTitle() : "none"); //$NON-NLS-1$ //$NON-NLS-2$
1382    try {
1383      UIStats.start(UIStats.NOTIFY_PART_LISTENERS, label);
1384      partListeners.firePartBroughtToTop(part);
1385      partListeners2.firePartBroughtToTop(getReference(part));
1386      selectionService.partBroughtToTop(part);
1387    } finally {
1388      UIStats.end(UIStats.NOTIFY_PART_LISTENERS, label);
1389    }
1390  }
1391  /**
1392   * Fire part close out.
1393   */
1394  private void firePartClosed(IWorkbenchPartReference ref) {
1395    String label = "close" + ref.getTitle(); //$NON-NLS-1$
1396    try {
1397      UIStats.start(UIStats.NOTIFY_PART_LISTENERS, label);
1398      IWorkbenchPart part = ref.getPart(false);
1399      if (part != null) {
1400        partListeners.firePartClosed(part);
1401        selectionService.partClosed(part);
1402      }
1403      partListeners2.firePartClosed(ref);
1404    } finally {
1405      UIStats.end(UIStats.NOTIFY_PART_LISTENERS, label);
1406    }
1407  }
1408  /**
1409   * Fire part deactivation out.
1410   */
1411  private void firePartDeactivated(IWorkbenchPart part) {
1412    String label = "deactivate" + (part != null ? part.getTitle() : "none"); //$NON-NLS-1$ //$NON-NLS-2$
1413    try {
1414      UIStats.start(UIStats.NOTIFY_PART_LISTENERS, label);
1415      partListeners.firePartDeactivated(part);
1416      partListeners2.firePartDeactivated(getReference(part));
1417      selectionService.partDeactivated(part);
1418    } finally {
1419      UIStats.end(UIStats.NOTIFY_PART_LISTENERS, label);
1420    }
1421  }
1422  /**
1423   * Fire part open out.
1424   */
1425  public void firePartOpened(IWorkbenchPart part) {
1426    String label = "opened" + (part != null ? part.getTitle() : "none"); //$NON-NLS-1$ //$NON-NLS-2$
1427    try {
1428      UIStats.start(UIStats.NOTIFY_PART_LISTENERS, label);
1429      partListeners.firePartOpened(part);
1430      partListeners2.firePartOpened(getReference(part));
1431      selectionService.partOpened(part);
1432    } finally {
1433      UIStats.end(UIStats.NOTIFY_PART_LISTENERS, label);
1434    }
1435  }
1436  /**
1437   * Fire part input changed out.
1438   */
1439  private void firePartInputChanged(IWorkbenchPart part) {
1440    String label = "inputChanged" + (part != null ? part.getTitle() : "none"); //$NON-NLS-1$ //$NON-NLS-2$
1441    try {
1442      UIStats.start(UIStats.NOTIFY_PART_LISTENERS, label);
1443      partListeners2.firePartInputChanged(getReference(part));
1444      selectionService.partInputChanged(part);
1445    } finally {
1446      UIStats.end(UIStats.NOTIFY_PART_LISTENERS, label);
1447    }
1448  }
1449  /**
1450   * Notify property change listeners about a property change.
1451   * 
1452   * @param changeId
1453   *            the change id
1454   * @param oldValue
1455   *            old property value
1456   * @param newValue
1457   *            new property value
1458   */
1459  private void firePropertyChange(
1460    String changeId,
1461    Object oldValue,
1462    Object newValue) {
1463    Object[] listeners = propertyChangeListeners.getListeners();
1464    PropertyChangeEvent event =
1465      new PropertyChangeEvent(this, changeId, oldValue, newValue);
1466
1467    for (int i = 0; i < listeners.length; i++) {
1468      ((IPropertyChangeListener) listeners[i]).propertyChange(event);
1469    }
1470  }
1471  /*
1472   * Returns the action bars.
1473   */
1474  public IActionBars getActionBars() {
1475    if (actionBars == null)
1476      actionBars = new WWinActionBars(window);
1477    return actionBars;
1478  }
1479  /**
1480   * Returns an array of the visible action sets.
1481   */
1482  public IActionSetDescriptor[] getActionSets() {
1483    Perspective persp = getActivePerspective();
1484    if (persp != null)
1485      return persp.getActionSets();
1486    else
1487      return new IActionSetDescriptor[0];
1488  }
1489  
1490  /**
1491   * @see IWorkbenchPage
1492   */
1493  public IEditorPart getActiveEditor() {
1494    return getEditorManager().getVisibleEditor();
1495  }
1496  /*
1497   * (non-Javadoc) Method declared on IPartService
1498   */
1499  public IWorkbenchPart getActivePart() {
1500    return activePart;
1501  }
1502  /*
1503   * (non-Javadoc) Method declared on IPartService
1504   */
1505  public IWorkbenchPartReference getActivePartReference() {
1506    return getReference(activePart);
1507  }
1508  /**
1509   * Returns the active perspective for the page, <code>null</code> if
1510   * none.
1511   */
1512  public Perspective getActivePerspective() {
1513    return perspList.getActive();
1514  }
1515  /**
1516   * Returns the client composite.
1517   */
1518  public Composite getClientComposite() {
1519    return composite;
1520  }
1521  /**
1522   * Answer the editor manager for this window.
1523   */
1524// for dynamic UI - change access from private to protected
1525  protected EditorManager getEditorManager() {
1526    return editorMgr;
1527  }
1528  /**
1529   * Answer the perspective presentation.
1530   */
1531  public PerspectiveHelper getPerspectivePresentation() {
1532    if (getActivePerspective() != null)
1533      return getActivePerspective().getPresentation();
1534    return null;
1535  }
1536  /**
1537   * Answer the editor presentation.
1538   */
1539  public EditorAreaHelper getEditorPresentation() {
1540    return editorPresentation;
1541  }
1542  /**
1543   * See IWorkbenchPage.
1544   */
1545  public IEditorPart[] getEditors() {
1546    final IEditorReference refs[] = getEditorReferences();
1547    final ArrayList result = new ArrayList(refs.length);
1548    Display d = getWorkbenchWindow().getShell().getDisplay();
1549    //Must be backward compatible.
1550    d.syncExec(new Runnable() {
1551      public void run() {
1552        for (int i = 0; i < refs.length; i++) {
1553          IWorkbenchPart part = refs[i].getPart(true);
1554          if (part != null)
1555            result.add(part);
1556        }
1557      }
1558    });
1559    final IEditorPart editors[] = new IEditorPart[result.size()];
1560    return (IEditorPart[]) result.toArray(editors);
1561  }
1562
1563  public IEditorPart[] getDirtyEditors() {
1564    return getEditorManager().getDirtyEditors();
1565  }
1566  public IEditorPart findEditor(IEditorInput input) {
1567    return getEditorManager().findEditor(input);
1568  }
1569  /**
1570   * See IWorkbenchPage.
1571   */
1572  public IEditorReference[] getEditorReferences() {
1573    return getEditorManager().getEditors();
1574  }
1575  /**
1576   * Returns the docked views.
1577   */
1578  public IViewReference[] getFastViews() {
1579    Perspective persp = getActivePerspective();
1580    if (persp != null)
1581      return persp.getFastViews();
1582    else
1583      return new IViewReference[0];
1584  }
1585  /**
1586   * @see IWorkbenchPage
1587   */
1588  public IAdaptable getInput() {
1589    return input;
1590  }
1591  /**
1592   * Returns the page label. This is a combination of the page input and
1593   * active perspective.
1594   */
1595  public String getLabel() {
1596    String label = WorkbenchMessages.getString("WorkbenchPage.UnknownLabel"); //$NON-NLS-1$
1597    if (input != null) {
1598      IWorkbenchAdapter adapter =
1599        (IWorkbenchAdapter) input.getAdapter(IWorkbenchAdapter.class);
1600      if (adapter != null)
1601        label = adapter.getLabel(input);
1602    }
1603    Perspective persp = getActivePerspective();
1604    if (persp != null)
1605      label = WorkbenchMessages.format("WorkbenchPage.PerspectiveFormat", new Object[] { label, persp.getDesc().getLabel()}); //$NON-NLS-1$
1606    else if (deferredActivePersp != null)
1607      label = WorkbenchMessages.format("WorkbenchPage.PerspectiveFormat", new Object[] { label, deferredActivePersp.getLabel()}); //$NON-NLS-1$  
1608    return label;
1609  }
1610  /**
1611   * Returns the new wizard actions the page. This is List of Strings.
1612   */
1613  public ArrayList getNewWizardActionIds() {
1614    Perspective persp = getActivePerspective();
1615    if (persp != null)
1616      return persp.getNewWizardActionIds();
1617    else
1618      return new ArrayList();
1619  }
1620  /**
1621   * Returns the perspective.
1622   */
1623  public IPerspectiveDescriptor getPerspective() {
1624    if (deferredActivePersp != null)
1625      return deferredActivePersp;
1626    Perspective persp = getActivePerspective();
1627    if (persp != null)
1628      return persp.getDesc();
1629    else
1630      return null;
1631  }
1632  /**
1633   * Returns the perspective actions for this page. This is List of Strings.
1634   */
1635  public ArrayList getPerspectiveActionIds() {
1636    Perspective persp = getActivePerspective();
1637    if (persp != null)
1638      return persp.getPerspectiveActionIds();
1639    else
1640      return new ArrayList();
1641  }
1642  /*
1643   * (non-Javadoc) Method declared on ISelectionService
1644   */
1645  public ISelection getSelection() {
1646    return selectionService.getSelection();
1647  }
1648
1649  /*
1650   * (non-Javadoc) Method declared on ISelectionService
1651   */
1652  public ISelection getSelection(String partId) {
1653    return selectionService.getSelection(partId);
1654  }
1655
1656  /**
1657   * Returns the ids of the parts to list in the Show In... prompter. This is
1658   * a List of Strings.
1659   */
1660  public ArrayList getShowInPartIds() {
1661    Perspective persp = getActivePerspective();
1662    if (persp != null)
1663      return persp.getShowInPartIds();
1664    else
1665      return new ArrayList();
1666  }
1667
1668  /**
1669   * The user successfully performed a Show In... action on the specified
1670   * part. Update the list of Show In items accordingly.
1671   */
1672  public void performedShowIn(String partId) {
1673    Perspective persp = getActivePerspective();
1674    if (persp != null) {
1675      persp.performedShowIn(partId);
1676    }
1677  }
1678
1679  /**
1680   * Sorts the given collection of show in target part ids in MRU order.
1681   */
1682  public void sortShowInPartIds(ArrayList partIds) {
1683    final Perspective persp = getActivePerspective();
1684    if (persp != null) {
1685      Collections.sort(partIds, new Comparator() {
1686        public int compare(Object a, Object b) {
1687          long ta = persp.getShowInTime((String) a);
1688          long tb = persp.getShowInTime((String) b);
1689          return (ta == tb) ? 0 : ((ta > tb) ? -1 : 1);
1690        }
1691      });
1692    }
1693  }
1694
1695  /**
1696   * Returns the show view actions the page. This is a List of Strings.
1697   */
1698  public ArrayList getShowViewActionIds() {
1699    Perspective persp = getActivePerspective();
1700    if (persp != null)
1701      return persp.getShowViewActionIds();
1702    else
1703      return new ArrayList();
1704  }
1705  /**
1706   * Returns the unprotected window.
1707   */
1708  protected WorkbenchWindow getUnprotectedWindow() {
1709    return window;
1710  }
1711  /*
1712   * Returns the view factory.
1713   */
1714  public ViewFactory getViewFactory() {
1715    if (viewFactory == null) {
1716      viewFactory =
1717        new ViewFactory(
1718          this,
1719          WorkbenchPlugin.getDefault().getViewRegistry());
1720    }
1721    return viewFactory;
1722  }
1723
1724  /**
1725   * Returns all parts that are owned by this page
1726   * 
1727   * @return
1728   */
1729  IWorkbenchPartReference[] getAllParts() {
1730    IViewReference[] views = viewFactory.getViews();
1731    IEditorReference[] editors = getEditorReferences();
1732    
1733    IWorkbenchPartReference[] result = new IWorkbenchPartReference[views.length + editors.length];
1734    int resultIdx = 0;
1735    
1736    for (int i = 0; i < views.length; i++) {
1737      result[resultIdx++] = views[i];
1738    }
1739    
1740    for (int i = 0; i < editors.length; i++) {
1741      result[resultIdx++] = editors[i];
1742    }
1743    
1744    return result;
1745  }
1746  
1747  /**
1748   * Returns all open parts that are owned by this page (that is, all parts
1749   * for which a part opened event would have been sent -- these would be
1750   * activated parts whose controls have already been created.
1751   */
1752  IWorkbenchPartReference[] getOpenParts() {
1753    IWorkbenchPartReference[] refs = getAllParts();
1754    List result = new ArrayList();
1755    
1756    for (int i = 0; i < refs.length; i++) {
1757      IWorkbenchPartReference reference = refs[i];
1758      
1759      IWorkbenchPart part = reference.getPart(false);
1760      if (part != null) {
1761        result.add(reference);
1762      }
1763    }
1764    
1765    return (IWorkbenchPartReference[]) result.toArray(new IWorkbenchPartReference[result.size()]);
1766  }
1767  
1768  /**
1769   * See IWorkbenchPage.
1770   */
1771  public IViewReference[] getViewReferences() {
1772    Perspective persp = getActivePerspective();
1773    if (persp != null)
1774      return persp.getViewReferences();
1775    else
1776      return new IViewReference[0];
1777  }
1778  /**
1779   * See IWorkbenchPage.
1780   */
1781  public IViewPart[] getViews() {
1782    Perspective persp = getActivePerspective();
1783    if (persp != null) {
1784      IViewReference refs[] = persp.getViewReferences();
1785      ArrayList parts = new ArrayList(refs.length);
1786      for (int i = 0; i < refs.length; i++) {
1787        IWorkbenchPart part = refs[i].getPart(true);
1788        if (part != null)
1789          parts.add(part);
1790      }
1791      IViewPart[] result = new IViewPart[parts.size()];
1792      return (IViewPart[]) parts.toArray(result);
1793    }
1794    return new IViewPart[0];
1795  }
1796  /**
1797   * See IWorkbenchPage.
1798   */
1799  public IWorkbenchWindow getWorkbenchWindow() {
1800    return window;
1801  }
1802  /**
1803   * Implements IWorkbenchPage
1804   * 
1805   * @see org.eclipse.ui.IWorkbenchPage#getWorkingSet()
1806   * @since 2.0
1807   * @deprecated individual views should store a working set if needed
1808   */
1809  public IWorkingSet getWorkingSet() {
1810    return workingSet;
1811  }
1812
1813  /**
1814   * @see IWorkbenchPage
1815   */
1816  public void hideActionSet(String actionSetID) {
1817    Perspective persp = getActivePerspective();
1818    if (persp != null) {
1819      persp.hideActionSet(actionSetID);
1820      window.updateActionSets();
1821      window.firePerspectiveChanged(
1822        this,
1823        getPerspective(),
1824        CHANGE_ACTION_SET_HIDE);
1825    }
1826  }
1827
1828  /* (non-Javadoc)
1829   * @see org.eclipse.ui.IWorkbenchPage#hideView(org.eclipse.ui.IViewReference)
1830   */
1831  public void hideView(IViewReference ref) {
1832    if (ref == null)
1833      return;
1834    IWorkbenchPart part = ref.getPart(false);
1835    if (part != null) {
1836      hideView((IViewPart) part);
1837    } else {
1838      hideView(getActivePerspective(), ref);
1839    }    
1840  }
1841  
1842  /* package */ void refreshActiveView() {
1843    IWorkbenchPart nextActive = activationList.getActive();
1844    
1845    if (nextActive != activePart) {
1846      if (nextActive != null) {
1847        activate(nextActive);
1848      } else {
1849        setActivePart(null);
1850      }
1851    }
1852  }
1853  
1854  /**
1855   * See IPerspective
1856   */
1857  public void hideView(IViewPart view) {
1858    // Sanity check.
1859    Perspective persp = getActivePerspective();
1860    if (persp == null || !certifyPart(view))
1861      return;
1862
1863    // If part is added / removed always unzoom.
1864    IViewReference ref = (IViewReference) getReference(view);
1865    if (isZoomed() && !isFastView(ref))
1866      zoomOut();
1867
1868    // Confirm.
1869    if (!persp.canCloseView(view))
1870      return;
1871
1872    // Activate new part.
1873    if (view == activePart) {
1874      IWorkbenchPart prevActive = activationList.getPreviouslyActive();
1875      if (prevActive != null)
1876        activate(prevActive);
1877      else
1878        setActivePart(null);
1879    }
1880
1881    hideView(persp, ref);
1882
1883  }
1884  private void hideView(Perspective persp, IViewReference ref) {
1885    // Notify interested listeners before the hide
1886    window.firePerspectiveChanged(this, getPerspective(), ref, CHANGE_VIEW_HIDE);
1887
1888    // Hide the part.
1889    persp.hideView(ref);
1890
1891    // If the part is no longer reference then dispose it.
1892    boolean exists = viewFactory.hasView(ref);
1893    if (!exists) {
1894      firePartClosed(ref);
1895      disposePart(ref);
1896      activationList.remove(ref);
1897
1898      /*
1899       * Bug 42684. A ViewPane instance has been disposed, but an attempt
1900       * is then made to remove focus from it. This happens because the
1901       * ViewPane is still viewed as the active part. The activePart
1902       * should always be modified when the view is changed. activePart
1903       * isn't really needed anymore (see declaration).
1904       */
1905      activePart = activationList.getActive();
1906    }
1907
1908    // Notify interested listeners after the hide
1909    window.firePerspectiveChanged(this, getPerspective(), CHANGE_VIEW_HIDE);
1910
1911    // Just in case view was fast.
1912    window.updateFastViewBar();
1913  }
1914
1915  /**
1916   * Initialize the page.
1917   * 
1918   * @param w
1919   *            the parent window
1920   * @param layoutID
1921   *            may be <code>null</code> if restoring from file
1922   * @param input
1923   *            the page input
1924   */
1925  private void init(WorkbenchWindow w, String layoutID, IAdaptable input)
1926    throws WorkbenchException {
1927    // Save args.
1928    this.window = w;
1929    this.input = input;
1930
1931    // Create presentation.
1932    createClientComposite();
1933    editorPresentation = new EditorAreaHelper(this);
1934    editorMgr = new EditorManager(window, this, editorPresentation);
1935
1936    // Get perspective descriptor.
1937    if (layoutID != null) {
1938      PerspectiveDescriptor desc =
1939        (PerspectiveDescriptor) WorkbenchPlugin
1940          .getDefault()
1941          .getPerspectiveRegistry()
1942          .findPerspectiveWithId(layoutID);
1943      if (desc == null)
1944        throw new WorkbenchException(WorkbenchMessages.getString("WorkbenchPage.ErrorRecreatingPerspective")); //$NON-NLS-1$
1945      Perspective persp = createPerspective(desc);
1946      if (persp == null)
1947        return;
1948      perspList.setActive(persp);
1949      window.firePerspectiveActivated(this, desc);
1950    }
1951  }
1952  /**
1953   * See IWorkbenchPage.
1954   */
1955  public boolean isPartVisible(IWorkbenchPart part) {
1956    return ((PartSite) part.getSite()).getPane().isVisible();
1957  }
1958  /**
1959   * See IWorkbenchPage.
1960   */
1961  public boolean isEditorAreaVisible() {
1962    Perspective persp = getActivePerspective();
1963    if (persp == null)
1964      return false;
1965    return persp.isEditorAreaVisible();
1966  }
1967  /**
1968   * Returns whether the view is fast.
1969   */
1970  public boolean isFastView(IViewReference ref) {
1971    Perspective persp = getActivePerspective();
1972    if (persp != null)
1973      return persp.isFastView(ref);
1974    else
1975      return false;
1976  }
1977  /**
1978   * Returns whether the layout of the active
1979   * perspective is fixed.
1980   */
1981  public boolean isFixedLayout() {
1982    Perspective persp = getActivePerspective();
1983    if (persp != null)
1984      return persp.isFixedLayout();
1985    else
1986      return false;
1987  }
1988
1989  /**
1990   * Return the active fast view or null if there are no fast views or if
1991   * there are all minimized.
1992   */
1993  public IViewReference getActiveFastView() {
1994    Perspective persp = getActivePerspective();
1995    if (persp != null)
1996      return persp.getActiveFastView();
1997    else
1998      return null;
1999  }
2000  /**
2001   * Return true if the perspective has a dirty editor.
2002   */
2003  protected boolean isSaveNeeded() {
2004    return getEditorManager().isSaveAllNeeded();
2005  }
2006  /**
2007   * Returns whether the page is zoomed.
2008   */
2009  public boolean isZoomed() {
2010    Perspective persp = getActivePerspective();
2011    if (persp == null)
2012      return false;
2013    if (persp.getPresentation() == null)
2014      return false;
2015    return persp.getPresentation().isZoomed();
2016  }
2017  /**
2018   * Returns <code>true</code> if the window needs to unzoom for the given
2019   * IWorkbenchPart to be seen by the user. Returns false otherwise.
2020   * 
2021   * @param part
2022   *            the part whose visibility is to be determined
2023   * @return <code>true</code> if the window needs to unzoom for the given
2024   *         IWorkbenchPart to be seen by the user, <code>false</code>
2025   *         otherwise.
2026   */
2027  private boolean needToZoomOut(IWorkbenchPart part) {
2028    // part is an editor
2029    if (part instanceof IEditorPart) {
2030      if (getActivePart() instanceof IViewPart) {
2031        return true;
2032      }
2033      EditorSite site = (EditorSite) part.getSite();
2034      EditorPane pane = (EditorPane) site.getPane();
2035      EditorStack book = pane.getWorkbook();
2036      return !book.equals(book.getEditorArea().getActiveWorkbook());
2037    }
2038    // part is a view
2039    if (part instanceof IViewPart) {
2040      if (isFastView((IViewReference) getReference(part))
2041        || part.equals(getActivePart()))
2042        return false;
2043      else
2044        return true;
2045    }
2046
2047    return true;
2048  }
2049  /**
2050   * This method is called when the page is activated.
2051   */
2052  protected void onActivate() {
2053    Iterator enum = perspList.iterator();
2054    while (enum.hasNext()) {
2055      Perspective perspective = (Perspective) enum.next();
2056      window.addPerspectiveShortcut(perspective.getDesc(), this);
2057    }
2058    composite.setVisible(true);
2059    Perspective persp = getActivePerspective();
2060
2061    if (persp != null) {
2062      window.selectPerspectiveShortcut(persp.getDesc(), this, true);
2063      persp.onActivate();
2064      updateVisibility(null, persp);
2065    }
2066    if (activePart == null && persp != null) {
2067      IViewReference refs[] = persp.getViewReferences();
2068      for (int i = 0; i < refs.length; i++) {
2069        IViewReference ref = refs[i];
2070        if (ref != null) {
2071          activePart = ref.getPart(false);
2072          if (activePart != null)
2073            break;
2074        }
2075      }
2076    }
2077    if (activePart != null) {
2078      activationList.setActive(activePart);
2079
2080      activatePart(activePart);
2081      actionSwitcher.updateActivePart(activePart);
2082      if (activePart instanceof IEditorPart) {
2083        lastActiveEditor = (IEditorPart) activePart;
2084        actionSwitcher.updateTopEditor((IEditorPart) activePart);
2085      } else {
2086        IEditorPart editor = editorMgr.getVisibleEditor();
2087        if (editor != null) {
2088          actionSwitcher.updateTopEditor(editor);
2089
2090          // inform the site's action bars of the current editor
2091          // (important that this occur during page opening).
2092          PartSite site = (PartSite) editor.getSite();
2093          SubActionBars bars = (SubActionBars) site.getActionBars();
2094          bars.partChanged(editor);
2095        }
2096      }
2097      firePartActivated(activePart);
2098    } else {
2099      composite.setFocus();
2100    }
2101  }
2102  /**
2103   * This method is called when the page is deactivated.
2104   */
2105  protected void onDeactivate() {
2106    if (activePart != null) {
2107      deactivatePart(activePart);
2108      actionSwitcher.updateActivePart(null);
2109      firePartDeactivated(activePart);
2110    }
2111    actionSwitcher.updateTopEditor(null);
2112    lastActiveEditor = null;
2113    if (getActivePerspective() != null)
2114      getActivePerspective().onDeactivate();
2115    composite.setVisible(false);
2116    Iterator enum = perspList.iterator();
2117    while (enum.hasNext()) {
2118      Perspective perspective = (Perspective) enum.next();
2119      window.removePerspectiveShortcut(perspective.getDesc(), this);
2120    }
2121  }
2122  /**
2123   * See IWorkbenchPage.
2124   */
2125  public void reuseEditor(IReusableEditor editor, IEditorInput input) {
2126    editor.setInput(input);
2127    firePartInputChanged(editor);
2128  }
2129  /**
2130   * See IWorkbenchPage.
2131   */
2132  public IEditorPart openEditor(IEditorInput input, String editorID)
2133    throws PartInitException {
2134    return openEditor(input, editorID, true);
2135  }
2136  /**
2137   * See IWorkbenchPage.
2138   */
2139  public IEditorPart openEditor(
2140    final IEditorInput input,
2141    final String editorID,
2142    final boolean activate)
2143    throws PartInitException {
2144    if (input == null || editorID == null) {
2145      throw new IllegalArgumentException();
2146    }
2147
2148    final IEditorPart result[] = new IEditorPart[1];
2149    final PartInitException ex[] = new PartInitException[1];
2150    BusyIndicator
2151      .showWhile(
2152        window.getWorkbench().getDisplay(),
2153        new Runnable() {
2154      public void run() {
2155        try {
2156          result[0] = busyOpenEditor(input, editorID, activate);
2157        } catch (PartInitException e) {
2158          ex[0] = e;
2159        }
2160      }
2161    });
2162    if (ex[0] != null)
2163      throw ex[0];
2164    return result[0];
2165  }
2166  /**
2167     * See IWorkbenchPage.openEditor
2168     */
2169    private IEditorPart busyOpenEditor(IEditorInput input, String editorID,
2170            boolean activate) throws PartInitException {
2171
2172        final Workbench workbench = (Workbench) getWorkbenchWindow()
2173                .getWorkbench();
2174        workbench.largeUpdateStart();
2175
2176        try {
2177            return busyOpenEditorBatched(input, editorID, activate);
2178
2179        } finally {
2180            workbench.largeUpdateEnd();
2181        }
2182    }
2183
2184    /**
2185     * Do not call this method.  Use <code>busyOpenEditor</code>.
2186     * 
2187     * @see IWorkbenchPage#openEditor(IEditorInput, String, boolean)
2188     */
2189    private IEditorPart busyOpenEditorBatched(IEditorInput input,
2190            String editorID, boolean activate) throws PartInitException {
2191            
2192    // If an editor already exists for the input use it.
2193    IEditorPart editor = getEditorManager().findEditor(input);
2194    if (editor != null) {
2195      if (IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID.equals(editorID)) {
2196        if (editor.isDirty()) {
2197            MessageDialog dialog = new MessageDialog(getWorkbenchWindow().getShell(), WorkbenchMessages.getString("Save"), //$NON-NLS-1$
2198    null, // accept the default window icon
2199  WorkbenchMessages.format("WorkbenchPage.editorAlreadyOpenedMsg", new String[] { input.getName()}), //$NON-NLS-1$
2200          MessageDialog.QUESTION,
2201            new String[] {
2202              IDialogConstants.YES_LABEL,
2203              IDialogConstants.NO_LABEL,
2204              IDialogConstants.CANCEL_LABEL },
2205            0);
2206          int saveFile = dialog.open();
2207          if (saveFile == 0) {
2208            try {
2209              final IEditorPart editorToSave = editor;
2210              getWorkbenchWindow()
2211                .run(false, false, new IRunnableWithProgress() {
2212                public void run(IProgressMonitor monitor)
2213                  throws
2214                    InvocationTargetException,
2215                    InterruptedException {
2216                  editorToSave.doSave(monitor);
2217                }
2218              });
2219            } catch (InvocationTargetException e) {
2220              throw (RuntimeException) e.getTargetException();
2221            } catch (InterruptedException e) {
2222              return null;
2223            }
2224          } else if (saveFile == 2) {
2225            return null;
2226          }
2227        }
2228      } else {
2229        showEditor(activate, editor);
2230        return editor;
2231      }
2232    }
2233
2234    // Disabled turning redraw off, because it causes setFocus
2235    // in activate(editor) to fail.
2236    // getClientComposite().setRedraw(false);
2237
2238    // Remember the old visible editor
2239    IEditorPart oldVisibleEditor = getEditorManager().getVisibleEditor();
2240
2241    // Otherwise, create a new one. This may cause the new editor to
2242    // become the visible (i.e top) editor.
2243    IEditorReference ref = null;
2244    ref = getEditorManager().openEditor(editorID, input, true);
2245    if (ref != null) {
2246      editor = ref.getEditor(true);
2247      addPart(ref);
2248    }
2249
2250    if (editor != null) {
2251      //firePartOpened(editor);
2252      zoomOutIfNecessary(editor);
2253      setEditorAreaVisible(true);
2254      if (activate) {
2255        if (editor instanceof MultiEditor)
2256          activate(((MultiEditor) editor).getActiveEditor());
2257        else
2258          activate(editor);
2259      } else {
2260        activationList.setActive(editor);
2261        if (activePart != null) {
2262          // ensure the activation list is in a valid state
2263          activationList.setActive(activePart);
2264        }
2265        // The previous openEditor call may create a new editor
2266        // and make it visible, so send the notification.
2267        IEditorPart visibleEditor =
2268          getEditorManager().getVisibleEditor();
2269        if ((visibleEditor == editor)
2270          && (oldVisibleEditor != editor)) {
2271          actionSwitcher.updateTopEditor(editor);
2272          firePartBroughtToTop(editor);
2273        } else {
2274          bringToTop(editor);
2275        }
2276      }
2277      window.firePerspectiveChanged(
2278          this,
2279          getPerspective(),
2280          ref,
2281          CHANGE_EDITOR_OPEN);
2282      window.firePerspectiveChanged(
2283        this,
2284        getPerspective(),
2285        CHANGE_EDITOR_OPEN);
2286    }
2287
2288    //  getClientComposite().setRedraw(true);
2289
2290    return editor;
2291  }
2292  private void showEditor(boolean activate, IEditorPart editor) {
2293    zoomOutIfNecessary(editor);
2294    setEditorAreaVisible(true);
2295    if (activate)
2296      activate(editor);
2297    else
2298      bringToTop(editor);
2299  }
2300  /**
2301   * See IWorkbenchPage.
2302   */
2303  public boolean isEditorPinned(IEditorPart editor) {
2304    return !((EditorSite) editor.getEditorSite()).getReuseEditor();
2305  }
2306  /**
2307   * Returns whether changes to a part will affect zoom. There are a few
2308   * conditions for this .. - we are zoomed. - the part is contained in the
2309   * main window. - the part is not the zoom part - the part is not a fast
2310   * view - the part and the zoom part are not in the same editor workbook
2311   */
2312  private boolean partChangeAffectsZoom(IWorkbenchPartReference ref) {
2313    PartPane pane = ((WorkbenchPartReference) ref).getPane();
2314    if (pane instanceof MultiEditorInnerPane)
2315      pane = ((MultiEditorInnerPane) pane).getParentPane();
2316    return getActivePerspective().getPresentation().partChangeAffectsZoom(
2317      pane);
2318  }
2319  /**
2320   * Removes a fast view.
2321   */
2322  public void removeFastView(IViewReference ref) {
2323    Perspective persp = getActivePerspective();
2324    if (persp == null)
2325      return;
2326
2327    // If parts change always update zoom.
2328    if (isZoomed())
2329      zoomOut();
2330
2331    // Do real work.
2332    persp.removeFastView(ref);
2333
2334    // Notify listeners.
2335    window.updateFastViewBar();
2336    window.firePerspectiveChanged(
2337        this,
2338        getPerspective(),
2339        ref,
2340        CHANGE_FAST_VIEW_REMOVE);
2341    window.firePerspectiveChanged(
2342      this,
2343      getPerspective(),
2344      CHANGE_FAST_VIEW_REMOVE);
2345  }
2346  /**
2347   * Removes an IPartListener from the part service.
2348   */
2349  public void removePartListener(IPartListener l) {
2350    partListeners.removePartListener(l);
2351  }
2352  /**
2353   * Removes an IPartListener from the part service.
2354   */
2355  public void removePartListener(IPartListener2 l) {
2356    partListeners2.removePartListener(l);
2357  }
2358  /**
2359   * Implements IWorkbenchPage
2360   * 
2361   * @see org.eclipse.ui.IWorkbenchPage#removePropertyChangeListener(IPropertyChangeListener)
2362   * @since 2.0
2363   * @deprecated individual views should store a working set if needed and
2364   *             register a property change listener directly with the
2365   *             working set manager to receive notification when the view
2366   *             working set is removed.
2367   */
2368  public void removePropertyChangeListener(IPropertyChangeListener listener) {
2369    propertyChangeListeners.remove(listener);
2370  }
2371
2372  /*
2373   * (non-Javadoc) Method declared on ISelectionListener.
2374   */
2375  public void removeSelectionListener(ISelectionListener listener) {
2376    selectionService.removeSelectionListener(listener);
2377  }
2378
2379  /*
2380   * (non-Javadoc) Method declared on ISelectionListener.
2381   */
2382  public void removeSelectionListener(
2383    String partId,
2384    ISelectionListener listener) {
2385    selectionService.removeSelectionListener(partId, listener);
2386  }
2387  /*
2388   * (non-Javadoc) Method declared on ISelectionListener.
2389   */
2390  public void removePostSelectionListener(ISelectionListener listener) {
2391    selectionService.removePostSelectionListener(listener);
2392  }
2393
2394  /*
2395   * (non-Javadoc) Method declared on ISelectionListener.
2396   */
2397  public void removePostSelectionListener(
2398    String partId,
2399    ISelectionListener listener) {
2400    selectionService.removePostSelectionListener(partId, listener);
2401  }
2402  /**
2403   * This method is called when a part is activated by clicking within it. In
2404   * response, the part, the pane, and all of its actions will be activated.
2405   * 
2406   * In the current design this method is invoked by the part pane when the
2407   * pane, the part, or any children gain focus.
2408   */
2409  public void requestActivation(IWorkbenchPart part) {
2410    // Sanity check.
2411    if (!certifyPart(part))
2412      return;
2413
2414    // Real work.
2415    setActivePart(part);
2416  }
2417  /**
2418   * Resets the layout for the perspective. The active part in the old layout
2419   * is activated in the new layout for consistent user context.
2420   */
2421  public void resetPerspective() {
2422    // Run op in busy cursor.
2423    // Use set redraw to eliminate the "flash" that can occur in the
2424    // coolbar as the perspective is reset.
2425    CoolBarManager mgr = window.getCoolBarManager();
2426    try {
2427      mgr.getControl().setRedraw(false);
2428      BusyIndicator.showWhile(null, new Runnable() {
2429        public void run() {
2430          busyResetPerspective();
2431        }
2432      });
2433    } finally {
2434      mgr.getControl().setRedraw(true);
2435    }
2436  }
2437  /**
2438   * Restore this page from the memento and ensure that the active
2439   * perspective is equals the active descriptor otherwise create a new
2440   * perspective for that descriptor. If activeDescriptor is null active the
2441   * old perspective.
2442   */
2443  public IStatus restoreState(
2444    IMemento memento,
2445    IPerspectiveDescriptor activeDescritor) {
2446    // Restore working set
2447    String pageName = memento.getString(IWorkbenchConstants.TAG_LABEL);
2448    String label = pageName == null ? "" : "::" + pageName; //$NON-NLS-1$ //$NON-NLS-2$
2449
2450    try {
2451      UIStats.start(UIStats.RESTORE_WORKBENCH, "WorkbenchPage" + label); //$NON-NLS-1$
2452      if (pageName == null)
2453        pageName = ""; //$NON-NLS-1$
2454      MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID, IStatus.OK, WorkbenchMessages.format("WorkbenchPage.unableToRestorePerspective", new String[] { pageName }), //$NON-NLS-1$
2455      null);
2456
2457      String workingSetName =
2458        memento.getString(IWorkbenchConstants.TAG_WORKING_SET);
2459      if (workingSetName != null) {
2460        WorkingSetManager workingSetManager =
2461          (WorkingSetManager) getWorkbenchWindow()
2462            .getWorkbench()
2463            .getWorkingSetManager();
2464        setWorkingSet(workingSetManager.getWorkingSet(workingSetName));
2465      }
2466
2467      // Restore editor manager.
2468      IMemento childMem =
2469        memento.getChild(IWorkbenchConstants.TAG_EDITORS);
2470      result.merge(getEditorManager().restoreState(childMem));
2471
2472      childMem = memento.getChild(IWorkbenchConstants.TAG_VIEWS);
2473      if (childMem != null)
2474        result.merge(getViewFactory().restoreState(childMem));
2475
2476      // Get persp block.
2477      childMem = memento.getChild(IWorkbenchConstants.TAG_PERSPECTIVES);
2478      String activePartID =
2479        childMem.getString(IWorkbenchConstants.TAG_ACTIVE_PART);
2480      String activePartSecondaryID = null;
2481      if (activePartID != null) {
2482        activePartSecondaryID = ViewFactory.extractSecondaryId(activePartID);
2483        if (activePartSecondaryID != null) {
2484            activePartID = ViewFactory.extractPrimaryId(activePartID);
2485        }
2486      }
2487      String activePerspectiveID =
2488        childMem.getString(IWorkbenchConstants.TAG_ACTIVE_PERSPECTIVE);
2489
2490      // Restore perspectives.
2491      IMemento perspMems[] =
2492        childMem.getChildren(IWorkbenchConstants.TAG_PERSPECTIVE);
2493      Perspective activePerspective = null;
2494      for (int i = 0; i < perspMems.length; i++) {
2495        try {
2496          Perspective persp = new Perspective(null, this);
2497          result.merge(persp.restoreState(perspMems[i]));
2498          IPerspectiveDescriptor desc = persp.getDesc();
2499          if (desc.equals(activeDescritor))
2500            activePerspective = persp;
2501          else if (
2502            (activePerspective == null)
2503              && desc.getId().equals(activePerspectiveID))
2504            activePerspective = persp;
2505          perspList.add(persp);
2506        } catch (WorkbenchException e) {
2507        }
2508      }
2509      boolean restoreActivePerspective = false;
2510      if (activeDescritor == null)
2511        restoreActivePerspective = true;
2512      else if (
2513        activePerspective != null
2514          && activePerspective.getDesc().equals(activeDescritor)) {
2515        restoreActivePerspective = true;
2516      } else {
2517        restoreActivePerspective = false;
2518        activePerspective =
2519          createPerspective((PerspectiveDescriptor) activeDescritor);
2520        if (activePerspective == null) {
2521          result.merge(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, WorkbenchMessages.format("Workbench.showPerspectiveError", new String[] { activeDescritor.getId()}), //$NON-NLS-1$
2522          null));
2523        }
2524      }
2525
2526      perspList.setActive(activePerspective);
2527
2528      // Make sure we have a valid perspective to work with,
2529      // otherwise return.
2530      activePerspective = perspList.getActive();
2531      if (activePerspective == null) {
2532        activePerspective = perspList.getNextActive();
2533        perspList.setActive(activePerspective);
2534        result.merge(activePerspective.restoreState());
2535      }
2536      if (activePerspective != null && restoreActivePerspective)
2537        result.merge(activePerspective.restoreState());
2538
2539      if (activePerspective != null) {
2540        window.firePerspectiveActivated(
2541          this,
2542          activePerspective.getDesc());
2543
2544        // Restore active part.
2545        if (activePartID != null) {
2546          IViewReference ref =
2547            activePerspective.findView(activePartID, activePartSecondaryID);
2548          IViewPart view = null;
2549          if (ref != null)
2550            view = ref.getView(true);
2551          if (view != null)
2552            activePart = view;
2553        }
2554      }
2555
2556      childMem =
2557        memento.getChild(IWorkbenchConstants.TAG_NAVIGATION_HISTORY);
2558      if (childMem != null)
2559        navigationHistory.restoreState(childMem);
2560      else if (getActiveEditor() != null)
2561        navigationHistory.markEditor(getActiveEditor());
2562      return result;
2563    } finally {
2564      UIStats.end(UIStats.RESTORE_WORKBENCH, "WorkbenchPage" + label); //$NON-NLS-1$
2565    }
2566  }
2567  /**
2568   * See IWorkbenchPage
2569   */
2570  public boolean saveAllEditors(boolean confirm) {
2571    return getEditorManager().saveAll(confirm, false);
2572  }
2573  /*
2574   * Saves the workbench part.
2575   */
2576  protected boolean savePart(
2577    ISaveablePart saveable,
2578    IWorkbenchPart part,
2579    boolean confirm) {
2580    // Do not certify part do allow editors inside a multipageeditor to
2581    // call this.
2582    return getEditorManager().savePart(saveable, part, confirm);
2583  }
2584  /**
2585   * Saves an editors in the workbench. If <code>confirm</code> is <code>true</code>
2586   * the user is prompted to confirm the command.
2587   * 
2588   * @param confirm
2589   *            if user confirmation should be sought
2590   * @return <code>true</code> if the command succeeded, or <code>false</code>
2591   *         if the user cancels the command
2592   */
2593  public boolean saveEditor(IEditorPart editor, boolean confirm) {
2594    return savePart(editor, editor, confirm);
2595  }
2596  /**
2597   * Saves the current perspective.
2598   */
2599  public void savePerspective() {
2600    Perspective persp = getActivePerspective();
2601    if (persp == null)
2602      return;
2603
2604    // Always unzoom.
2605    if (isZoomed())
2606      zoomOut();
2607
2608    persp.saveDesc();
2609  }
2610  /**
2611   * Saves the perspective.
2612   */
2613  public void savePerspectiveAs(IPerspectiveDescriptor newDesc) {
2614    Perspective persp = getActivePerspective();
2615    if (persp == null)
2616      return;
2617    IPerspectiveDescriptor oldDesc = persp.getDesc();
2618
2619    // Always unzoom.
2620    if (isZoomed())
2621      zoomOut();
2622
2623    persp.saveDescAs(newDesc);
2624    window.updatePerspectiveShortcut(oldDesc, newDesc, this);
2625  }
2626  /**
2627   * Save the state of the page.
2628   */
2629  public IStatus saveState(IMemento memento) {
2630    // We must unzoom to get correct layout.
2631    if (isZoomed())
2632      zoomOut();
2633
2634    MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID, IStatus.OK, WorkbenchMessages.format("WorkbenchPage.unableToSavePerspective", new String[] { getLabel()}), //$NON-NLS-1$
2635    null);
2636
2637    // Save editor manager.
2638    IMemento childMem =
2639      memento.createChild(IWorkbenchConstants.TAG_EDITORS);
2640    result.merge(editorMgr.saveState(childMem));
2641
2642    childMem = memento.createChild(IWorkbenchConstants.TAG_VIEWS);
2643    result.merge(getViewFactory().saveState(childMem));
2644
2645    // Create persp block.
2646    childMem = memento.createChild(IWorkbenchConstants.TAG_PERSPECTIVES);
2647    if (getPerspective() != null)
2648      childMem.putString(
2649        IWorkbenchConstants.TAG_ACTIVE_PERSPECTIVE,
2650        getPerspective().getId());
2651    if (getActivePart() != null) {
2652        if (getActivePart() instanceof IViewPart) {
2653            IViewReference ref = (IViewReference) getReference(getActivePart());
2654            if (ref != null) {
2655          childMem.putString(
2656            IWorkbenchConstants.TAG_ACTIVE_PART,
2657            ViewFactory.getKey(ref));
2658            }
2659        }
2660        else {
2661        childMem.putString(
2662          IWorkbenchConstants.TAG_ACTIVE_PART,
2663          getActivePart().getSite().getId());
2664        }
2665    }
2666
2667    // Save each perspective in opened order
2668    Iterator enum = perspList.iterator();
2669    while (enum.hasNext()) {
2670      Perspective persp = (Perspective) enum.next();
2671      IMemento gChildMem =
2672        childMem.createChild(IWorkbenchConstants.TAG_PERSPECTIVE);
2673      result.merge(persp.saveState(gChildMem));
2674    }
2675    // Save working set if set
2676    if (workingSet != null) {
2677      memento.putString(
2678        IWorkbenchConstants.TAG_WORKING_SET,
2679        workingSet.getName());
2680    }
2681
2682    navigationHistory.saveState(
2683      memento.createChild(IWorkbenchConstants.TAG_NAVIGATION_HISTORY));
2684    return result;
2685  }
2686  /**
2687   * Sets the active part.
2688   */
2689  private void setActivePart(IWorkbenchPart newPart) {
2690    // Optimize it.
2691    if (activePart == newPart)
2692      return;
2693
2694    //No need to change the history if the active editor is becoming the
2695    // active part
2696    boolean markLocation = newPart != lastActiveEditor;
2697    String label = newPart != null ? newPart.getTitle() : "none"; //$NON-NLS-1$
2698    try {
2699      UIStats.start(UIStats.ACTIVATE_PART, label);
2700      // Notify perspective. It may deactivate fast view.
2701      Perspective persp = getActivePerspective();
2702      if (persp != null)
2703        persp.partActivated(newPart);
2704
2705      // Deactivate old part
2706      IWorkbenchPart oldPart = activePart;
2707      if (oldPart != null) {
2708        deactivatePart(oldPart);
2709      }
2710
2711      // Set active part.
2712      activePart = newPart;
2713      if (newPart != null) {
2714        activationList.setActive(newPart);
2715        if (newPart instanceof IEditorPart) {
2716          lastActiveEditor = (IEditorPart) newPart;
2717          IEditorReference ref =
2718            (IEditorReference) getReference(lastActiveEditor);
2719          editorMgr.setVisibleEditor(ref, true);
2720        }
2721      }
2722      activatePart(activePart);
2723
2724      if (markLocation
2725        && activePart != null
2726        && activePart instanceof IEditorPart)
2727        navigationHistory.markEditor((IEditorPart) activePart);
2728
2729      // Fire notifications
2730      if (oldPart != null)
2731        firePartDeactivated(oldPart);
2732
2733      // Update actions now so old actions have heard part deactivated
2734      // and
2735      // new actions can hear part activated.
2736      actionSwitcher.updateActivePart(newPart);
2737      if (newPart != null)
2738        firePartActivated(newPart);
2739    } finally {
2740      UIStats.end(UIStats.ACTIVATE_PART, label);
2741    }
2742  }
2743  /**
2744   * See IWorkbenchPage.
2745   */
2746  public void setEditorAreaVisible(boolean showEditorArea) {
2747    Perspective persp = getActivePerspective();
2748    if (persp == null)
2749      return;
2750    if (showEditorArea == persp.isEditorAreaVisible())
2751      return;
2752    // If parts change always update zoom.
2753    if (isZoomed())
2754      zoomOut();
2755    // Update editor area visibility.
2756    if (showEditorArea) {
2757      persp.showEditorArea();
2758      window.firePerspectiveChanged(
2759        this,
2760        getPerspective(),
2761        CHANGE_EDITOR_AREA_SHOW);
2762    } else {
2763      persp.hideEditorArea();
2764      if (activePart instanceof IEditorPart) {
2765        IEditorPart e = (IEditorPart) activePart;
2766        setActivePart(null);
2767        // preserve editor contributions
2768        actionSwitcher.updateTopEditor(e);
2769      }
2770      window.firePerspectiveChanged(
2771        this,
2772        getPerspective(),
2773        CHANGE_EDITOR_AREA_HIDE);
2774    }
2775  }
2776  /**
2777   * Sets the layout of the page. Assumes the new perspective is not null.
2778   * Keeps the active part if possible. Updates the window menubar and
2779   * toolbar if necessary.
2780   */
2781  private void setPerspective(Perspective newPersp) {
2782    // Don't do anything if already active layout
2783    Perspective oldPersp = getActivePerspective();
2784    if (oldPersp == newPersp)
2785      return;
2786
2787    if (newPersp != null) {
2788      IStatus status = newPersp.restoreState();
2789      if (status.getSeverity() != IStatus.OK) {
2790        String title = WorkbenchMessages.getString("WorkbenchPage.problemRestoringTitle"); //$NON-NLS-1$
2791        String msg = WorkbenchMessages.getString("WorkbenchPage.errorReadingState"); //$NON-NLS-1$
2792        ErrorDialog.openError(
2793          getWorkbenchWindow().getShell(),
2794          title,
2795          msg,
2796          status);
2797      }
2798    }
2799
2800    // Deactivate active part.
2801
2802    // ensure the switcher is not showing any action sets
2803    // so it will reshow them in the new perspective
2804    actionSwitcher.updateTopEditor(null);
2805
2806    IWorkbenchPart oldActivePart = activePart;
2807    setActivePart(null);
2808
2809    // Deactivate the old layout
2810    if (oldPersp != null) {
2811      oldPersp.onDeactivate();
2812      window.selectPerspectiveShortcut(oldPersp.getDesc(), this, false);
2813    }
2814
2815    // Activate the new layout
2816    perspList.setActive(newPersp);
2817    if (newPersp != null) {
2818      newPersp.onActivate();
2819
2820      // Notify listeners of activation
2821      window.firePerspectiveActivated(this, newPersp.getDesc());
2822
2823      // Update the shortcut
2824      window.selectPerspectiveShortcut(newPersp.getDesc(), this, true);
2825    } else {
2826      // No need to remember old active part since there
2827      // is no new active perspective to activate it in.
2828      oldActivePart = null;
2829    }
2830
2831    // Update the window
2832    window.updateActionSets();
2833    window.updateFastViewBar();
2834
2835    updateVisibility(oldPersp, newPersp);
2836
2837    // Reactivate active part.
2838    if (oldActivePart != null) {
2839      oldPersp.setOldPartRef(getReference(oldActivePart));
2840      if (oldActivePart instanceof IEditorPart
2841        && isEditorAreaVisible()) {
2842        activate(oldActivePart);
2843      } else if (oldActivePart instanceof IViewPart) {
2844        IEditorPart ed = editorMgr.getVisibleEditor();
2845        if (ed != null)
2846          actionSwitcher.updateTopEditor(ed);
2847        String id = oldActivePart.getSite().getId();
2848        String secondaryId = ((IViewPart) oldActivePart).getViewSite().getSecondaryId();
2849        if (newPersp.findView(id, secondaryId) != null) {
2850          activate(oldActivePart);
2851        } else {
2852          activateOldPart(newPersp);
2853        }
2854      } else {
2855        activateOldPart(newPersp);
2856      }
2857    } else { //no active part
2858      IEditorPart ed = editorMgr.getVisibleEditor();
2859      if (ed != null) {
2860        actionSwitcher.updateTopEditor(ed);
2861      } else {
2862        activateOldPart(newPersp);
2863      }
2864    }
2865    if (getActivePart() == null && activationList.getActive() != null) {
2866      activate(activationList.getActive());
2867    }
2868    if (editorPresentation != null)
2869      editorPresentation.showVisibleEditor();
2870    
2871    if (newPersp != null && oldPersp != null ) {
2872      if (!stickyPerspectives.contains(newPersp.getDesc())) {
2873          IViewRegistry viewReg = WorkbenchPlugin.getDefault().getViewRegistry();
2874          IStickyViewDescriptor [] stickyDescs = viewReg.getStickyViews();
2875          for (int i = 0; i < stickyDescs.length; i++) {
2876              try {
2877                  // show a sticky view if it was in the last perspective
2878                        if (oldPersp.findView(stickyDescs[i].getId()) != null) {
2879                            showView(stickyDescs[i].getId(), null, IWorkbenchPage.VIEW_CREATE);
2880                        }
2881              }
2882                    catch (PartInitException e) {
2883              WorkbenchPlugin.log("Could not open view :" + stickyDescs[i].getId(), new Status(IStatus.ERROR, WorkbenchPlugin.PI_WORKBENCH, IStatus.ERROR, "Could not open view :" + stickyDescs[i].getId(), e));  //$NON-NLS-1$ //$NON-NLS-2$
2884            }
2885                }
2886        stickyPerspectives.add(newPersp.getDesc());
2887      }
2888    }
2889  }
2890  /*
2891   * Update visibility state of all views.
2892   */
2893  private void updateVisibility(Perspective oldPersp, Perspective newPersp) {
2894    HashSet set = new HashSet();
2895    IWorkbenchPartReference[] refs;
2896    if (oldPersp != null) {
2897      refs = oldPersp.getViewReferences();
2898      for (int i = 0; i < refs.length; i++) {
2899        PartPane pane = ((WorkbenchPartReference) refs[i]).getPane();
2900        if (pane != null)
2901          set.add(pane);
2902      }
2903    }
2904    if (newPersp != null) {
2905      refs = newPersp.getViewReferences();
2906      for (int i = 0; i < refs.length; i++) {
2907        PartPane pane = ((WorkbenchPartReference) refs[i]).getPane();
2908        if (pane != null)
2909          set.add(pane);
2910      }
2911      PerspectiveHelper pres = newPersp.getPresentation();
2912      for (Iterator iter = set.iterator(); iter.hasNext();) {
2913        PartPane pane = (PartPane) iter.next();
2914        IWorkbenchPartReference partRef = pane.getPartReference();
2915        pane.setVisible(pres.isPartVisible(partRef));
2916      }
2917    } else {
2918      for (Iterator iter = set.iterator(); iter.hasNext();) {
2919        PartPane pane = (PartPane) iter.next();
2920        pane.setVisible(false);
2921      }
2922    }
2923  }
2924
2925  private void activateOldPart(Perspective newPersp) {
2926    if (window.isClosing())
2927      return;
2928    if (newPersp != null) {
2929            IWorkbenchPartReference oldPartRef = newPersp.getOldPartRef();
2930      IWorkbenchPart prevOldPart = null;
2931            if (oldPartRef != null)
2932                prevOldPart = oldPartRef.getPart(false);
2933      if (prevOldPart != null)
2934        activate(prevOldPart);
2935      else if (isEditorAreaVisible())
2936        activate(getActiveEditor());
2937    }
2938  }
2939  /**
2940   * Sets the perspective.
2941   * 
2942   * @param persp
2943   *            identifies the new perspective.
2944   */
2945  public void setPerspective(final IPerspectiveDescriptor desc) {
2946    // Going from multiple to single rows can make the coolbar
2947    // and its adjacent views appear jumpy as perspectives are
2948    // switched. Turn off redraw to help with this.
2949    CoolBarManager mgr = window.getCoolBarManager();
2950    try {
2951      mgr.getControl().setRedraw(false);
2952      getClientComposite().setRedraw(false);
2953      // Run op in busy cursor.
2954      BusyIndicator.showWhile(null, new Runnable() {
2955        public void run() {
2956          busySetPerspective(desc);
2957        }
2958      });
2959    } finally {
2960      getClientComposite().setRedraw(true);
2961      mgr.getControl().setRedraw(true);
2962      IWorkbenchPart part = getActivePart();
2963      if (part != null)
2964        part.setFocus();
2965    }
2966  }
2967  /**
2968   * Restore the toolbar layout for the active perspective.
2969   */
2970  protected void resetToolBarLayout() {
2971    window.getCoolBarManager().resetItemOrder();
2972  }
2973  /**
2974   * Sets the active working set for the workbench page. Notifies property
2975   * change listener about the change.
2976   * 
2977   * @param newWorkingSet
2978   *            the active working set for the page. May be null.
2979   * @since 2.0
2980   * @deprecated individual views should store a working set if needed
2981   */
2982  public void setWorkingSet(IWorkingSet newWorkingSet) {
2983    IWorkingSet oldWorkingSet = workingSet;
2984
2985    workingSet = newWorkingSet;
2986    if (oldWorkingSet != newWorkingSet) {
2987      firePropertyChange(
2988        CHANGE_WORKING_SET_REPLACE,
2989        oldWorkingSet,
2990        newWorkingSet);
2991    }
2992    if (newWorkingSet != null) {
2993      WorkbenchPlugin
2994        .getDefault()
2995        .getWorkingSetManager()
2996        .addPropertyChangeListener(
2997        propertyChangeListener);
2998    } else {
2999      WorkbenchPlugin
3000        .getDefault()
3001        .getWorkingSetManager()
3002        .removePropertyChangeListener(propertyChangeListener);
3003    }
3004  }
3005  /**
3006   * @see IWorkbenchPage
3007   */
3008  public void showActionSet(String actionSetID) {
3009    Perspective persp = getActivePerspective();
3010    if (persp != null) {
3011      persp.showActionSet(actionSetID);
3012      window.updateActionSets();
3013      window.firePerspectiveChanged(
3014        this,
3015        getPerspective(),
3016        CHANGE_ACTION_SET_SHOW);
3017    }
3018  }
3019  /**
3020   * See IWorkbenchPage.
3021   */
3022  public IViewPart showView(String viewID) throws PartInitException {
3023    return showView(viewID, null, VIEW_ACTIVATE);
3024  }
3025  
3026  /* (non-Javadoc)
3027   * @see org.eclipse.ui.IWorkbenchPage#showView(java.lang.String, java.lang.String, int)
3028   */
3029  public IViewPart showView(
3030      final String viewID, 
3031      final String secondaryID, 
3032      final int mode) throws PartInitException {
3033    
3034    if (secondaryID != null) {
3035        if (secondaryID.length() == 0 || secondaryID.indexOf(ViewFactory.ID_SEP) != -1)
3036        throw new IllegalArgumentException(WorkbenchMessages.getString("WorkbenchPage.IllegalSecondaryId")); //$NON-NLS-1$
3037    }
3038    if (!certifyMode(mode)) 
3039      throw new IllegalArgumentException(WorkbenchMessages.getString("WorkbenchPage.IllegalViewMode")); //$NON-NLS-1$
3040    
3041    // Run op in busy cursor.
3042    final Object[] result = new Object[1];
3043    BusyIndicator.showWhile(null, new Runnable() {
3044      public void run() {
3045        try {
3046          result[0] = busyShowView(viewID, secondaryID, mode);
3047        } catch (PartInitException e) {
3048          result[0] = e;
3049        }
3050      }
3051    });
3052    if (result[0] instanceof IViewPart)
3053      return (IViewPart) result[0];
3054    else if (result[0] instanceof PartInitException)
3055      throw (PartInitException) result[0];
3056    else
3057      throw new PartInitException(WorkbenchMessages.getString("WorkbenchPage.AbnormalWorkbenchCondition")); //$NON-NLS-1$
3058  }
3059  /**
3060   * @param mode the mode to test
3061   * @return whether the mode is recognized
3062   * @since 3.0
3063   */
3064  private boolean certifyMode(int mode) {
3065    switch(mode) {
3066      case VIEW_ACTIVATE:
3067      case VIEW_VISIBLE:
3068      case VIEW_CREATE:
3069        return true;
3070      default:
3071        return false;
3072    }
3073  }
3074  
3075  /**
3076   * Hides the active fast view. Has no effect if there is no fast view active.
3077   */
3078  public void hideFastView() {
3079    Perspective persp = getActivePerspective();
3080    if (persp != null) {
3081      IViewReference ref = persp.getActiveFastView();
3082      if (ref != null) {
3083        toggleFastView(ref);
3084      }
3085    }
3086  }
3087  
3088  /**
3089   * Toggles the visibility of a fast view. If the view is active it is
3090   * deactivated. Otherwise, it is activated.
3091   */
3092  public void toggleFastView(IViewReference ref) {
3093    Perspective persp = getActivePerspective();
3094    if (persp != null) {
3095      persp.toggleFastView(ref);
3096      // if the fast view has been deactivated
3097      if (ref != persp.getActiveFastView()) {
3098        IWorkbenchPart previouslyActive =
3099          activationList.getPreviouslyActive();
3100        IEditorPart activeEditor = getActiveEditor();
3101        if (activeEditor != null
3102          && previouslyActive instanceof IEditorPart)
3103          setActivePart(activeEditor);
3104        else
3105          setActivePart(previouslyActive);
3106      }
3107    }
3108  }
3109  /**
3110   * Zoom in on a part. If the part is already in zoom then zoom out.
3111   */
3112  public void toggleZoom(IWorkbenchPartReference ref) {
3113    Perspective persp = getActivePerspective();
3114    if (persp == null)
3115      return;
3116
3117    PartPane pane = ((WorkbenchPartReference) ref).getPane();
3118
3119    // If target part is detached fire the zoom event.  Note this doesn't 
3120    // actually cause any changes in size and is required to support 
3121    // intro state changes.  We may want to introduce the notion of a zoomed
3122    // (fullscreen) detached view at a later time.
3123    if (pane.getWindow() instanceof DetachedWindow) {
3124        pane.setZoomed(!pane.isZoomed());
3125      return;
3126    }
3127
3128    if (ref instanceof IViewReference && persp.isFastView((IViewReference)ref)) {
3129      persp.toggleFastViewZoom();
3130      return;
3131    }
3132        
3133    // Update zoom status.
3134    if (isZoomed()) {
3135      zoomOut();
3136    
3137      return;
3138    } else {
3139      persp.getPresentation().zoomIn(ref);
3140      activate(ref.getPart(true));      
3141    }
3142  }
3143  /**
3144   * updateActionBars method comment.
3145   */
3146  public void updateActionBars() {
3147    window.updateActionBars();
3148  }
3149
3150  /**
3151   * Sets the tab list of this page's composite appropriately when a part is
3152   * activated.
3153   */
3154  private void updateTabList(IWorkbenchPart part) {
3155    PartSite site = (PartSite) part.getSite();
3156    PartPane pane = site.getPane();
3157    if (pane instanceof ViewPane) {
3158      ViewPane viewPane = (ViewPane) pane;
3159      Control[] tabList = viewPane.getTabList();
3160      if (pane.getWindow() instanceof DetachedWindow) {
3161        viewPane.getControl().getShell().setTabList(tabList);
3162      } else {
3163        getClientComposite().setTabList(tabList);
3164      }
3165    } else if (pane instanceof EditorPane) {
3166      EditorSashContainer ea = ((EditorPane) pane).getWorkbook().getEditorArea();
3167      ea.updateTabList();
3168      getClientComposite().setTabList(new Control[] { ea.getParent()});
3169    }
3170  }
3171
3172  /**
3173   * The title of the given part has changed. For views, updates the fast
3174   * view button if necessary.
3175   */
3176  public void updateTitle(IViewReference ref) {
3177    if (isFastView(ref)) {
3178      // Would be more efficient to just update label of single tool item
3179      // but we don't have access to it from here.
3180      window.updateFastViewBar();
3181    }
3182  }
3183  /**
3184   * Zooms out a zoomed in part.
3185   */
3186  /* package */
3187  void zoomOut() {
3188    Perspective persp = getActivePerspective();
3189    if (persp != null)
3190      persp.getPresentation().zoomOut();
3191  }
3192  /**
3193   * Zooms out a zoomed in part if it is necessary to do so for the user to
3194   * view the IWorkbenchPart that is the argument. Otherwise, does nothing.
3195   * 
3196   * @param part
3197   *            the part to be made viewable
3198   */
3199  private void zoomOutIfNecessary(IWorkbenchPart part) {
3200    if (isZoomed() && needToZoomOut(part))
3201      zoomOut();
3202  }
3203  /**
3204   * @see IPageLayout.
3205   */
3206  public int getEditorReuseThreshold() {
3207    IPreferenceStore store =
3208      WorkbenchPlugin.getDefault().getPreferenceStore();
3209    return store.getInt(IPreferenceConstants.REUSE_EDITORS);
3210  }
3211  /**
3212   * @see IPageLayout.
3213   */
3214  public void setEditorReuseThreshold(int openEditors) {
3215  }
3216  /*
3217   * Returns the editors in activation order (oldest first).
3218   */
3219  public IEditorReference[] getSortedEditors() {
3220    return activationList.getEditors();
3221  }
3222  /**
3223   * Returns an iterator over the opened perspectives
3224   */
3225  protected IPerspectiveDescriptor[] getOpenedPerspectives() {
3226    Perspective opened[] = perspList.getOpenedPerspectives();
3227    IPerspectiveDescriptor[] result =
3228      new IPerspectiveDescriptor[opened.length];
3229    for (int i = 0; i < result.length; i++) {
3230      result[i] = opened[i].getDesc();
3231    }
3232    return result;
3233  }
3234  /*
3235   * Returns the perspectives in activation order (oldest first).
3236   */
3237  protected IPerspectiveDescriptor[] getSortedPerspectives() {
3238    Perspective sortedArray[] = perspList.getSortedPerspectives();
3239    IPerspectiveDescriptor[] result =
3240      new IPerspectiveDescriptor[sortedArray.length];
3241    for (int i = 0; i < result.length; i++) {
3242      result[i] = sortedArray[i].getDesc();
3243    }
3244    return result;
3245  }
3246  /*
3247   * Returns the parts in activation order (oldest first).
3248   */
3249  public IWorkbenchPartReference[] getSortedParts() {
3250    return activationList.getParts();
3251  }
3252
3253  public IWorkbenchPartReference getReference(IWorkbenchPart part) {
3254    if (part == null)
3255      return null;
3256    PartPane pane = ((PartSite) part.getSite()).getPane();
3257    if (pane instanceof MultiEditorInnerPane) {
3258      MultiEditorInnerPane innerPane = (MultiEditorInnerPane) pane;
3259      return innerPane.getParentPane().getPartReference();
3260    }
3261    if (pane == null) {
3262      /*
3263       * An error has occurred while creating the view.
3264       */
3265      IViewReference refs[] = getViewReferences();
3266      for (int i = 0; i < refs.length; i++) {
3267        if (refs[i].getPart(false) == part)
3268          return refs[i];
3269      }
3270      return null;
3271    }
3272    return pane.getPartReference();
3273  }
3274
3275  private class ActivationList {
3276    //List of parts in the activation order (oldest first)
3277    List parts = new ArrayList();
3278
3279    /*
3280     * Add/Move the active part to end of the list;
3281     */
3282    void setActive(IWorkbenchPart part) {
3283      if (parts.size() <= 0)
3284        return;
3285      PartPane pane = ((PartSite) part.getSite()).getPane();
3286      if (pane instanceof MultiEditorInnerPane) {
3287        MultiEditorInnerPane innerPane = (MultiEditorInnerPane) pane;
3288        setActive(
3289          innerPane.getParentPane().getPartReference().getPart(true));
3290      } else {
3291        IWorkbenchPartReference ref = getReference(part);
3292        if (ref == parts.get(parts.size() - 1))
3293          return;
3294        parts.remove(ref);
3295        parts.add(ref);
3296      }
3297      pane.addPropertyChangeListener(propertyChangeListener);
3298    }
3299    /*
3300     * Add/Move the active part to end of the list;
3301     */
3302    void setActive(IWorkbenchPartReference ref) {
3303      setActive(ref.getPart(true));
3304    }
3305    /*
3306     * Add the active part to the beginning of the list.
3307     */
3308    void add(IWorkbenchPartReference ref) {
3309      if (parts.indexOf(ref) >= 0)
3310        return;
3311
3312      IWorkbenchPart part = ref.getPart(false);
3313      if (part != null) {
3314        PartPane pane = ((PartSite) part.getSite()).getPane();
3315        if (pane instanceof MultiEditorInnerPane) {
3316          MultiEditorInnerPane innerPane =
3317            (MultiEditorInnerPane) pane;
3318          add(innerPane.getParentPane().getPartReference());
3319          return;
3320        }
3321      }
3322      PartPane pane = ((WorkbenchPartReference) ref).getPane();
3323      if (pane != null)
3324        pane.addPropertyChangeListener(propertyChangeListener);
3325      parts.add(0, ref);
3326    }
3327    /*
3328     * Return the active part. Filter fast views.
3329     */
3330    IWorkbenchPart getActive() {
3331      if (parts.isEmpty())
3332        return null;
3333      return getActive(parts.size() - 1);
3334    }
3335    /*
3336     * Return the previously active part. Filter fast views.
3337     */
3338    IWorkbenchPart getPreviouslyActive() {
3339      if (parts.size() < 2)
3340        return null;
3341      return getActive(parts.size() - 2);
3342    }
3343    /*
3344     * Find a part in the list starting from the end and filter fast views
3345     * and views from other perspectives.
3346     */
3347    private IWorkbenchPart getActive(int start) {
3348      IWorkbenchPartReference[] views = getViewReferences();
3349      for (int i = start; i >= 0; i--) {
3350        IWorkbenchPartReference ref =
3351          (IWorkbenchPartReference) parts.get(i);
3352        
3353        // Skip parts whose containers have disabled auto-focus
3354        IWorkbenchPart part = ref.getPart(false);
3355        
3356        if (part != null) {
3357          IWorkbenchPartSite site = part.getSite();
3358          if (site instanceof PartSite) {
3359            PartSite partSite = (PartSite)site;
3360            
3361            ILayoutContainer container = partSite.getPane().getContainer();
3362            if ((container != null) && (!container.allowsAutoFocus())) {
3363              continue;
3364            }
3365          }
3366        }
3367        
3368        // Skip fastviews
3369        if (ref instanceof IViewReference) {
3370          if (!((IViewReference) ref).isFastView()  ) {
3371            for (int j = 0; j < views.length; j++) {
3372              if (views[j] == ref) {
3373                return ref.getPart(true);
3374              }
3375            }
3376          }
3377        } else {
3378          return ref.getPart(true);
3379        }
3380      }
3381      return null;
3382    }
3383    /*
3384     * Retuns the index of the part within the activation list. The higher
3385     * the index, the more recent it was used.
3386     */
3387    int indexOf(IWorkbenchPart part) {
3388      return parts.indexOf(getReference(part));
3389    }
3390    /*
3391     * Returns the index of the part reference within the activation list.  
3392     * The higher the index, the more recent it was used.
3393     */
3394    int indexOf(IWorkbenchPartReference ref) {
3395        return parts.indexOf(ref);
3396    }
3397    /*
3398     * Remove a part from the list
3399     */
3400    boolean remove(IWorkbenchPartReference ref) {
3401      PartPane pane = ((WorkbenchPartReference) ref).getPane();
3402      if (pane != null)
3403        pane.removePropertyChangeListener(propertyChangeListener);
3404      return parts.remove(ref);
3405    }
3406    /*
3407     * Returns the editors in activation order (oldest first).
3408     */
3409    private IEditorReference[] getEditors() {
3410      ArrayList editors = new ArrayList(parts.size());
3411      for (Iterator i = parts.iterator(); i.hasNext();) {
3412        IWorkbenchPartReference part =
3413          (IWorkbenchPartReference) i.next();
3414        if (part instanceof IEditorReference) {
3415          editors.add(part);
3416        }
3417      }
3418      return (IEditorReference[]) editors.toArray(
3419        new IEditorReference[editors.size()]);
3420    }
3421    /*
3422     * Return a list with all parts (editors and views).
3423     */
3424    private IWorkbenchPartReference[] getParts() {
3425      IWorkbenchPartReference[] views = getViewReferences();
3426      ArrayList resultList = new ArrayList(parts.size());
3427      for (Iterator iterator = parts.iterator(); iterator.hasNext();) {
3428        IWorkbenchPartReference ref =
3429          (IWorkbenchPartReference) iterator.next();
3430        if (ref instanceof IViewReference) {
3431          //Filter views from other perspectives
3432          for (int i = 0; i < views.length; i++) {
3433            if (views[i] == ref) {
3434              resultList.add(ref);
3435              break;
3436            }
3437          }
3438        } else {
3439          resultList.add(ref);
3440        }
3441      }
3442      IWorkbenchPartReference[] result =
3443        new IWorkbenchPartReference[resultList.size()];
3444      return (IWorkbenchPartReference[]) resultList.toArray(result);
3445    }
3446    /*
3447     * Returns the topmost editor on the stack, or null if none.
3448     */
3449    IEditorPart getTopEditor() {
3450      IEditorReference editors[] = getEditors();
3451      if (editors.length > 0) {
3452        return editors[editors.length - 1].getEditor(true);
3453      }
3454      return null;
3455    }
3456  }
3457
3458  /**
3459   * Helper class to keep track of all opened perspective. Both the opened
3460   * and used order is kept.
3461   */
3462  private class PerspectiveList {
3463    /**
3464     * List of perspectives in the order they were opened;
3465     */
3466    private List openedList;
3467
3468    /**
3469     * List of perspectives in the order they were used. Last element is
3470     * the most recently used, and first element is the least recently
3471     * used.
3472     */
3473    private List usedList;
3474
3475    /**
3476     * The perspective explicitly set as being the active one
3477     */
3478    private Perspective active;
3479
3480    /**
3481     * Creates an empty instance of the perspective list
3482     */
3483    public PerspectiveList() {
3484      openedList = new ArrayList(15);
3485      usedList = new ArrayList(15);
3486    }
3487    /**
3488     * Return all perspectives in the order they were activated.
3489     */
3490    public Perspective[] getSortedPerspectives() {
3491      Perspective[] result = new Perspective[usedList.size()];
3492      return (Perspective[]) usedList.toArray(result);
3493    }
3494    /**
3495     * Adds a perspective to the list. No check is done for a duplicate
3496     * when adding.
3497     */
3498    public boolean add(Perspective perspective) {
3499      openedList.add(perspective);
3500      usedList.add(0, perspective);
3501      //It will be moved to top only when activated.
3502      return true;
3503    }
3504
3505    /**
3506     * Returns an iterator on the perspective list in the order they were
3507     * opened.
3508     */
3509    public Iterator iterator() {
3510      return openedList.iterator();
3511    }
3512    /**
3513     * Returns an array with all opened perspectives
3514     */
3515    public Perspective[] getOpenedPerspectives() {
3516      Perspective[] result = new Perspective[openedList.size()];
3517      return (Perspective[]) openedList.toArray(result);
3518    }
3519    /**
3520     * Removes a perspective from the list.
3521     */
3522    public boolean remove(Perspective perspective) {
3523      if (active == perspective)
3524        active = null;
3525      usedList.remove(perspective);
3526      return openedList.remove(perspective);
3527    }
3528
3529    /**
3530     * Swap the opened order of old perspective with the new perspective.
3531     */
3532    public void swap(
3533      Perspective oldPerspective,
3534      Perspective newPerspective) {
3535      int oldIndex = openedList.indexOf(oldPerspective);
3536      int newIndex = openedList.indexOf(newPerspective);
3537
3538      if (oldIndex < 0 || newIndex < 0)
3539        return;
3540
3541      openedList.set(oldIndex, newPerspective);
3542      openedList.set(newIndex, oldPerspective);
3543    }
3544
3545    /**
3546     * Returns whether the list contains any perspectives
3547     */
3548    public boolean isEmpty() {
3549      return openedList.isEmpty();
3550    }
3551
3552    /**
3553     * Returns the most recently used perspective in the list.
3554     */
3555    public Perspective getActive() {
3556      return active;
3557    }
3558
3559    /**
3560     * Returns the next most recently used perspective in the list.
3561     */
3562    public Perspective getNextActive() {
3563      if (active == null) {
3564        if (usedList.isEmpty())
3565          return null;
3566        else
3567          return (Perspective) usedList.get(usedList.size() - 1);
3568      } else {
3569        if (usedList.size() < 2)
3570          return null;
3571        else
3572          return (Perspective) usedList.get(usedList.size() - 2);
3573      }
3574    }
3575
3576    /**
3577     * Returns the number of perspectives opened
3578     */
3579    public int size() {
3580      return openedList.size();
3581    }
3582
3583    /**
3584     * Marks the specified perspective as the most recently used one in the
3585     * list.
3586     */
3587    public void setActive(Perspective perspective) {
3588      if (perspective == active)
3589        return;
3590
3591      active = perspective;
3592
3593      if (perspective != null) {
3594        usedList.remove(perspective);
3595        usedList.add(perspective);
3596      }
3597    }
3598  }
3599
3600  //for dynamic UI
3601  protected HashMap getStateMap() {
3602    return stateMap;
3603  }
3604
3605  //for dynamic UI
3606  protected void addPerspective(Perspective persp) {
3607    perspList.add(persp);
3608  }
3609  
3610  /**
3611   * Find the stack of view references stacked with this view part.
3612   * 
3613   * @param part the part
3614   * @return the stack of references
3615   * @since 3.0
3616   */
3617  private IViewReference [] getViewReferenceStack(IViewPart part) {
3618    // Sanity check.
3619    Perspective persp = getActivePerspective();
3620    if (persp == null || !certifyPart(part))
3621      return null;    
3622    
3623    ILayoutContainer container = ((PartSite)part.getSite()).getPane().getContainer();
3624    if (container instanceof ViewStack) {
3625      ViewStack folder = (ViewStack) container;
3626      final ArrayList list = new ArrayList(folder.getChildren().length);
3627      for (int i = 0; i < folder.getChildren().length; i++) {
3628        LayoutPart layoutPart = folder.getChildren()[i];
3629        if (layoutPart instanceof ViewPane) {          
3630          IViewReference view = ((ViewPane)layoutPart).getViewReference();
3631          if (view != null)
3632            list.add(view);
3633        }
3634      }
3635
3636      // sort the list by activation order
3637      Collections.sort(list, new Comparator() {
3638                public int compare(Object o1, Object o2) {
3639                    int pos1 = (-1) * activationList.indexOf((IWorkbenchPartReference) o1);
3640                    int pos2 = (-1) * activationList.indexOf((IWorkbenchPartReference) o2);
3641                    return pos1 - pos2;
3642                }});
3643      
3644      return (IViewReference []) list.toArray(new IViewReference [list.size()]);
3645    }
3646    
3647    return new IViewReference[] { (IViewReference) getReference(part) };
3648  }
3649  
3650  /* (non-Javadoc)
3651   * @see org.eclipse.ui.IWorkbenchPage#getViewStack(org.eclipse.ui.IViewPart)
3652   */
3653  public IViewPart [] getViewStack(IViewPart part) {
3654      IViewReference [] refStack = getViewReferenceStack(part);
3655      if (refStack == null)
3656          return null;
3657      
3658      IViewPart [] stack = new IViewPart[refStack.length];
3659      for (int i = 0; i < refStack.length; i++) {
3660            stack[i] = refStack[i].getView(true);
3661        }
3662          
3663      return stack;
3664  }
3665  /**
3666   * Allow for programmatically resizing a part.
3667   * <p>
3668   * <em>EXPERIMENTAL</em>
3669   * </p>
3670   * <p>
3671   * Known limitations:
3672   * <ul>
3673   * <li>currently applies only to views</li>
3674   * <li>has no effect when view is zoomed</li>
3675   * </ul> 
3676   */
3677  public void resizeView(IViewPart part, int width, int height) {
3678    SashInfo sashInfo = new SashInfo();
3679    PartPane pane = ((PartSite)part.getSite()).getPane();
3680    ILayoutContainer container = pane.getContainer();
3681    LayoutTree tree = getPerspectivePresentation().getLayout().root.find(((ViewStack)container));
3682    
3683    // retrieve our layout sashes from the layout tree
3684    findSashParts(tree, pane.findSashes(), sashInfo);
3685    
3686    // first set the width
3687    float deltaWidth = width - pane.getBounds().width;
3688    if (sashInfo.right != null) {
3689      Rectangle rightBounds = sashInfo.rightNode.getBounds();
3690      // set the new ratio 
3691      sashInfo.right.setRatio(
3692        ((float) ((deltaWidth + sashInfo.right.getBounds().x) - rightBounds.x))
3693          / ((float) rightBounds.width));    
3694      // complete the resize
3695      sashInfo.rightNode.setBounds(rightBounds);  
3696    }
3697    else if (sashInfo.left != null) {
3698      Rectangle leftBounds = sashInfo.leftNode.getBounds();
3699      // set the ratio
3700      sashInfo.left.setRatio(
3701        (float) ((sashInfo.left.getBounds().x - deltaWidth) - leftBounds.x)
3702          / ((float) leftBounds.width));      
3703      // complete the resize
3704      sashInfo.leftNode.setBounds(sashInfo.leftNode.getBounds());
3705    }
3706
3707    // next set the height
3708    float deltaHeight = height - pane.getBounds().height;
3709    if (sashInfo.bottom != null) {
3710      Rectangle bottomBounds = sashInfo.bottomNode.getBounds();
3711      // set the new ratio 
3712      sashInfo.bottom.setRatio(
3713        ((float) ((deltaHeight + sashInfo.bottom.getBounds().y) - bottomBounds.y))
3714          / ((float) bottomBounds.height));    
3715      // complete the resize
3716      sashInfo.bottomNode.setBounds(bottomBounds);  
3717    }
3718    else if (sashInfo.top != null) {
3719      Rectangle topBounds = sashInfo.topNode.getBounds();
3720      // set the ratio
3721      sashInfo.top.setRatio(
3722        (float) ((sashInfo.top.getBounds().y - deltaHeight) - topBounds.y)
3723          / ((float) topBounds.height));      
3724      // complete the resize
3725      sashInfo.topNode.setBounds(topBounds);
3726    }  
3727
3728  }
3729  // provides sash information for the given pane
3730  private class SashInfo {
3731    private LayoutPartSash right;
3732    private LayoutPartSash left;
3733    private LayoutPartSash top;
3734    private LayoutPartSash bottom;
3735    private LayoutTreeNode rightNode;
3736    private LayoutTreeNode leftNode;
3737    private LayoutTreeNode topNode;
3738    private LayoutTreeNode bottomNode;
3739  }
3740  private void findSashParts(LayoutTree tree, PartPane.Sashes sashes, SashInfo info) {
3741    LayoutTree parent = tree.getParent();
3742    if (parent == null)
3743      return;
3744
3745    if (parent.part instanceof LayoutPartSash) {
3746      // get the layout part sash from this tree node
3747      LayoutPartSash sash = (LayoutPartSash) parent.part;      
3748      // make sure it has a sash control
3749      Control control = sash.getControl();
3750      if (control != null) {
3751        // check for a vertical sash
3752        if (sash.isVertical()) {
3753          if (sashes.left == control) {
3754            info.left = sash;
3755            info.leftNode = parent.findSash(sash);
3756          }
3757          else if (sashes.right == control) {
3758            info.right = sash;
3759            info.rightNode = parent.findSash(sash);
3760          }
3761        }        
3762        // check for a horizontal sash
3763        else {
3764          if (sashes.top == control) {
3765            info.top = sash;
3766            info.topNode = parent.findSash(sash);  
3767          }
3768          else if (sashes.bottom == control) {
3769            info.bottom = sash;
3770            info.bottomNode = parent.findSash(sash);
3771          }
3772        }
3773      }
3774    }
3775    // recursive call to continue up the tree
3776    findSashParts(parent, sashes, info);    
3777  }
3778}