blob: f95ee0154226d56479f3a5716c40ddc163692647 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 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
*******************************************************************************/
package org.eclipse.bpel.common.ui.composite;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.bpel.common.ui.CommonUIPlugin;
import org.eclipse.bpel.common.ui.Messages;
import org.eclipse.bpel.common.ui.Utils;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.CoolBarManager;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.ICoolBarManager;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IActionBars2;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.internal.EditorActionBuilder;
import org.eclipse.ui.internal.EditorManager;
import org.eclipse.ui.internal.EditorReference;
import org.eclipse.ui.internal.EditorSite;
import org.eclipse.ui.internal.WorkbenchPage;
import org.eclipse.ui.internal.registry.EditorDescriptor;
import org.eclipse.ui.services.IServiceLocator;
/**
* Handles embedded editor's contributions activation and deactivation.
*/
public class EditorInViewManager {
protected WorkbenchPage page;
protected IViewSite fViewSite;
protected Map<String,EditorDescriptor> idToDescriptor;
protected EditorManager eclipseEditorManager;
private static final String EXTPT_EMBEDDED_EDITORS = "embeddedEditors"; //$NON-NLS-1$
private static final String CHILD_EDITOR = "editor"; //$NON-NLS-1$
private static final String ATT_EDITOR_ID = "id"; //$NON-NLS-1$
private static final String ATT_EDITOR_CLASS = "class"; //$NON-NLS-1$
/**
* Brand new EditorInView manager.
*
* @param viewSite
*/
public EditorInViewManager (IViewSite viewSite) {
this.fViewSite = viewSite;
idToDescriptor = new HashMap<String,EditorDescriptor>(10);
page = (WorkbenchPage) viewSite.getPage();
}
/**
* Creates and initializes an IEditorPart given its id and input.
* @param editorId
* @param input
* @return the editor part.
* @throws CoreException
*/
public IEditorPart createEditor(String editorId, IEditorInput input) throws CoreException {
IEditorPart editor = instantiateEditor(editorId);
EditorSite site = createEditorSite(editorId, input, editor);
editor.init(site, input);
// Force menus to be created.
// TODO: The following lines do not seem to be necessary anymore.
// Keep them at least until Eclipse 3.0 is released so that if we
// face the same problem again we can workaround it.
// IMenuManager menuManager = site.getActionBars().getMenuManager();
// menuManager.setVisible(false);
// menuManager.setVisible(true);
return editor;
}
/**
* Instantiates an editor given its id. The editor id has to be declared
* through the <code>embeddedEditors</code> extension point.
*
* @throws CoreException if the editorId is not found
*/
protected IEditorPart instantiateEditor (String editorId) throws CoreException {
EditorDescriptor descriptor = idToDescriptor.get(editorId);
if (descriptor == null) {
descriptor = readDescriptor(editorId);
if (descriptor == null) {
IStatus status = new Status(IStatus.ERROR, CommonUIPlugin.PLUGIN_ID, ICompositeEditorConstants.COULD_NOT_INSTANTIATE_EDITOR, NLS.bind(Messages.CompositeEditorManager_Could_not_find_editor, (new Object[] { editorId })), null);
throw new CoreException(status);
}
}
return (IEditorPart) descriptor.getConfigurationElement().createExecutableExtension(ATT_EDITOR_CLASS);
}
/**
* Creates an editor descriptor based on the information defined in the <code>embeddedEditors</code>
* extension point for the given editorId.
*
* @return the editor descriptor or <code>null</code> if there none for the given editorId
*/
protected EditorDescriptor readDescriptor (String editorId) {
for(IConfigurationElement element : Utils.getConfigurationElements(EXTPT_EMBEDDED_EDITORS)) {
if (CHILD_EDITOR.equals(element.getName()) == false) {
continue;
}
String extensionId = element.getAttribute(ATT_EDITOR_ID);
if (extensionId == null) {
// the editor id is mandatory - log error
String pluginId = element.getDeclaringExtension().getNamespace();
IStatus status = new Status(IStatus.ERROR, pluginId, ICompositeEditorConstants.MISSING_ATTRIBUTE, Messages.CompositeEditorManager_5, null);
CommonUIPlugin.getDefault().getLog().log(status);
continue;
}
if (editorId.equals(extensionId)) {
// Use reflection to create and set state on an editor descriptor
// This was done to avoid copying the class to this package
try {
Constructor constuctor = EditorDescriptor.class.getDeclaredConstructor(new Class[0]);
constuctor.setAccessible(true);
EditorDescriptor descriptor = (EditorDescriptor)constuctor.newInstance(new Object[0]);
Method method = descriptor.getClass().getDeclaredMethod("setID", new Class[] {String.class});
method.setAccessible(true);
method.invoke(descriptor, new Object[]{editorId});
method = descriptor.getClass().getDeclaredMethod("setConfigurationElement", new Class[] {IConfigurationElement.class});
method.setAccessible(true);
method.invoke(descriptor, new Object[]{element});
method = descriptor.getClass().getDeclaredMethod("setName", new Class[] {String.class});
method.setAccessible(true);
method.invoke(descriptor, new Object[]{editorId});
idToDescriptor.put(editorId, descriptor);
return descriptor;
} catch (SecurityException e) {
CommonUIPlugin.getDefault().createErrorStatus("Problem creating descriptor for " + editorId, e, true);
} catch (IllegalArgumentException e) {
CommonUIPlugin.getDefault().createErrorStatus("Problem creating descriptor for " + editorId, e, true);
} catch (NoSuchMethodException e) {
CommonUIPlugin.getDefault().createErrorStatus("Problem creating descriptor for " + editorId, e, true);
} catch (InstantiationException e) {
CommonUIPlugin.getDefault().createErrorStatus("Problem creating descriptor for " + editorId, e, true);
} catch (IllegalAccessException e) {
CommonUIPlugin.getDefault().createErrorStatus("Problem creating descriptor for " + editorId, e, true);
} catch (InvocationTargetException e) {
CommonUIPlugin.getDefault().createErrorStatus("Problem creating descriptor for " + editorId, e, true);
}
}
}
return null;
}
/**
* Creates and populates an editor site for the given editor.
*/
protected EditorSite createEditorSite(String editorId, IEditorInput input, IEditorPart editor) {
EditorDescriptor descriptor = idToDescriptor.get(editorId);
IEditorReference ref = new EditorReference(getEditorManager(), input, descriptor);
EditorSite site = new EditorInViewSite(fViewSite, ref, editor, page, descriptor);
IEditorActionBarContributor contributor = descriptor.createActionBarContributor();
site.setActionBars(createEditorActionBars(descriptor, contributor, site));
return site;
}
/**
* Creates the action bars for the given editor. It also searches for editor
* contribution extensions.
*/
protected CompositeEditorActionBars createEditorActionBars(EditorDescriptor descriptor, IEditorActionBarContributor contributor, EditorSite site) {
String type = String.valueOf(System.currentTimeMillis());
// IActionBars viewActionBars = viewSite.getActionBars();
// IActionBars2 parentActionBars = getIActionBars2Wrapper(viewActionBars);
CompositeEditorActionBars actionBars = new CompositeEditorActionBars(page, site, type);
if (contributor != null) {
actionBars.setEditorContributor(contributor);
contributor.init(actionBars, page);
}
// Read action extensions.
EditorActionBuilder builder = new EditorActionBuilder();
IEditorActionBarContributor extension = builder.readActionExtensions(descriptor /*WDG , actionBars*/);
if (extension != null) {
actionBars.setExtensionContributor(extension);
extension.init(actionBars, page);
}
return actionBars;
}
/**
* Creates an IActionBars2 as a wrapper of an IActionBars.
*/
protected IActionBars2 getIActionBars2Wrapper(final IActionBars actionBars) {
return new IActionBars2() {
public ICoolBarManager getCoolBarManager() {
return new CoolBarManager();
}
public void clearGlobalActionHandlers() {
actionBars.clearGlobalActionHandlers();
}
public IAction getGlobalActionHandler(String actionId) {
return actionBars.getGlobalActionHandler(actionId);
}
public IMenuManager getMenuManager() {
// Returns the page menu manager so that the editor
// can contribute to any menu (Edit, Navigate, etc...).
return page.getActionBars().getMenuManager();
}
public IStatusLineManager getStatusLineManager() {
return actionBars.getStatusLineManager();
}
public IToolBarManager getToolBarManager() {
return actionBars.getToolBarManager();
}
public void setGlobalActionHandler(String actionId, IAction handler) {
actionBars.setGlobalActionHandler(actionId, handler);
}
public void updateActionBars() {
actionBars.updateActionBars();
}
public IServiceLocator getServiceLocator() {
return actionBars.getServiceLocator();
}
};
}
/**
* Activate contributions.
* @param editor
*/
public void activate(IEditorPart editor) {
editor.setFocus();
IEditorSite site = editor.getEditorSite();
CompositeEditorActionBars actionBars = (CompositeEditorActionBars) site.getActionBars();
actionBars.partChanged(editor);
actionBars.activate(true);
((EditorInViewSite) site).activate();
}
/**
* Deactivate contributions.
* @param editor
*/
public void deactivate(IEditorPart editor) {
if (editor != null) {
CompositeEditorActionBars actionBars = (CompositeEditorActionBars) editor.getEditorSite().getActionBars();
actionBars.deactivate(true);
IEditorSite site = editor.getEditorSite();
((EditorInViewSite) site).deactivate();
}
}
/**
* Creates an embedded editor corresponding to the given editorId.
* <p>
* It is important to notice that the returned editor will never be
* the workbench active part.
* <p>
* @param editorId the embedded editor id
* @param editorComposite the editor's parent composite
* @return IEditorPart the embedded editor instance
*
*/
public IEditorPart createEditor(String editorId, IEditorInput input, Composite editorComposite) throws CoreException {
final IEditorPart editor = createEditor(editorId, input);
Composite composite = new Composite(editorComposite, SWT.NONE);
composite.setLayout(new FillLayout());
editor.createPartControl(composite);
// This is the fundamental part of our implementation.
// Editors are activated when we get an Activate
// event from the editor's composite.
associate(editor, composite);
return editor;
}
/**
* Associates the control with the given editor. When the control
* is activated all the editor contributions will be activated
* as well. This is useful when the CompositeEditor is not only
* composed by embedded editor but also by other controls. If no editor
* is associated with these controls the available contributions
* (menus, toolbars, status line, etc...) will be the contributions
* for the last active editor and might cause confusion to the user.
*/
protected void associate(final IEditorPart editor, Control control) {
control.addListener(SWT.Activate, new Listener() {
public void handleEvent(Event event) {
activate(editor);
}
});
control.addListener(SWT.Deactivate, new Listener() {
public void handleEvent(Event event) {
deactivate(editor);
}
});
}
/**
* Removes the given editor from this composite editor. If the given
* editor is the current active editor the main editor will be activated
* instead. The main editor cannot be disconnected by calling this
* method.
*
* @param editor
*/
public void disposeEditor(IEditorPart editor) {
EditorInViewSite site = (EditorInViewSite) editor.getSite();
CompositeEditorActionBars actionBars = (CompositeEditorActionBars) site.getActionBars();
actionBars.dispose();
site.dispose();
try {
editor.dispose();
} catch (Throwable t) {
System.out.println("disposeEditor: " + editor);
}
}
/**
* TODO: remove this internal access
*/
public EditorManager getEditorManager() {
if (eclipseEditorManager == null) {
try {
Field field = WorkbenchPage.class.getDeclaredField("editorMgr"); //$NON-NLS-1$
field.setAccessible(true);
eclipseEditorManager = (EditorManager) field.get(page);
} catch (Exception e) {
CommonUIPlugin.log(e);
}
}
return eclipseEditorManager;
}
}