/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Markus Alexander Kuppe, Versant GmbH - bug 215797 *******************************************************************************/ package org.eclipse.ui.internal; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.Geometry; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IMemento; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.IPerspectiveDescriptor; import org.eclipse.ui.IPerspectiveFactory; import org.eclipse.ui.IPlaceholderFolderLayout; import org.eclipse.ui.IViewLayout; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.IWorkbenchPreferenceConstants; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.WorkbenchException; import org.eclipse.ui.XMLMemento; import org.eclipse.ui.contexts.IContextService; import org.eclipse.ui.internal.StartupThreading.StartupRunnable; import org.eclipse.ui.internal.contexts.ContextAuthority; import org.eclipse.ui.internal.intro.IIntroConstants; import org.eclipse.ui.internal.layout.ITrimManager; import org.eclipse.ui.internal.layout.IWindowTrim; import org.eclipse.ui.internal.layout.TrimLayout; import org.eclipse.ui.internal.misc.StatusUtil; import org.eclipse.ui.internal.registry.ActionSetRegistry; import org.eclipse.ui.internal.registry.IActionSetDescriptor; import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants; import org.eclipse.ui.internal.registry.PerspectiveDescriptor; import org.eclipse.ui.internal.registry.PerspectiveExtensionReader; import org.eclipse.ui.internal.registry.PerspectiveRegistry; import org.eclipse.ui.internal.registry.StickyViewDescriptor; import org.eclipse.ui.internal.util.PrefUtil; import org.eclipse.ui.presentations.AbstractPresentationFactory; import org.eclipse.ui.presentations.IStackPresentationSite; import org.eclipse.ui.statushandlers.StatusManager; import org.eclipse.ui.views.IStickyViewDescriptor; import org.eclipse.ui.views.IViewDescriptor; import org.eclipse.ui.views.IViewRegistry; /** * The ViewManager is a factory for workbench views. */ public class Perspective { protected PerspectiveDescriptor descriptor; protected WorkbenchPage page; // Editor Area management protected LayoutPart editorArea; protected PartPlaceholder editorHolder; protected boolean editorHidden = false; protected boolean editorAreaRestoreOnUnzoom = false; protected int editorAreaState = IStackPresentationSite.STATE_RESTORED; private ViewFactory viewFactory; protected ArrayList alwaysOnActionSets; protected ArrayList alwaysOffActionSets; protected ArrayList newWizardShortcuts; protected ArrayList showViewShortcuts; protected ArrayList perspectiveShortcuts; //private List fastViews; protected FastViewManager fastViewManager = null; private Map mapIDtoViewLayoutRec; protected boolean fixed; protected ArrayList showInPartIds; protected HashMap showInTimes = new HashMap(); private IViewReference activeFastView; protected IMemento memento; protected PerspectiveHelper presentation; final static private String VERSION_STRING = "0.016";//$NON-NLS-1$ private FastViewPane fastViewPane = new FastViewPane(); // fields used by fast view resizing via a sash private static final int FASTVIEW_HIDE_STEPS = 5; /** * Reference to the part that was previously active * when this perspective was deactivated. */ private IWorkbenchPartReference oldPartRef = null; protected boolean shouldHideEditorsOnActivate = false; protected PageLayout layout; /** * ViewManager constructor comment. */ public Perspective(PerspectiveDescriptor desc, WorkbenchPage page) throws WorkbenchException { this(page); descriptor = desc; if (desc != null) { createPresentation(desc); } } /** * ViewManager constructor comment. */ protected Perspective(WorkbenchPage page) throws WorkbenchException { this.page = page; this.editorArea = page.getEditorPresentation().getLayoutPart(); this.viewFactory = page.getViewFactory(); alwaysOnActionSets = new ArrayList(2); alwaysOffActionSets = new ArrayList(2); // We'll only make a FastView Manager if there's a // Trim manager in the WorkbenchWindow IWorkbenchWindow wbw = page.getWorkbenchWindow(); if (wbw instanceof WorkbenchWindow) { if (((WorkbenchWindow)wbw).getTrimManager() != null) fastViewManager = new FastViewManager(this, page); } mapIDtoViewLayoutRec = new HashMap(); } /** * Sets the fast view attribute. Note: The page is expected to update action * bars. */ public void makeFastView(IViewReference ref) { addFastView(ref, true); } /** * Sets the fast view attribute. Note: The page is expected to update action * bars. */ public void addFastView(IViewReference ref, boolean handleLayout) { ViewPane pane = (ViewPane) ((WorkbenchPartReference) ref).getPane(); if (!isFastView(ref)) { if (handleLayout) { // Only remove the part from the presentation if it // is actually in the presentation. if (presentation.hasPlaceholder(ref.getId(), ref.getSecondaryId()) || pane.getContainer() != null) { presentation.removePart(pane); } } // We are drag-enabling the pane because it has been disabled // when it was removed from the perspective presentation. pane.setFast(true); Control ctrl = pane.getControl(); if (ctrl != null) { ctrl.setEnabled(false); // Remove focus support. } } } /** * Moves a part forward in the Z order of a perspective so it is visible. * * @param part the part to bring to move forward * @return true if the part was brought to top, false if not. */ public boolean bringToTop(IViewReference ref) { if (isFastView(ref)) { setActiveFastView(ref); return true; } else { return presentation.bringPartToTop(getPane(ref)); } } /** * Returns whether a view exists within the perspective. */ public boolean containsView(IViewPart view) { IViewSite site = view.getViewSite(); IViewReference ref = findView(site.getId(), site.getSecondaryId()); if (ref == null) { return false; } return (view == ref.getPart(false)); } /** * Create the initial list of action sets. */ protected void createInitialActionSets(List outputList, List stringList) { ActionSetRegistry reg = WorkbenchPlugin.getDefault() .getActionSetRegistry(); Iterator iter = stringList.iterator(); while (iter.hasNext()) { String id = (String) iter.next(); IActionSetDescriptor desc = reg.findActionSet(id); if (desc != null) { outputList.add(desc); } else { WorkbenchPlugin.log("Unable to find Action Set: " + id);//$NON-NLS-1$ } } } /** * Create a presentation for a perspective. */ private void createPresentation(PerspectiveDescriptor persp) throws WorkbenchException { if (persp.hasCustomDefinition()) { loadCustomPersp(persp); } else { loadPredefinedPersp(persp); } } /** * Dispose the perspective and all views contained within. */ public void dispose() { // Get rid of presentation. if (presentation == null) { disposeViewRefs(); return; } presentation.deactivate(); presentation.dispose(); fastViewPane.dispose(); // Release each view. IViewReference refs[] = getViewReferences(); for (int i = 0, length = refs.length; i < length; i++) { getViewFactory().releaseView(refs[i]); } mapIDtoViewLayoutRec.clear(); } private void disposeViewRefs() { if (memento == null) { return; } IMemento views[] = memento.getChildren(IWorkbenchConstants.TAG_VIEW); for (int x = 0; x < views.length; x++) { // Get the view details. IMemento childMem = views[x]; String id = childMem.getString(IWorkbenchConstants.TAG_ID); // skip creation of the intro reference - it's handled elsewhere. if (id.equals(IIntroConstants.INTRO_VIEW_ID)) { continue; } String secondaryId = ViewFactory.extractSecondaryId(id); if (secondaryId != null) { id = ViewFactory.extractPrimaryId(id); } // Create and open the view. if (!"true".equals(childMem.getString(IWorkbenchConstants.TAG_REMOVED))) { //$NON-NLS-1$ IViewReference ref = viewFactory.getView(id, secondaryId); if (ref != null) { viewFactory.releaseView(ref); } } } } /** * Finds the view with the given ID that is open in this page, or * <code>null</code> if not found. * * @param viewId * the view ID */ public IViewReference findView(String viewId) { return findView(viewId, null); } /** * Finds the view with the given id and secondary id that is open in this page, * or <code>null</code> if not found. * * @param viewId the view ID * @param secondaryId the secondary ID */ public IViewReference findView(String id, String secondaryId) { IViewReference refs[] = getViewReferences(); for (int i = 0; i < refs.length; i++) { IViewReference ref = refs[i]; if (id.equals(ref.getId()) && (secondaryId == null ? ref.getSecondaryId() == null : secondaryId.equals(ref.getSecondaryId()))) { return ref; } } return null; } /** * Returns the window's client composite widget * which views and editor area will be parented. */ public Composite getClientComposite() { return page.getClientComposite(); } /** * Returns the perspective. */ public IPerspectiveDescriptor getDesc() { return descriptor; } /** * Returns the bounds of the given fast view. */ /*package*/Rectangle getFastViewBounds(IViewReference ref) { // Copy the bounds of the page composite Rectangle bounds = page.getClientComposite().getBounds(); // get the width ratio of the fast view float ratio = getFastViewWidthRatio(ref); // Compute the actual width of the fast view. bounds.width = (int) (ratio * getClientComposite().getSize().x); return bounds; } /** * Returns the docked views. */ public IViewReference[] getFastViews() { if (fastViewManager == null) return new IViewReference[0]; List trueFVBRefs = fastViewManager.getFastViews(FastViewBar.FASTVIEWBAR_ID); IViewReference array[] = new IViewReference[trueFVBRefs.size()]; trueFVBRefs.toArray(array); return array; } /** * Returns the new wizard shortcuts associated with this perspective. * * @return an array of new wizard identifiers */ public String[] getNewWizardShortcuts() { return (String[]) newWizardShortcuts.toArray(new String[newWizardShortcuts.size()]); } /** * Returns the pane for a view reference. */ protected ViewPane getPane(IViewReference ref) { return (ViewPane) ((WorkbenchPartReference) ref).getPane(); } /** * Returns the perspective shortcuts associated with this perspective. * * @return an array of perspective identifiers */ public String[] getPerspectiveShortcuts() { return (String[]) perspectiveShortcuts.toArray(new String[perspectiveShortcuts.size()]); } /** * Returns the presentation. */ public PerspectiveHelper getPresentation() { return presentation; } /** * Retrieves the fast view width ratio for the given view. * If the ratio is not known, the default ratio for the view is assigned and returned. */ public float getFastViewWidthRatio(IViewReference ref) { ViewLayoutRec rec = getViewLayoutRec(ref, true); if (rec.fastViewWidthRatio == IPageLayout.INVALID_RATIO) { IViewRegistry reg = WorkbenchPlugin.getDefault().getViewRegistry(); IViewDescriptor desc = reg.find(ref.getId()); rec.fastViewWidthRatio = (desc != null ? desc.getFastViewWidthRatio() : IPageLayout.DEFAULT_FASTVIEW_RATIO); } return rec.fastViewWidthRatio; } /** * Returns the ids of the parts to list in the Show In... dialog. * This is a List of Strings. */ public ArrayList getShowInPartIds() { return showInPartIds; } /** * Returns the time at which the last Show In was performed * for the given target part, or 0 if unknown. */ public long getShowInTime(String partId) { Long t = (Long) showInTimes.get(partId); return t == null ? 0L : t.longValue(); } /** * Returns the show view shortcuts associated with this perspective. * * @return an array of view identifiers */ public String[] getShowViewShortcuts() { return (String[]) showViewShortcuts.toArray(new String[showViewShortcuts.size()]); } /** * Returns the view factory. */ public ViewFactory getViewFactory() { return viewFactory; } /** * See IWorkbenchPage. */ public IViewReference[] getViewReferences() { // Get normal views. if (presentation == null) { return new IViewReference[0]; } List panes = new ArrayList(5); presentation.collectViewPanes(panes); List fastViews = (fastViewManager != null) ? fastViewManager.getFastViews(null) : new ArrayList(); IViewReference[] resultArray = new IViewReference[panes.size() + fastViews.size()]; // Copy fast views. int nView = 0; for (int i = 0; i < fastViews.size(); i++) { resultArray[nView] = (IViewReference) fastViews.get(i); ++nView; } // Copy normal views. for (int i = 0; i < panes.size(); i++) { ViewPane pane = (ViewPane) panes.get(i); resultArray[nView] = pane.getViewReference(); ++nView; } return resultArray; } /** * Hide the editor area if visible */ protected void hideEditorArea() { if (!isEditorAreaVisible()) { return; } // Show the editor in the appropriate location if (useNewMinMax(this)) { // If it's the currently maximized part we have to restore first if (getPresentation().getMaximizedStack() instanceof EditorStack) { getPresentation().getMaximizedStack().setState(IStackPresentationSite.STATE_RESTORED); } boolean isMinimized = editorAreaState == IStackPresentationSite.STATE_MINIMIZED; if (!isMinimized) hideEditorAreaLocal(); else setEditorAreaTrimVisibility(false); } else { hideEditorAreaLocal(); } editorHidden = true; } /** * Hide the editor area if visible */ protected void hideEditorAreaLocal() { if (editorHolder != null) { return; } // Replace the editor area with a placeholder so we // know where to put it back on show editor area request. editorHolder = new PartPlaceholder(editorArea.getID()); presentation.getLayout().replace(editorArea, editorHolder); } /** * Hides a fast view. The view shrinks equally <code>steps</code> times * before disappearing completely. */ private void hideFastView(IViewReference ref, int steps) { setFastViewIconSelection(ref, false); // Note: We always do at least one step of the animation. // Note: This doesn't take into account the overhead of doing if (ref == activeFastView) { saveFastViewWidthRatio(); fastViewPane.hideView(); } } /** * Hides the fast view sash for zooming in a fast view. */ void hideFastViewSash() { fastViewPane.hideFastViewSash(); } public boolean hideView(IViewReference ref) { // If the view is locked just return. ViewPane pane = getPane(ref); // Remove the view from the current presentation. if (isFastView(ref)) { if (pane != null) { pane.setFast(false); //force an update of the toolbar } if (activeFastView == ref) { setActiveFastView(null); } if (pane != null) { pane.getControl().setEnabled(true); } } else { presentation.removePart(pane); } // Dispose view if ref count == 0. getViewFactory().releaseView(ref); return true; } /* * Return whether the editor area is visible or not. */ protected boolean isEditorAreaVisible() { return !editorHidden; } /** * Returns true if a view is fast. */ public boolean isFastView(IViewReference ref) { if (fastViewManager == null) return false; return fastViewManager.isFastView(ref); } /** * Returns the view layout rec for the given view reference, * or null if not found. If create is true, it creates the record * if not already created. */ public ViewLayoutRec getViewLayoutRec(IViewReference ref, boolean create) { ViewLayoutRec result = getViewLayoutRec(ViewFactory.getKey(ref), create); if (result == null && create==false) { result = getViewLayoutRec(ref.getId(), false); } return result; } /** * Returns the view layout record for the given view id * or null if not found. If create is true, it creates the record * if not already created. */ private ViewLayoutRec getViewLayoutRec(String viewId, boolean create) { ViewLayoutRec rec = (ViewLayoutRec) mapIDtoViewLayoutRec.get(viewId); if (rec == null && create) { rec = new ViewLayoutRec(); mapIDtoViewLayoutRec.put(viewId, rec); } return rec; } /** * Returns true if a layout or perspective is fixed. */ public boolean isFixedLayout() { //@issue is there a difference between a fixed //layout and a fixed perspective?? If not the API //may need some polish, WorkbenchPage, PageLayout //and Perspective all have isFixed methods. //PageLayout and Perspective have their own fixed //attribute, we are assuming they are always in sync. //WorkbenchPage delegates to the perspective. return fixed; } /** * Returns true if a view is standalone. * * @since 3.0 */ public boolean isStandaloneView(IViewReference ref) { ViewLayoutRec rec = getViewLayoutRec(ref, false); return rec != null && rec.isStandalone; } /** * Returns whether the title for a view should * be shown. This applies only to standalone views. * * @since 3.0 */ public boolean getShowTitleView(IViewReference ref) { ViewLayoutRec rec = getViewLayoutRec(ref, false); return rec != null && rec.showTitle; } /** * Creates a new presentation from a persistence file. * Note: This method should not modify the current state of the perspective. */ private void loadCustomPersp(PerspectiveDescriptor persp) { //get the layout from the registry PerspectiveRegistry perspRegistry = (PerspectiveRegistry) WorkbenchPlugin .getDefault().getPerspectiveRegistry(); try { IMemento memento = perspRegistry.getCustomPersp(persp.getId()); // Restore the layout state. MultiStatus status = new MultiStatus( PlatformUI.PLUGIN_ID, IStatus.OK, NLS.bind(WorkbenchMessages.Perspective_unableToRestorePerspective, persp.getLabel()), null); status.merge(restoreState(memento)); status.merge(restoreState()); if (status.getSeverity() != IStatus.OK) { unableToOpenPerspective(persp, status); } } catch (IOException e) { unableToOpenPerspective(persp, null); } catch (WorkbenchException e) { unableToOpenPerspective(persp, e.getStatus()); } } private void unableToOpenPerspective(PerspectiveDescriptor persp, IStatus status) { PerspectiveRegistry perspRegistry = (PerspectiveRegistry) WorkbenchPlugin .getDefault().getPerspectiveRegistry(); perspRegistry.deletePerspective(persp); // If this is a predefined perspective, we will not be able to delete // the perspective (we wouldn't want to). But make sure to delete the // customized portion. persp.deleteCustomDefinition(); String title = WorkbenchMessages.Perspective_problemRestoringTitle; String msg = WorkbenchMessages.Perspective_errorReadingState; if (status == null) { MessageDialog.openError((Shell) null, title, msg); } else { ErrorDialog.openError((Shell) null, title, msg, status); } } /** * Create a presentation for a perspective. * Note: This method should not modify the current state of the perspective. */ protected void loadPredefinedPersp(PerspectiveDescriptor persp) throws WorkbenchException { // Create layout engine. IPerspectiveFactory factory = null; try { factory = persp.createFactory(); } catch (CoreException e) { throw new WorkbenchException(NLS.bind(WorkbenchMessages.Perspective_unableToLoad, persp.getId() )); } /* * IPerspectiveFactory#createFactory() can return null */ if (factory == null) { throw new WorkbenchException(NLS.bind(WorkbenchMessages.Perspective_unableToLoad, persp.getId() )); } // Create layout factory. ViewSashContainer container = new ViewSashContainer(page, getClientComposite()); layout = new PageLayout(container, getViewFactory(), editorArea, descriptor); layout.setFixed(descriptor.getFixed()); // add the placeholders for the sticky folders and their contents IPlaceholderFolderLayout stickyFolderRight = null, stickyFolderLeft = null, stickyFolderTop = null, stickyFolderBottom = null; IStickyViewDescriptor[] descs = WorkbenchPlugin.getDefault() .getViewRegistry().getStickyViews(); for (int i = 0; i < descs.length; i++) { IStickyViewDescriptor stickyViewDescriptor = descs[i]; String id = stickyViewDescriptor.getId(); switch (stickyViewDescriptor.getLocation()) { case IPageLayout.RIGHT: if (stickyFolderRight == null) { stickyFolderRight = layout .createPlaceholderFolder( StickyViewDescriptor.STICKY_FOLDER_RIGHT, IPageLayout.RIGHT, .75f, IPageLayout.ID_EDITOR_AREA); } stickyFolderRight.addPlaceholder(id); break; case IPageLayout.LEFT: if (stickyFolderLeft == null) { stickyFolderLeft = layout.createPlaceholderFolder( StickyViewDescriptor.STICKY_FOLDER_LEFT, IPageLayout.LEFT, .25f, IPageLayout.ID_EDITOR_AREA); } stickyFolderLeft.addPlaceholder(id); break; case IPageLayout.TOP: if (stickyFolderTop == null) { stickyFolderTop = layout.createPlaceholderFolder( StickyViewDescriptor.STICKY_FOLDER_TOP, IPageLayout.TOP, .25f, IPageLayout.ID_EDITOR_AREA); } stickyFolderTop.addPlaceholder(id); break; case IPageLayout.BOTTOM: if (stickyFolderBottom == null) { stickyFolderBottom = layout.createPlaceholderFolder( StickyViewDescriptor.STICKY_FOLDER_BOTTOM, IPageLayout.BOTTOM, .75f, IPageLayout.ID_EDITOR_AREA); } stickyFolderBottom.addPlaceholder(id); break; } //should never be null as we've just added the view above IViewLayout viewLayout = layout.getViewLayout(id); viewLayout.setCloseable(stickyViewDescriptor.isCloseable()); viewLayout.setMoveable(stickyViewDescriptor.isMoveable()); } // Run layout engine. factory.createInitialLayout(layout); PerspectiveExtensionReader extender = new PerspectiveExtensionReader(); extender.extendLayout(page.getExtensionTracker(), descriptor.getId(), layout); // Retrieve view layout info stored in the page layout. mapIDtoViewLayoutRec.putAll(layout.getIDtoViewLayoutRecMap()); // Create action sets. List temp = new ArrayList(); createInitialActionSets(temp, layout.getActionSets()); IContextService service = null; if (page != null) { service = (IContextService) page.getWorkbenchWindow().getService( IContextService.class); } try { if (service!=null) { service.activateContext(ContextAuthority.DEFER_EVENTS); } for (Iterator iter = temp.iterator(); iter.hasNext();) { IActionSetDescriptor descriptor = (IActionSetDescriptor) iter .next(); addAlwaysOn(descriptor); } } finally { if (service!=null) { service.activateContext(ContextAuthority.SEND_EVENTS); } } newWizardShortcuts = layout.getNewWizardShortcuts(); showViewShortcuts = layout.getShowViewShortcuts(); perspectiveShortcuts = layout.getPerspectiveShortcuts(); showInPartIds = layout.getShowInPartIds(); // Retrieve fast views if (fastViewManager != null) { ArrayList fastViews = layout.getFastViews(); for (Iterator fvIter = fastViews.iterator(); fvIter.hasNext();) { IViewReference ref = (IViewReference) fvIter.next(); fastViewManager.addViewReference(FastViewBar.FASTVIEWBAR_ID, -1, ref, !fvIter.hasNext()); } } // Is the layout fixed fixed = layout.isFixed(); // Create presentation. presentation = new PerspectiveHelper(page, container, this); // Hide editor area if requested by factory if (!layout.isEditorAreaVisible()) { hideEditorArea(); } } private void removeAlwaysOn(IActionSetDescriptor descriptor) { if (descriptor == null) { return; } if (!alwaysOnActionSets.contains(descriptor)) { return; } alwaysOnActionSets.remove(descriptor); if (page != null) { page.perspectiveActionSetChanged(this, descriptor, ActionSetManager.CHANGE_HIDE); } } protected void addAlwaysOff(IActionSetDescriptor descriptor) { if (descriptor == null) { return; } if (alwaysOffActionSets.contains(descriptor)) { return; } alwaysOffActionSets.add(descriptor); if (page != null) { page.perspectiveActionSetChanged(this, descriptor, ActionSetManager.CHANGE_MASK); } removeAlwaysOn(descriptor); } protected void addAlwaysOn(IActionSetDescriptor descriptor) { if (descriptor == null) { return; } if (alwaysOnActionSets.contains(descriptor)) { return; } alwaysOnActionSets.add(descriptor); if (page != null) { page.perspectiveActionSetChanged(this, descriptor, ActionSetManager.CHANGE_SHOW); } removeAlwaysOff(descriptor); } private void removeAlwaysOff(IActionSetDescriptor descriptor) { if (descriptor == null) { return; } if (!alwaysOffActionSets.contains(descriptor)) { return; } alwaysOffActionSets.remove(descriptor); if (page != null) { page.perspectiveActionSetChanged(this, descriptor, ActionSetManager.CHANGE_UNMASK); } } /** * activate. */ protected void onActivate() { // Update editor area state. if (editorArea.getControl() != null) { boolean visible = isEditorAreaVisible(); boolean inTrim = editorAreaState == IStackPresentationSite.STATE_MINIMIZED; // Funky check: Intro uses the old zoom behaviour when maximized. Make sure we don't show the // editor if it's supposed to be hidden because the intro is maximized. Note that // 'childObscuredByZoom' will only respond 'true' when using the old behaviour. boolean introMaxed = getPresentation().getLayout().childObscuredByZoom(editorArea); editorArea.setVisible(visible && !inTrim && !introMaxed); } // Update fast views. // Make sure the control for the fastviews are created so they can // be activated. if (fastViewManager != null) { List fastViews = fastViewManager.getFastViews(null); for (int i = 0; i < fastViews.size(); i++) { ViewPane pane = getPane((IViewReference) fastViews.get(i)); if (pane != null) { Control ctrl = pane.getControl(); if (ctrl == null) { pane.createControl(getClientComposite()); ctrl = pane.getControl(); } ctrl.setEnabled(false); // Remove focus support. } } } // Set the visibility of all fast view pins setAllPinsVisible(true); // Trim Stack Support boolean useNewMinMax = Perspective.useNewMinMax(this); boolean hideEditorArea = shouldHideEditorsOnActivate || (editorHidden && editorHolder == null); // We have to set the editor area's stack state -before- // activating the presentation since it's used there to determine // size of the resulting stack if (useNewMinMax && !hideEditorArea) { refreshEditorAreaVisibility(); } // Show the layout presentation.activate(getClientComposite()); if (useNewMinMax) { fastViewManager.activate(); // Move any minimized extension stacks to the trim if (layout != null) { // Turn aimations off IPreferenceStore preferenceStore = PrefUtil.getAPIPreferenceStore(); boolean useAnimations = preferenceStore .getBoolean(IWorkbenchPreferenceConstants.ENABLE_ANIMATIONS); preferenceStore.setValue(IWorkbenchPreferenceConstants.ENABLE_ANIMATIONS, false); List minStacks = layout.getMinimizedStacks(); for (Iterator msIter = minStacks.iterator(); msIter.hasNext();) { ViewStack vs = (ViewStack) msIter.next(); vs.setMinimized(true); } // Restore the animation pref preferenceStore.setValue(IWorkbenchPreferenceConstants.ENABLE_ANIMATIONS, useAnimations); // this is a one-off deal...set during the extension reading minStacks.clear(); layout = null; } } else { // Update the FVB only if not using the new min/max WorkbenchWindow wbw = (WorkbenchWindow) page.getWorkbenchWindow(); if (wbw != null) { ITrimManager tbm = wbw.getTrimManager(); if (tbm != null) { IWindowTrim fvb = tbm.getTrim(FastViewBar.FASTVIEWBAR_ID); if (fvb instanceof FastViewBar) { ((FastViewBar)fvb).update(true); } } } } // If we are -not- using the new min/max then ensure that there // are no stacks in the trim. This can happen when a user switches // back to the 3.0 presentation... if (!Perspective.useNewMinMax(this) && fastViewManager != null) { boolean stacksWereRestored = fastViewManager.restoreAllTrimStacks(); setEditorAreaTrimVisibility(false); // Restore any 'maximized' view stack since we've restored // the minimized stacks if (stacksWereRestored && presentation.getMaximizedStack() instanceof ViewStack) { ViewStack vs = (ViewStack) presentation.getMaximizedStack(); vs.setPresentationState(IStackPresentationSite.STATE_RESTORED); presentation.setMaximizedStack(null); } } // We hide the editor area -after- the presentation activates if (hideEditorArea) { // We do this here to ensure that createPartControl is called on the // top editor // before it is hidden. See bug 20166. hideEditorArea(); shouldHideEditorsOnActivate = false; // this is an override so it should handle both states if (useNewMinMax) setEditorAreaTrimVisibility(editorAreaState == IStackPresentationSite.STATE_MINIMIZED); } } /** * deactivate. */ protected void onDeactivate() { presentation.deactivate(); setActiveFastView(null); setAllPinsVisible(false); // Update fast views. if (fastViewManager != null) { List fastViews = fastViewManager.getFastViews(null); for (int i = 0; i < fastViews.size(); i++) { ViewPane pane = getPane((IViewReference) fastViews.get(i)); if (pane != null) { Control ctrl = pane.getControl(); if (ctrl != null) { ctrl.setEnabled(true); // Add focus support. } } } fastViewManager.deActivate(); } // Ensure that the editor area trim is hidden as well setEditorAreaTrimVisibility(false); } /** * Notifies that a part has been activated. */ public void partActivated(IWorkbenchPart activePart) { // If a fastview is open close it. if (activeFastView != null && activeFastView.getPart(false) != activePart) { setActiveFastView(null); } } /** * The user successfully performed a Show In... action on the specified part. * Update the history. */ public void performedShowIn(String partId) { showInTimes.put(partId, new Long(System.currentTimeMillis())); } /** * Sets the fast view attribute. Note: The page is expected to update action * bars. */ public void removeFastView(IViewReference ref) { removeFastView(ref, true); } /** * Sets the fast view attribute. Note: The page is expected to update action * bars. */ public void removeFastView(IViewReference ref, boolean handleLayout) { ViewPane pane = getPane(ref); if (activeFastView == ref) { setActiveFastView(null); } pane.setFast(false); Control ctrl = pane.getControl(); if (ctrl != null) { ctrl.setEnabled(true); // Modify focus support. } if (handleLayout) { // We are disabling the pane because it will be enabled when it // is added to the presentation. When a pane is enabled a drop // listener is added to it, and we do not want to have multiple // listeners for a pane presentation.addPart(pane); } } /** * Fills a presentation with layout data. * Note: This method should not modify the current state of the perspective. */ public IStatus restoreState(IMemento memento) { MultiStatus result = new MultiStatus( PlatformUI.PLUGIN_ID, IStatus.OK, WorkbenchMessages.Perspective_problemsRestoringPerspective, null); // Create persp descriptor. descriptor = new PerspectiveDescriptor(null, null, null); result.add(descriptor.restoreState(memento)); PerspectiveDescriptor desc = (PerspectiveDescriptor) WorkbenchPlugin .getDefault().getPerspectiveRegistry().findPerspectiveWithId( descriptor.getId()); if (desc != null) { descriptor = desc; } this.memento = memento; // Add the visible views. IMemento views[] = memento.getChildren(IWorkbenchConstants.TAG_VIEW); result.merge(createReferences(views)); memento = memento.getChild(IWorkbenchConstants.TAG_FAST_VIEWS); if (memento != null) { views = memento.getChildren(IWorkbenchConstants.TAG_VIEW); result.merge(createReferences(views)); } return result; } IStatus createReferences(IMemento views[]) { MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID, IStatus.OK, WorkbenchMessages.Perspective_problemsRestoringViews, null); for (int x = 0; x < views.length; x++) { // Get the view details. IMemento childMem = views[x]; String id = childMem.getString(IWorkbenchConstants.TAG_ID); // skip creation of the intro reference - it's handled elsewhere. if (id.equals(IIntroConstants.INTRO_VIEW_ID)) { continue; } String secondaryId = ViewFactory.extractSecondaryId(id); if (secondaryId != null) { id = ViewFactory.extractPrimaryId(id); } // Create and open the view. try { if (!"true".equals(childMem.getString(IWorkbenchConstants.TAG_REMOVED))) { //$NON-NLS-1$ viewFactory.createView(id, secondaryId); } } catch (PartInitException e) { childMem.putString(IWorkbenchConstants.TAG_REMOVED, "true"); //$NON-NLS-1$ result.add(StatusUtil.newStatus(IStatus.ERROR, e.getMessage() == null ? "" : e.getMessage(), //$NON-NLS-1$ e)); } } return result; } /** * Fills a presentation with layout data. * Note: This method should not modify the current state of the perspective. */ public IStatus restoreState() { if (this.memento == null) { return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "", null); //$NON-NLS-1$ } MultiStatus result = new MultiStatus( PlatformUI.PLUGIN_ID, IStatus.OK, WorkbenchMessages.Perspective_problemsRestoringPerspective, null); IMemento memento = this.memento; this.memento = null; final IMemento boundsMem = memento.getChild(IWorkbenchConstants.TAG_WINDOW); if (boundsMem != null) { final Rectangle r = new Rectangle(0, 0, 0, 0); r.x = boundsMem.getInteger(IWorkbenchConstants.TAG_X).intValue(); r.y = boundsMem.getInteger(IWorkbenchConstants.TAG_Y).intValue(); r.height = boundsMem.getInteger(IWorkbenchConstants.TAG_HEIGHT) .intValue(); r.width = boundsMem.getInteger(IWorkbenchConstants.TAG_WIDTH) .intValue(); StartupThreading.runWithoutExceptions(new StartupRunnable() { public void runWithException() throws Throwable { if (page.getWorkbenchWindow().getPages().length == 0) { page.getWorkbenchWindow().getShell().setBounds(r); } } }); } // Create an empty presentation.. final PerspectiveHelper [] presArray = new PerspectiveHelper[1]; StartupThreading.runWithoutExceptions(new StartupRunnable() { public void runWithException() throws Throwable { ViewSashContainer mainLayout = new ViewSashContainer(page, getClientComposite()); presArray[0] = new PerspectiveHelper(page, mainLayout, Perspective.this); }}); final PerspectiveHelper pres = presArray[0]; // Read the layout. result.merge(pres.restoreState(memento .getChild(IWorkbenchConstants.TAG_LAYOUT))); StartupThreading.runWithoutExceptions(new StartupRunnable() { public void runWithException() throws Throwable { // Add the editor workbook. Do not hide it now. pres.replacePlaceholderWithPart(editorArea); }}); // Add the visible views. IMemento[] views = memento.getChildren(IWorkbenchConstants.TAG_VIEW); for (int x = 0; x < views.length; x++) { // Get the view details. IMemento childMem = views[x]; String id = childMem.getString(IWorkbenchConstants.TAG_ID); String secondaryId = ViewFactory.extractSecondaryId(id); if (secondaryId != null) { id = ViewFactory.extractPrimaryId(id); } // skip the intro as it is restored higher up in workbench. if (id.equals(IIntroConstants.INTRO_VIEW_ID)) { continue; } // Create and open the view. IViewReference viewRef = viewFactory.getView(id, secondaryId); WorkbenchPartReference ref = (WorkbenchPartReference) viewRef; // report error if (ref == null) { String key = ViewFactory.getKey(id, secondaryId); result.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, NLS.bind(WorkbenchMessages.Perspective_couldNotFind, key ), null)); continue; } boolean willPartBeVisible = pres.willPartBeVisible(ref.getId(), secondaryId); if (willPartBeVisible) { IViewPart view = (IViewPart) ref.getPart(true); if (view != null) { ViewSite site = (ViewSite) view.getSite(); ViewPane pane = (ViewPane) site.getPane(); pres.replacePlaceholderWithPart(pane); } } else { pres.replacePlaceholderWithPart(ref.getPane()); } } // Load the fast views if (fastViewManager != null) fastViewManager.restoreState(memento, result); // Load the view layout recs IMemento[] recMementos = memento .getChildren(IWorkbenchConstants.TAG_VIEW_LAYOUT_REC); for (int i = 0; i < recMementos.length; i++) { IMemento recMemento = recMementos[i]; String compoundId = recMemento .getString(IWorkbenchConstants.TAG_ID); if (compoundId != null) { ViewLayoutRec rec = getViewLayoutRec(compoundId, true); if (IWorkbenchConstants.FALSE.equals(recMemento .getString(IWorkbenchConstants.TAG_CLOSEABLE))) { rec.isCloseable = false; } if (IWorkbenchConstants.FALSE.equals(recMemento .getString(IWorkbenchConstants.TAG_MOVEABLE))) { rec.isMoveable = false; } if (IWorkbenchConstants.TRUE.equals(recMemento .getString(IWorkbenchConstants.TAG_STANDALONE))) { rec.isStandalone = true; rec.showTitle = !IWorkbenchConstants.FALSE .equals(recMemento .getString(IWorkbenchConstants.TAG_SHOW_TITLE)); } } } final IContextService service = (IContextService)page.getWorkbenchWindow().getService(IContextService.class); try { // one big try block, don't kill me here // defer context events if (service != null) { service.activateContext(ContextAuthority.DEFER_EVENTS); } HashSet knownActionSetIds = new HashSet(); // Load the always on action sets. IMemento[] actions = memento .getChildren(IWorkbenchConstants.TAG_ALWAYS_ON_ACTION_SET); for (int x = 0; x < actions.length; x++) { String actionSetID = actions[x] .getString(IWorkbenchConstants.TAG_ID); final IActionSetDescriptor d = WorkbenchPlugin.getDefault() .getActionSetRegistry().findActionSet(actionSetID); if (d != null) { StartupThreading .runWithoutExceptions(new StartupRunnable() { public void runWithException() throws Throwable { addAlwaysOn(d); } }); knownActionSetIds.add(actionSetID); } } // Load the always off action sets. actions = memento .getChildren(IWorkbenchConstants.TAG_ALWAYS_OFF_ACTION_SET); for (int x = 0; x < actions.length; x++) { String actionSetID = actions[x] .getString(IWorkbenchConstants.TAG_ID); final IActionSetDescriptor d = WorkbenchPlugin.getDefault() .getActionSetRegistry().findActionSet(actionSetID); if (d != null) { StartupThreading .runWithoutExceptions(new StartupRunnable() { public void runWithException() throws Throwable { addAlwaysOff(d); } }); knownActionSetIds.add(actionSetID); } } // Load "show view actions". actions = memento .getChildren(IWorkbenchConstants.TAG_SHOW_VIEW_ACTION); showViewShortcuts = new ArrayList(actions.length); for (int x = 0; x < actions.length; x++) { String id = actions[x].getString(IWorkbenchConstants.TAG_ID); showViewShortcuts.add(id); } // Load "show in times". actions = memento.getChildren(IWorkbenchConstants.TAG_SHOW_IN_TIME); for (int x = 0; x < actions.length; x++) { String id = actions[x].getString(IWorkbenchConstants.TAG_ID); String timeStr = actions[x] .getString(IWorkbenchConstants.TAG_TIME); if (id != null && timeStr != null) { try { long time = Long.parseLong(timeStr); showInTimes.put(id, new Long(time)); } catch (NumberFormatException e) { // skip this one } } } // Load "show in parts" from registry, not memento showInPartIds = getShowInIdsFromRegistry(); // Load "new wizard actions". actions = memento .getChildren(IWorkbenchConstants.TAG_NEW_WIZARD_ACTION); newWizardShortcuts = new ArrayList(actions.length); for (int x = 0; x < actions.length; x++) { String id = actions[x].getString(IWorkbenchConstants.TAG_ID); newWizardShortcuts.add(id); } // Load "perspective actions". actions = memento .getChildren(IWorkbenchConstants.TAG_PERSPECTIVE_ACTION); perspectiveShortcuts = new ArrayList(actions.length); for (int x = 0; x < actions.length; x++) { String id = actions[x].getString(IWorkbenchConstants.TAG_ID); perspectiveShortcuts.add(id); } ArrayList extActionSets = getPerspectiveExtensionActionSets(); for (int i = 0; i < extActionSets.size(); i++) { String actionSetID = (String) extActionSets.get(i); if (knownActionSetIds.contains(actionSetID)) { continue; } final IActionSetDescriptor d = WorkbenchPlugin.getDefault() .getActionSetRegistry().findActionSet(actionSetID); if (d != null) { StartupThreading .runWithoutExceptions(new StartupRunnable() { public void runWithException() throws Throwable { addAlwaysOn(d); } }); knownActionSetIds.add(d.getId()); } } // Add the visible set of action sets to our knownActionSetIds // Now go through the registry to ensure we pick up any new action // sets // that have been added but not yet considered by this perspective. ActionSetRegistry reg = WorkbenchPlugin.getDefault() .getActionSetRegistry(); IActionSetDescriptor[] array = reg.getActionSets(); int count = array.length; for (int i = 0; i < count; i++) { IActionSetDescriptor desc = array[i]; if ((!knownActionSetIds.contains(desc.getId())) && (desc.isInitiallyVisible())) { addActionSet(desc); } } } finally { // restart context changes if (service != null) { StartupThreading.runWithoutExceptions(new StartupRunnable() { public void runWithException() throws Throwable { service.activateContext(ContextAuthority.SEND_EVENTS); } }); } } // Save presentation. presentation = pres; // Hide the editor area if needed. Need to wait for the // presentation to be fully setup first. Integer areaVisible = memento .getInteger(IWorkbenchConstants.TAG_AREA_VISIBLE); // Rather than hiding the editors now we must wait until after their // controls // are created. This ensures that if an editor is instantiated, // createPartControl // is also called. See bug 20166. shouldHideEditorsOnActivate = (areaVisible != null && areaVisible .intValue() == 0); // Restore the trim state of the editor area IPreferenceStore preferenceStore = PrefUtil.getAPIPreferenceStore(); boolean useNewMinMax = preferenceStore.getBoolean(IWorkbenchPreferenceConstants.ENABLE_NEW_MIN_MAX); if (useNewMinMax) { Integer trimStateInt = memento.getInteger(IWorkbenchConstants.TAG_AREA_TRIM_STATE); if (trimStateInt != null) { editorAreaState = trimStateInt.intValue() & 0x3; // low order two bits contain the state editorAreaRestoreOnUnzoom = (trimStateInt.intValue() & 4) != 0; } } // restore the fixed state Integer isFixed = memento.getInteger(IWorkbenchConstants.TAG_FIXED); fixed = (isFixed != null && isFixed.intValue() == 1); return result; } /** * Restores a fast view to its corrent presentation structure. * This method is pubilc because the FastViewManager uses it to * reconstruct it minimized stacks on startup. * * @param fvMemento The mement containing the fast view info * @param result The result status * @return The reference to the restored view */ public IViewReference restoreFastView(IMemento fvMemento, MultiStatus result) { String viewID = fvMemento.getString(IWorkbenchConstants.TAG_ID); String secondaryId = ViewFactory.extractSecondaryId(viewID); if (secondaryId != null) { viewID = ViewFactory.extractPrimaryId(viewID); } IViewReference viewRef = getViewReference(viewID, secondaryId); if (viewRef == null) { String key = ViewFactory.getKey(viewID, secondaryId); WorkbenchPlugin .log("Could not create view: '" + key + "'."); //$NON-NLS-1$ //$NON-NLS-2$ result .add(new Status( IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, NLS.bind(WorkbenchMessages.Perspective_couldNotFind, key ), null)); return null; } // Restore fast view width ratio Float ratio = fvMemento.getFloat(IWorkbenchConstants.TAG_RATIO); if (ratio == null) { Integer viewWidth = fvMemento .getInteger(IWorkbenchConstants.TAG_WIDTH); if (viewWidth == null) { ratio = new Float(IPageLayout.DEFAULT_FASTVIEW_RATIO); } else { ratio = new Float((float) viewWidth.intValue() / (float) getClientComposite().getSize().x); } } ViewLayoutRec rec = getViewLayoutRec(viewRef, true); rec.fastViewWidthRatio = ratio.floatValue(); return viewRef; } /** * Returns the ActionSets read from perspectiveExtensions in the registry. */ protected ArrayList getPerspectiveExtensionActionSets() { PerspectiveExtensionReader reader = new PerspectiveExtensionReader(); reader .setIncludeOnlyTags(new String[] { IWorkbenchRegistryConstants.TAG_ACTION_SET }); PageLayout layout = new PageLayout(); reader.extendLayout(null, descriptor.getOriginalId(), layout); return layout.getActionSets(); } /** * Returns the Show In... part ids read from the registry. */ protected ArrayList getShowInIdsFromRegistry() { PerspectiveExtensionReader reader = new PerspectiveExtensionReader(); reader .setIncludeOnlyTags(new String[] { IWorkbenchRegistryConstants.TAG_SHOW_IN_PART }); PageLayout layout = new PageLayout(); reader.extendLayout(null, descriptor.getOriginalId(), layout); return layout.getShowInPartIds(); } /** * Save the layout. */ public void saveDesc() { saveDescAs(descriptor); } /** * Save the layout. */ public void saveDescAs(IPerspectiveDescriptor desc) { PerspectiveDescriptor realDesc = (PerspectiveDescriptor) desc; //get the layout from the registry PerspectiveRegistry perspRegistry = (PerspectiveRegistry) WorkbenchPlugin .getDefault().getPerspectiveRegistry(); // Capture the layout state. XMLMemento memento = XMLMemento.createWriteRoot("perspective");//$NON-NLS-1$ IStatus status = saveState(memento, realDesc, false); if (status.getSeverity() == IStatus.ERROR) { ErrorDialog.openError((Shell) null, WorkbenchMessages.Perspective_problemSavingTitle, WorkbenchMessages.Perspective_problemSavingMessage, status); return; } //save it to the preference store try { perspRegistry.saveCustomPersp(realDesc, memento); descriptor = realDesc; } catch (IOException e) { perspRegistry.deletePerspective(realDesc); MessageDialog.openError((Shell) null, WorkbenchMessages.Perspective_problemSavingTitle, WorkbenchMessages.Perspective_problemSavingMessage); } } /** * Save the layout. */ public IStatus saveState(IMemento memento) { MultiStatus result = new MultiStatus( PlatformUI.PLUGIN_ID, IStatus.OK, WorkbenchMessages.Perspective_problemsSavingPerspective, null); result.merge(saveState(memento, descriptor, true)); return result; } /** * Save the layout. */ private IStatus saveState(IMemento memento, PerspectiveDescriptor p, boolean saveInnerViewState) { MultiStatus result = new MultiStatus( PlatformUI.PLUGIN_ID, IStatus.OK, WorkbenchMessages.Perspective_problemsSavingPerspective, null); if (this.memento != null) { memento.putMemento(this.memento); return result; } // Save the version number. memento.putString(IWorkbenchConstants.TAG_VERSION, VERSION_STRING); result.add(p.saveState(memento)); if (!saveInnerViewState) { Rectangle bounds = page.getWorkbenchWindow().getShell().getBounds(); IMemento boundsMem = memento .createChild(IWorkbenchConstants.TAG_WINDOW); boundsMem.putInteger(IWorkbenchConstants.TAG_X, bounds.x); boundsMem.putInteger(IWorkbenchConstants.TAG_Y, bounds.y); boundsMem.putInteger(IWorkbenchConstants.TAG_HEIGHT, bounds.height); boundsMem.putInteger(IWorkbenchConstants.TAG_WIDTH, bounds.width); } // Save the "always on" action sets. Iterator itr = alwaysOnActionSets.iterator(); while (itr.hasNext()) { IActionSetDescriptor desc = (IActionSetDescriptor) itr.next(); IMemento child = memento .createChild(IWorkbenchConstants.TAG_ALWAYS_ON_ACTION_SET); child.putString(IWorkbenchConstants.TAG_ID, desc.getId()); } // Save the "always off" action sets. itr = alwaysOffActionSets.iterator(); while (itr.hasNext()) { IActionSetDescriptor desc = (IActionSetDescriptor) itr.next(); IMemento child = memento .createChild(IWorkbenchConstants.TAG_ALWAYS_OFF_ACTION_SET); child.putString(IWorkbenchConstants.TAG_ID, desc.getId()); } // Save "show view actions" itr = showViewShortcuts.iterator(); while (itr.hasNext()) { String str = (String) itr.next(); IMemento child = memento .createChild(IWorkbenchConstants.TAG_SHOW_VIEW_ACTION); child.putString(IWorkbenchConstants.TAG_ID, str); } // Save "show in times" itr = showInTimes.keySet().iterator(); while (itr.hasNext()) { String id = (String) itr.next(); Long time = (Long) showInTimes.get(id); IMemento child = memento .createChild(IWorkbenchConstants.TAG_SHOW_IN_TIME); child.putString(IWorkbenchConstants.TAG_ID, id); child.putString(IWorkbenchConstants.TAG_TIME, time.toString()); } // Save "new wizard actions". itr = newWizardShortcuts.iterator(); while (itr.hasNext()) { String str = (String) itr.next(); IMemento child = memento .createChild(IWorkbenchConstants.TAG_NEW_WIZARD_ACTION); child.putString(IWorkbenchConstants.TAG_ID, str); } // Save "perspective actions". itr = perspectiveShortcuts.iterator(); while (itr.hasNext()) { String str = (String) itr.next(); IMemento child = memento .createChild(IWorkbenchConstants.TAG_PERSPECTIVE_ACTION); child.putString(IWorkbenchConstants.TAG_ID, str); } // Get visible views. List viewPanes = new ArrayList(5); presentation.collectViewPanes(viewPanes); // Save the views. itr = viewPanes.iterator(); int errors = 0; while (itr.hasNext()) { ViewPane pane = (ViewPane) itr.next(); IViewReference ref = pane.getViewReference(); boolean restorable = page.getViewFactory().getViewRegistry().find( ref.getId()).isRestorable(); if(restorable) { IMemento viewMemento = memento .createChild(IWorkbenchConstants.TAG_VIEW); viewMemento.putString(IWorkbenchConstants.TAG_ID, ViewFactory .getKey(ref)); } } // save all fastview state if (fastViewManager != null) fastViewManager.saveState(memento); // Save the view layout recs. for (Iterator i = mapIDtoViewLayoutRec.keySet().iterator(); i.hasNext();) { String compoundId = (String) i.next(); ViewLayoutRec rec = (ViewLayoutRec) mapIDtoViewLayoutRec .get(compoundId); if (rec != null && (!rec.isCloseable || !rec.isMoveable || rec.isStandalone)) { IMemento layoutMemento = memento .createChild(IWorkbenchConstants.TAG_VIEW_LAYOUT_REC); layoutMemento.putString(IWorkbenchConstants.TAG_ID, compoundId); if (!rec.isCloseable) { layoutMemento.putString(IWorkbenchConstants.TAG_CLOSEABLE, IWorkbenchConstants.FALSE); } if (!rec.isMoveable) { layoutMemento.putString(IWorkbenchConstants.TAG_MOVEABLE, IWorkbenchConstants.FALSE); } if (rec.isStandalone) { layoutMemento.putString(IWorkbenchConstants.TAG_STANDALONE, IWorkbenchConstants.TRUE); layoutMemento.putString(IWorkbenchConstants.TAG_SHOW_TITLE, String.valueOf(rec.showTitle)); } } } if (errors > 0) { String message = WorkbenchMessages.Perspective_multipleErrors; if (errors == 1) { message = WorkbenchMessages.Perspective_oneError; } MessageDialog.openError(null, WorkbenchMessages.Error, message); } // Save the layout. IMemento childMem = memento.createChild(IWorkbenchConstants.TAG_LAYOUT); result.add(presentation.saveState(childMem)); // Save the editor visibility state if (isEditorAreaVisible()) { memento.putInteger(IWorkbenchConstants.TAG_AREA_VISIBLE, 1); } else { memento.putInteger(IWorkbenchConstants.TAG_AREA_VISIBLE, 0); } // Save the trim state of the editor area if using the new min/max IPreferenceStore preferenceStore = PrefUtil.getAPIPreferenceStore(); boolean useNewMinMax = preferenceStore.getBoolean(IWorkbenchPreferenceConstants.ENABLE_NEW_MIN_MAX); if (useNewMinMax) { int trimState = editorAreaState; trimState |= editorAreaRestoreOnUnzoom ? 4 : 0; memento.putInteger(IWorkbenchConstants.TAG_AREA_TRIM_STATE, trimState); } // Save the fixed state if (fixed) { memento.putInteger(IWorkbenchConstants.TAG_FIXED, 1); } else { memento.putInteger(IWorkbenchConstants.TAG_FIXED, 0); } return result; } public void turnOnActionSets(IActionSetDescriptor[] newArray) { for (int i = 0; i < newArray.length; i++) { IActionSetDescriptor descriptor = newArray[i]; addAlwaysOn(descriptor); } } public void turnOffActionSets(IActionSetDescriptor[] toDisable) { for (int i = 0; i < toDisable.length; i++) { IActionSetDescriptor descriptor = toDisable[i]; turnOffActionSet(descriptor); } } public void turnOffActionSet(IActionSetDescriptor toDisable) { addAlwaysOff(toDisable); } /** * Return the active fast view or null if there are no * fast views or if there are all minimized. */ public IViewReference getActiveFastView() { return activeFastView; } /** * Sets the active fast view. If a different fast view is already open, * it shrinks equally <code>steps</code> times before disappearing * completely. Then, <code>view</code> becomes active and is shown. */ /*package*/void setActiveFastView(IViewReference ref, int steps) { if (activeFastView == ref) { return; } if (activeFastView != null) { ViewPane pane = getPane(activeFastView); if (pane != null) { if (pane.isZoomed()) { presentation.zoomOut(); } hideFastView(activeFastView, steps); } } activeFastView = ref; try { if (activeFastView != null) { if (!showFastView(activeFastView)) { activeFastView = null; } } } catch (RuntimeException e) { activeFastView = null; } } /** * Sets the active fast view. */ /*package*/void setActiveFastView(IViewReference ref) { setActiveFastView(ref, FASTVIEW_HIDE_STEPS); } /** * Sets the visibility of all fast view pins. */ protected void setAllPinsVisible(boolean visible) { if (fastViewManager == null) return; Iterator iter = fastViewManager.getFastViews(null).iterator(); while (iter.hasNext()) { ViewPane pane = getPane((IViewReference) iter.next()); if (pane != null) { pane.setFast(visible); } } } /** * Sets the selection for the shortcut bar icon representing the givevn fast view. */ private void setFastViewIconSelection(IViewReference ref, boolean selected) { if (fastViewManager == null) return; fastViewManager.setFastViewIconSelection(ref, selected); } /** * Sets the new wizard actions for the page. * This is List of Strings. */ public void setNewWizardActionIds(ArrayList newList) { newWizardShortcuts = newList; } /** * Sets the perspective actions for this page. * This is List of Strings. */ public void setPerspectiveActionIds(ArrayList list) { perspectiveShortcuts = list; } /** * Sets the ids of the parts to list in the Show In... prompter. * This is a List of Strings. */ public void setShowInPartIds(ArrayList list) { showInPartIds = list; } /** * Sets the ids of the views to list in the Show View shortcuts. * This is a List of Strings. */ public void setShowViewActionIds(ArrayList list) { showViewShortcuts = list; } /** * Show the editor area if not visible */ protected void showEditorArea() { if (isEditorAreaVisible()) { return; } editorHidden = false; // Show the editor in the appropriate location if (useNewMinMax(this)) { boolean isMinimized = editorAreaState == IStackPresentationSite.STATE_MINIMIZED; if (!isMinimized) { // If the editor area is going to show then we have to restore if (getPresentation().getMaximizedStack() != null) getPresentation().getMaximizedStack().setState(IStackPresentationSite.STATE_RESTORED); showEditorAreaLocal(); } else setEditorAreaTrimVisibility(true); } else { showEditorAreaLocal(); } } /** * Show the editor area if not visible */ protected void showEditorAreaLocal() { if (editorHolder == null || editorHidden) { return; } // Replace the part holder with the editor area. presentation.getLayout().replace(editorHolder, editorArea); editorHolder = null; } private EditorAreaTrimToolBar getEditorAreaTrim(boolean createIfNecessary) { WorkbenchWindow wbw = (WorkbenchWindow) page.getWorkbenchWindow(); ITrimManager tbm = wbw.getTrimManager(); if (tbm == null) return null; // Create if necesary EditorAreaTrimToolBar editorAreaTrim = (EditorAreaTrimToolBar) tbm.getTrim(IPageLayout.ID_EDITOR_AREA); if (editorAreaTrim == null && createIfNecessary) { int suggestedSide = SWT.RIGHT; int cachedSide = ((TrimLayout)tbm).getPreferredArea(IPageLayout.ID_EDITOR_AREA); if (cachedSide != -1) suggestedSide = cachedSide; IWindowTrim beforeMe = ((TrimLayout)tbm).getPreferredLocation(IPageLayout.ID_EDITOR_AREA); // Gain access to the trim manager editorAreaTrim = new EditorAreaTrimToolBar(wbw, editorArea); editorAreaTrim.dock(suggestedSide); tbm.addTrim(suggestedSide, editorAreaTrim, beforeMe); } return editorAreaTrim; } public void setEditorAreaState(int newState) { if (newState == editorAreaState) return; editorAreaState = newState; // reset the restore flag if we're not minimized if (newState != IStackPresentationSite.STATE_MINIMIZED) editorAreaRestoreOnUnzoom = false; refreshEditorAreaVisibility(); } public int getEditorAreaState() { return editorAreaState; } /** * */ public void refreshEditorAreaVisibility() { // Nothing shows up if the editor area isn't visible at all if (editorHidden) { hideEditorAreaLocal(); setEditorAreaTrimVisibility(false); return; } EditorStack editorStack = ((EditorSashContainer) editorArea).getUpperRightEditorStack(null); if (editorStack == null) return; // Whatever we're doing, make the current editor stack match it editorStack.setStateLocal(editorAreaState); // If it's minimized then it's in the trim if (editorAreaState == IStackPresentationSite.STATE_MINIMIZED) { // Hide the editor area and show its trim hideEditorAreaLocal(); setEditorAreaTrimVisibility(true); } else { // Show the editor area and hide its trim setEditorAreaTrimVisibility(false); showEditorAreaLocal(); if (editorAreaState == IStackPresentationSite.STATE_MAXIMIZED) getPresentation().setMaximizedStack(editorStack); } } protected EditorAreaTrimToolBar setEditorAreaTrimVisibility(boolean visible) { WorkbenchWindow wbw = (WorkbenchWindow) page.getWorkbenchWindow(); ITrimManager tbm = wbw.getTrimManager(); if (tbm == null) return null; // Only create the trim element if it's going to be visible EditorAreaTrimToolBar editorAreaTrim = getEditorAreaTrim(visible); if (editorAreaTrim == null) return null; tbm.setTrimVisible(editorAreaTrim, visible); tbm.forceLayout(); return editorAreaTrim; } /** * Shows a fast view. * @return whether the view was successfully shown */ boolean showFastView(IViewReference ref) { if (fastViewManager == null) return false; // Make sure the part is restored. IWorkbenchPart refPart = ref.getPart(true); if (refPart == null) { return false; } ViewPane pane = getPane(ref); if (pane == null) { return false; } saveFastViewWidthRatio(); // Special check to ensure that a 'minimized' intro view shows // as 'standby' if (ref.getId().equals("org.eclipse.ui.internal.introview")) { //$NON-NLS-1$ if (refPart instanceof ViewIntroAdapterPart) { ((ViewIntroAdapterPart)refPart).setStandby(true); } } // Determine the display orientation int side = fastViewManager.getViewSide(ref); fastViewPane.showView(getClientComposite(), pane, side, getFastViewWidthRatio(ref)); setFastViewIconSelection(ref, true); return true; } private void saveFastViewWidthRatio() { ViewPane pane = fastViewPane.getCurrentPane(); if (pane != null) { ViewLayoutRec rec = getViewLayoutRec(pane.getViewReference(), true); rec.fastViewWidthRatio = fastViewPane.getCurrentRatio(); } } /** * Resolves a view's id into its reference, creating the * view if necessary. * * @param viewId The primary id of the view (must not be * <code>null</code> * @param secondaryId The secondary id of a multiple-instance view * (may be <code>null</code>). * * @return The reference to the specified view. This may be null if the * view fails to create (i.e. thrown a PartInitException) */ public IViewReference getViewReference(String viewId, String secondaryId) { IViewReference ref = page.findViewReference(viewId, secondaryId); if (ref == null) { ViewFactory factory = getViewFactory(); try { ref = factory.createView(viewId, secondaryId); } catch (PartInitException e) { IStatus status = StatusUtil.newStatus(IStatus.ERROR, e.getMessage() == null ? "" : e.getMessage(), //$NON-NLS-1$ e); StatusUtil.handleStatus(status, "Failed to create view: id=" + viewId, //$NON-NLS-1$ StatusManager.LOG); } } return ref; } /** * Shows the view with the given id and secondary id. */ public IViewPart showView(String viewId, String secondaryId) throws PartInitException { ViewFactory factory = getViewFactory(); IViewReference ref = factory.createView(viewId, secondaryId); IViewPart part = (IViewPart) ref.getPart(true); if (part == null) { throw new PartInitException(NLS.bind(WorkbenchMessages.ViewFactory_couldNotCreate, ref.getId())); } ViewSite site = (ViewSite) part.getSite(); ViewPane pane = (ViewPane) site.getPane(); IPreferenceStore store = WorkbenchPlugin.getDefault() .getPreferenceStore(); int openViewMode = store.getInt(IPreferenceConstants.OPEN_VIEW_MODE); if (openViewMode == IPreferenceConstants.OVM_FAST && fastViewManager != null) { fastViewManager.addViewReference(FastViewBar.FASTVIEWBAR_ID, -1, ref, true); setActiveFastView(ref); } else if (openViewMode == IPreferenceConstants.OVM_FLOAT && presentation.canDetach()) { presentation.addDetachedPart(pane); } else { if (useNewMinMax(this)) { // Is this view going to show in the trim? LayoutPart vPart = presentation.findPart(viewId, secondaryId); // Determine if there is a trim stack that should get the view String trimId = null; // If we can locate the correct trim stack then do so if (vPart != null) { String id = null; ILayoutContainer container = vPart.getContainer(); if (container instanceof ContainerPlaceholder) id = ((ContainerPlaceholder)container).getID(); else if (container instanceof ViewStack) id = ((ViewStack)container).getID(); // Is this place-holder in the trim? if (id != null && fastViewManager.getFastViews(id).size() > 0) { trimId = id; } } // No explicit trim found; If we're maximized then we either have to find an // arbitrary stack... if (trimId == null && presentation.getMaximizedStack() != null) { if (vPart == null) { ViewStackTrimToolBar blTrimStack = fastViewManager.getBottomRightTrimStack(); if (blTrimStack != null) { // OK, we've found a trim stack to add it to... trimId = blTrimStack.getId(); // Since there was no placeholder we have to add one LayoutPart blPart = presentation.findPart(trimId, null); if (blPart instanceof ContainerPlaceholder) { ContainerPlaceholder cph = (ContainerPlaceholder) blPart; if (cph.getRealContainer() instanceof ViewStack) { ViewStack vs = (ViewStack) cph.getRealContainer(); // Create a 'compound' id if this is a multi-instance part String compoundId = ref.getId(); if (ref.getSecondaryId() != null) compoundId = compoundId + ':' + ref.getSecondaryId(); // Add the new placeholder vs.add(new PartPlaceholder(compoundId)); } } } } } // If we have a trim stack located then add the view to it if (trimId != null) { fastViewManager.addViewReference(trimId, -1, ref, true); } else { boolean inMaximizedStack = vPart != null && vPart.getContainer() == presentation.getMaximizedStack(); // Do the default behavior presentation.addPart(pane); // Now, if we're maximized then we have to minimize the new stack if (presentation.getMaximizedStack() != null && !inMaximizedStack) { vPart = presentation.findPart(viewId, secondaryId); if (vPart != null && vPart.getContainer() instanceof ViewStack) { ViewStack vs = (ViewStack)vPart.getContainer(); vs.setState(IStackPresentationSite.STATE_MINIMIZED); // setting the state to minimized will create the trim toolbar // so we don't need a null pointer check here... fastViewManager.getViewStackTrimToolbar(vs.getID()).setRestoreOnUnzoom(true); } } } } else { presentation.addPart(pane); } } // Ensure that the newly showing part is enabled if (pane != null && pane.getControl() != null) pane.getControl().setEnabled(true); return part; } /** * Toggles the visibility of a fast view. If the view is active it * is deactivated. Otherwise, it is activated. */ public void toggleFastView(IViewReference ref) { if (ref == activeFastView) { setActiveFastView(null); } else { setActiveFastView(ref); } } /** * Returns the old part reference. * Returns null if there was no previously active part. * * @return the old part reference or <code>null</code> */ public IWorkbenchPartReference getOldPartRef() { return oldPartRef; } /** * Sets the old part reference. * * @param oldPartRef The old part reference to set, or <code>null</code> */ public void setOldPartRef(IWorkbenchPartReference oldPartRef) { this.oldPartRef = oldPartRef; } //for dynamic UI protected void addActionSet(IActionSetDescriptor newDesc) { IContextService service = (IContextService)page.getWorkbenchWindow().getService(IContextService.class); try { service.activateContext(ContextAuthority.DEFER_EVENTS); for (int i = 0; i < alwaysOnActionSets.size(); i++) { IActionSetDescriptor desc = (IActionSetDescriptor) alwaysOnActionSets .get(i); if (desc.getId().equals(newDesc.getId())) { removeAlwaysOn(desc); removeAlwaysOff(desc); break; } } addAlwaysOn(newDesc); } finally { service.activateContext(ContextAuthority.SEND_EVENTS); } } // for dynamic UI /* package */void removeActionSet(String id) { IContextService service = (IContextService)page.getWorkbenchWindow().getService(IContextService.class); try { service.activateContext(ContextAuthority.DEFER_EVENTS); for (int i = 0; i < alwaysOnActionSets.size(); i++) { IActionSetDescriptor desc = (IActionSetDescriptor) alwaysOnActionSets .get(i); if (desc.getId().equals(id)) { removeAlwaysOn(desc); break; } } for (int i = 0; i < alwaysOffActionSets.size(); i++) { IActionSetDescriptor desc = (IActionSetDescriptor) alwaysOffActionSets .get(i); if (desc.getId().equals(id)) { removeAlwaysOff(desc); break; } } } finally { service.activateContext(ContextAuthority.SEND_EVENTS); } } void removeActionSet(IActionSetDescriptor toRemove) { removeAlwaysOn(toRemove); removeAlwaysOff(toRemove); } public void setFastViewState(int newState) { fastViewPane.setState(newState); } public int getFastViewState() { return fastViewPane.getState(); } /** * Returns whether the given view is closeable in this perspective. * * @since 3.0 */ public boolean isCloseable(IViewReference reference) { ViewLayoutRec rec = getViewLayoutRec(reference, false); if (rec != null) { return rec.isCloseable; } return true; } /** * Returns whether the given view is moveable in this perspective. * * @since 3.0 */ public boolean isMoveable(IViewReference reference) { ViewLayoutRec rec = getViewLayoutRec(reference, false); if (rec != null) { return rec.isMoveable; } return true; } /** * Writes a description of the layout to the given string buffer. * This is used for drag-drop test suites to determine if two layouts are the * same. Like a hash code, the description should compare as equal iff the * layouts are the same. However, it should be user-readable in order to * help debug failed tests. Although these are english readable strings, * they should not be translated or equality tests will fail. * <p> * This is only intended for use by test suites. * </p> * * @param buf */ public void describeLayout(StringBuffer buf) { IViewReference[] fastViews = getFastViews(); if (fastViews.length != 0) { buf.append("fastviews ("); //$NON-NLS-1$ for (int idx = 0; idx < fastViews.length; idx++) { IViewReference ref = fastViews[idx]; if (idx > 0) { buf.append(", "); //$NON-NLS-1$ } buf.append(ref.getPartName()); } buf.append("), "); //$NON-NLS-1$ } getPresentation().describeLayout(buf); } /** * Sanity-checks the LayoutParts in this perspective. Throws an Assertation exception * if an object's internal state is invalid. */ public void testInvariants() { getPresentation().getLayout().testInvariants(); } public IActionSetDescriptor[] getAlwaysOnActionSets() { return (IActionSetDescriptor[]) alwaysOnActionSets.toArray(new IActionSetDescriptor[alwaysOnActionSets.size()]); } public IActionSetDescriptor[] getAlwaysOffActionSets() { return (IActionSetDescriptor[]) alwaysOffActionSets.toArray(new IActionSetDescriptor[alwaysOffActionSets.size()]); } /* package */ FastViewPane getFastViewPane() { return fastViewPane; } /** * Restores a part in the trim to the actual layout * @param part The part to restore */ public void restoreTrimPart(LayoutPart part) { if (fastViewManager == null) return; // Remove any current fastview setActiveFastView(null); // Set the part's state to place it back in the layout if (part instanceof ViewStack) { ViewStack vs = (ViewStack) part; fastViewManager.restoreToPresentation(vs.getID()); } if (part == editorArea) { setEditorAreaState(IStackPresentationSite.STATE_RESTORED); editorAreaRestoreOnUnzoom = false; } } /** * Determine the correct side to initially dock a new * trim part on. We do this by checking its rect against * the editor area. * * @param stackBounds The bounds of the stack we want to create trim for * @return the SWT side to dock the trim element on */ public int calcStackSide(Rectangle stackBounds) { // Where is the stack in relation to the EditorArea? Rectangle editorAreaBounds = editorArea.getBounds(); // Is this the Editor Area if (editorAreaBounds.equals(stackBounds)) return SWT.TOP; Point stackCenter = Geometry.centerPoint(stackBounds); Point editorAreaCenter = Geometry.centerPoint(editorAreaBounds); int dx = editorAreaCenter.x - stackCenter.x; int dy = editorAreaCenter.y - stackCenter.y; if (Math.abs(dx) > Math.abs(dy)) { return (dx > 0) ? SWT.LEFT : SWT.RIGHT; } if (dy > 0) { return (dx > 0) ? SWT.LEFT : SWT.RIGHT; } return SWT.BOTTOM; } /** * Restore any parts that are showing in the trim as * a result of a 'zoom' operation */ public void restoreZoomedParts() { if (fastViewManager == null) return; // Remove any current fastview setActiveFastView(null); // have the layout restore the parts fastViewManager.restoreZoomedViewStacks(); if (editorAreaRestoreOnUnzoom) { restoreTrimPart(editorArea); } } /** * @return Returns the fastViewManager. */ public FastViewManager getFastViewManager() { return fastViewManager; } /** * Sets the restore on unzoom state for the editor area * @param restore the new state */ public void setEditorAreaRestoreOnUnzoom(boolean restore) { editorAreaRestoreOnUnzoom = restore; } /** * @return the restore on unzoom state */ public boolean getEditorAreaRestoreOnUnzoom() { return editorAreaRestoreOnUnzoom; } /** * Used to restrict the use of the new min/max behavior to envoronments * in which it has a chance of working... * * @param activePerspective We pass this in as an arg so others won't have * to check it for 'null' (which is one of the failure cases) * */ public static boolean useNewMinMax(Perspective activePerspective) { // We need to have an active perspective if (activePerspective == null) return false; // We need to have a trim manager (if we don't then we // don't create a FastViewManager because it'd be useless) if (activePerspective.getFastViewManager() == null) return false; // Make sure we don't NPE anyplace WorkbenchWindow wbw = (WorkbenchWindow) activePerspective.page.getWorkbenchWindow(); if (wbw == null) return false; WorkbenchWindowConfigurer configurer = wbw.getWindowConfigurer(); if (configurer == null) return false; AbstractPresentationFactory factory = configurer.getPresentationFactory(); if (factory == null) return false; // Ok, we should be good to go, return the pref IPreferenceStore preferenceStore = PrefUtil.getAPIPreferenceStore(); boolean useNewMinMax = preferenceStore.getBoolean(IWorkbenchPreferenceConstants.ENABLE_NEW_MIN_MAX); return useNewMinMax; } }