/******************************************************************************* * 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 * Dan Rubel (dan_rubel@instantiations.com) - accessor to get context menu ids *******************************************************************************/ package org.eclipse.ui.internal; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IKeyBindingService; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.SubActionBars; import org.eclipse.ui.internal.progress.WorkbenchSiteProgressService; import org.eclipse.ui.internal.services.IServiceLocatorCreator; import org.eclipse.ui.internal.services.IWorkbenchLocationService; import org.eclipse.ui.internal.services.ServiceLocator; import org.eclipse.ui.internal.services.WorkbenchLocationService; import org.eclipse.ui.internal.testing.WorkbenchPartTestable; import org.eclipse.ui.progress.IWorkbenchSiteProgressService; import org.eclipse.ui.services.IDisposable; import org.eclipse.ui.services.IServiceScopes; import org.eclipse.ui.testing.IWorkbenchPartTestable; /** * <code>PartSite</code> is the general implementation for an * <code>IWorkbenchPartSite</code>. A site maintains the context for a part, * including the part, its pane, active contributions, selection provider, etc. * Together, these components make up the complete behavior for a part as if it * was implemented by one person. * * The <code>PartSite</code> lifecycle is as follows .. * * <ol> * <li>a site is constructed </li> * <li>a part is constructed and stored in the part </li> * <li>the site calls part.init() </li> * <li>a pane is constructed and stored in the site </li> * <li>the action bars for a part are constructed and stored in the site </li> * <li>the pane is added to a presentation </li> * <li>the SWT widgets for the pane and part are created </li> * <li>the site is activated, causing the actions to become visible </li> * </ol> */ public abstract class PartSite implements IWorkbenchPartSite { /** * This is a helper method for the register context menu functionality. It * is provided so that different implementations of the * <code>IWorkbenchPartSite</code> interface don't have to worry about how * context menus should work. * * @param menuId * the menu id * @param menuManager * the menu manager * @param selectionProvider * the selection provider * @param includeEditorInput * whether editor inputs should be included in the structured * selection when calculating contributions * @param part * the part for this site * @param menuExtenders * the collection of menu extenders for this site * @see IWorkbenchPartSite#registerContextMenu(MenuManager, * ISelectionProvider) */ public static final void registerContextMenu(final String menuId, final MenuManager menuManager, final ISelectionProvider selectionProvider, final boolean includeEditorInput, final IWorkbenchPart part, final Collection menuExtenders) { /* * Check to see if the same menu manager and selection provider have * already been used. If they have, then we can just add another menu * identifier to the existing PopupMenuExtender. */ final Iterator extenderItr = menuExtenders.iterator(); boolean foundMatch = false; while (extenderItr.hasNext()) { final PopupMenuExtender existingExtender = (PopupMenuExtender) extenderItr .next(); if (existingExtender.matches(menuManager, selectionProvider, part)) { existingExtender.addMenuId(menuId); foundMatch = true; break; } } if (!foundMatch) { menuExtenders.add(new PopupMenuExtender(menuId, menuManager, selectionProvider, part, includeEditorInput)); } } private IWorkbenchPartReference partReference; private IWorkbenchPart part; private IWorkbenchPage page; private String extensionID; private String pluginID; private String extensionName; private ISelectionProvider selectionProvider; private SubActionBars actionBars; private KeyBindingService keyBindingService; protected ArrayList menuExtenders; private WorkbenchSiteProgressService progressService; protected final ServiceLocator serviceLocator; /** * Build the part site. * * @param ref * the part reference * @param part * the part * @param page * the page it belongs to */ public PartSite(IWorkbenchPartReference ref, IWorkbenchPart part, IWorkbenchPage page) { this.partReference = ref; this.part = part; this.page = page; extensionID = "org.eclipse.ui.UnknownID"; //$NON-NLS-1$ extensionName = "Unknown Name"; //$NON-NLS-1$ // Initialize the service locator. final WorkbenchWindow workbenchWindow = (WorkbenchWindow) page.getWorkbenchWindow(); IServiceLocatorCreator slc = (IServiceLocatorCreator) workbenchWindow .getService(IServiceLocatorCreator.class); this.serviceLocator = (ServiceLocator) slc.createServiceLocator( workbenchWindow, null, new IDisposable(){ public void dispose() { final Control control = getPane().getControl(); if (control != null && !control.isDisposed()) { getPane().doHide(); } } }); initializeDefaultServices(); } /** * Initialize the local services. */ private void initializeDefaultServices() { serviceLocator.registerService(IWorkbenchLocationService.class, new WorkbenchLocationService(IServiceScopes.PARTSITE_SCOPE, getWorkbenchWindow().getWorkbench(), getWorkbenchWindow(), this, null, null, 2)); } /** * Dispose the contributions. */ public void dispose() { if (menuExtenders != null) { HashSet managers = new HashSet(menuExtenders.size()); for (int i = 0; i < menuExtenders.size(); i++) { PopupMenuExtender ext = (PopupMenuExtender) menuExtenders.get(i); managers.add(ext.getManager()); ext.dispose(); } if (managers.size()>0) { for (Iterator iterator = managers.iterator(); iterator .hasNext();) { MenuManager mgr = (MenuManager) iterator.next(); mgr.dispose(); } } menuExtenders = null; } if (keyBindingService != null) { keyBindingService.dispose(); keyBindingService = null; } if (progressService != null) { progressService.dispose(); progressService = null; } if (serviceLocator != null) { serviceLocator.dispose(); } part = null; } /** * Returns the action bars for the part. If this part is a view then it has * exclusive use of the action bars. If this part is an editor then the * action bars are shared among this editor and other editors of the same * type. */ public IActionBars getActionBars() { return actionBars; } /** * Returns the part registry extension ID. * * @return the registry extension ID */ public String getId() { return extensionID; } /** * Returns the page containing this workbench site's part. * * @return the page containing this part */ public IWorkbenchPage getPage() { return page; } /** * Gets the part pane. */ public PartPane getPane() { return ((WorkbenchPartReference) partReference).getPane(); } /** * Returns the part. */ public IWorkbenchPart getPart() { return part; } /** * Returns the part reference. */ public IWorkbenchPartReference getPartReference() { return partReference; } /** * Returns the part registry plugin ID. It cannot be <code>null</code>. * * @return the registry plugin ID */ public String getPluginId() { return pluginID; } /** * Returns the registered name for this part. */ public String getRegisteredName() { return extensionName; } /** * Returns the selection provider for a part. */ public ISelectionProvider getSelectionProvider() { return selectionProvider; } /** * Returns the shell containing this part. * * @return the shell containing this part */ public Shell getShell() { PartPane pane = getPane(); // Compatibility: This method should not be used outside the UI // thread... but since this condition // was not always in the JavaDoc, we still try to return our best guess // about the shell if it is // called from the wrong thread. Display currentDisplay = Display.getCurrent(); if (currentDisplay == null || currentDisplay != getWorkbenchWindow().getWorkbench() .getDisplay()) { // Uncomment this to locate places that try to access the shell from // a background thread // WorkbenchPlugin.log(new Exception("Error: // IWorkbenchSite.getShell() was called outside the UI thread. Fix // this code.")); //$NON-NLS-1$ return getWorkbenchWindow().getShell(); } if (pane == null) { return getWorkbenchWindow().getShell(); } Shell s = pane.getShell(); if (s == null) { return getWorkbenchWindow().getShell(); } return s; } /** * Returns the workbench window containing this part. * * @return the workbench window containing this part */ public IWorkbenchWindow getWorkbenchWindow() { return page.getWorkbenchWindow(); } /** * Register a popup menu for extension. */ public void registerContextMenu(String menuID, MenuManager menuMgr, ISelectionProvider selProvider) { if (menuExtenders == null) { menuExtenders = new ArrayList(1); } registerContextMenu(menuID, menuMgr, selProvider, true, getPart(), menuExtenders); } /** * Register a popup menu with the default id for extension. */ public void registerContextMenu(MenuManager menuMgr, ISelectionProvider selProvider) { registerContextMenu(getId(), menuMgr, selProvider); } // getContextMenuIds() added by Dan Rubel (dan_rubel@instantiations.com) /** * Get the registered popup menu identifiers */ public String[] getContextMenuIds() { if (menuExtenders == null) { return new String[0]; } ArrayList menuIds = new ArrayList(menuExtenders.size()); for (Iterator iter = menuExtenders.iterator(); iter.hasNext();) { final PopupMenuExtender extender = (PopupMenuExtender) iter.next(); menuIds.addAll(extender.getMenuIds()); } return (String[]) menuIds.toArray(new String[menuIds.size()]); } /** * Sets the action bars for the part. */ public void setActionBars(SubActionBars bars) { actionBars = bars; } /** * Sets the configuration element for a part. */ public void setConfigurationElement(IConfigurationElement configElement) { // Get extension ID. extensionID = configElement.getAttribute("id"); //$NON-NLS-1$ // Get plugin ID. pluginID = configElement.getNamespace(); // Get extension name. String name = configElement.getAttribute("name"); //$NON-NLS-1$ if (name != null) { extensionName = name; } } protected void setPluginId(String pluginId) { this.pluginID = pluginId; } /** * Sets the part registry extension ID. * * @param id * the registry extension ID */ protected void setId(String id) { extensionID = id; } /** * Sets the part. */ public void setPart(IWorkbenchPart newPart) { part = newPart; } /** * Sets the registered name for this part. * * @param name * the registered name */ protected void setRegisteredName(String name) { extensionName = name; } /** * Set the selection provider for a part. */ public void setSelectionProvider(ISelectionProvider provider) { selectionProvider = provider; } /* * @see IWorkbenchPartSite#getKeyBindingService() */ public IKeyBindingService getKeyBindingService() { if (keyBindingService == null) { keyBindingService = new KeyBindingService(this); // TODO why is this here? and it should be using HandlerSubmissions // directly.. if (this instanceof EditorSite) { EditorActionBuilder.ExternalContributor contributor = (EditorActionBuilder.ExternalContributor) ((EditorSite) this) .getExtensionActionBarContributor(); if (contributor != null) { ActionDescriptor[] actionDescriptors = contributor .getExtendedActions(); if (actionDescriptors != null) { for (int i = 0; i < actionDescriptors.length; i++) { ActionDescriptor actionDescriptor = actionDescriptors[i]; if (actionDescriptor != null) { IAction action = actionDescriptors[i] .getAction(); if (action != null && action.getActionDefinitionId() != null) { keyBindingService.registerAction(action); } } } } } } } return keyBindingService; } protected String getInitialScopeId() { return null; } /** * Get an adapter for this type. * * @param adapter * @return */ public final Object getAdapter(Class adapter) { if (IWorkbenchSiteProgressService.class == adapter) { return getSiteProgressService(); } if (IWorkbenchPartTestable.class == adapter) { return new WorkbenchPartTestable(this); } return Platform.getAdapterManager().getAdapter(this, adapter); } public void activateActionBars(boolean forceVisibility) { if (actionBars != null) { actionBars.activate(forceVisibility); } } public void deactivateActionBars(boolean forceHide) { if (actionBars != null) { actionBars.deactivate(forceHide); } } /** * Get a progress service for the receiver. * * @return WorkbenchSiteProgressService */ WorkbenchSiteProgressService getSiteProgressService() { if (progressService == null) { progressService = new WorkbenchSiteProgressService(this); } return progressService; } public final Object getService(final Class key) { return serviceLocator.getService(key); } public final boolean hasService(final Class key) { return serviceLocator.hasService(key); } /** * Prints out the identifier, the plug-in identifier and the registered * name. This is for debugging purposes only. * * @since 3.2 */ public String toString() { final StringBuffer buffer = new StringBuffer(); buffer.append("PartSite(id="); //$NON-NLS-1$ buffer.append(getId()); buffer.append(",pluginId="); //$NON-NLS-1$ buffer.append(getPluginId()); buffer.append(",registeredName="); //$NON-NLS-1$ buffer.append(getRegisteredName()); buffer.append(",hashCode="); //$NON-NLS-1$ buffer.append(hashCode()); buffer.append(')'); return buffer.toString(); } }