| /******************************************************************************* |
| * Copyright (c) 2000, 2007 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.pde.internal.ui.editor.plugin; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.action.ToolBarManager; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.ITreeContentProvider; |
| import org.eclipse.jface.viewers.LabelProvider; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.StructuredViewer; |
| import org.eclipse.jface.viewers.TreeViewer; |
| import org.eclipse.jface.wizard.WizardDialog; |
| import org.eclipse.pde.core.IModelChangedEvent; |
| import org.eclipse.pde.core.IModelChangedListener; |
| import org.eclipse.pde.core.plugin.IExtensions; |
| import org.eclipse.pde.core.plugin.IPluginAttribute; |
| import org.eclipse.pde.core.plugin.IPluginBase; |
| import org.eclipse.pde.core.plugin.IPluginElement; |
| import org.eclipse.pde.core.plugin.IPluginExtension; |
| import org.eclipse.pde.core.plugin.IPluginModelBase; |
| import org.eclipse.pde.core.plugin.IPluginObject; |
| import org.eclipse.pde.core.plugin.IPluginParent; |
| import org.eclipse.pde.core.plugin.ISharedExtensionsModel; |
| import org.eclipse.pde.internal.core.PDECore; |
| import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase; |
| import org.eclipse.pde.internal.core.ischema.ISchema; |
| import org.eclipse.pde.internal.core.ischema.ISchemaComplexType; |
| import org.eclipse.pde.internal.core.ischema.ISchemaElement; |
| import org.eclipse.pde.internal.core.schema.SchemaRegistry; |
| import org.eclipse.pde.internal.core.text.IDocumentNode; |
| import org.eclipse.pde.internal.core.text.plugin.IDocumentElement; |
| import org.eclipse.pde.internal.core.text.plugin.IDocumentExtension; |
| import org.eclipse.pde.internal.ui.PDELabelProvider; |
| import org.eclipse.pde.internal.ui.PDEPlugin; |
| import org.eclipse.pde.internal.ui.PDEPluginImages; |
| import org.eclipse.pde.internal.ui.PDEUIMessages; |
| import org.eclipse.pde.internal.ui.editor.PDEFormPage; |
| import org.eclipse.pde.internal.ui.editor.TreeSection; |
| import org.eclipse.pde.internal.ui.editor.actions.CollapseAction; |
| import org.eclipse.pde.internal.ui.editor.actions.SortAction; |
| import org.eclipse.pde.internal.ui.editor.contentassist.XMLElementProposalComputer; |
| import org.eclipse.pde.internal.ui.elements.DefaultContentProvider; |
| import org.eclipse.pde.internal.ui.parts.TreePart; |
| import org.eclipse.pde.internal.ui.search.PluginSearchActionGroup; |
| import org.eclipse.pde.internal.ui.util.SWTUtil; |
| import org.eclipse.pde.internal.ui.util.SharedLabelProvider; |
| import org.eclipse.pde.internal.ui.wizards.extension.ExtensionEditorWizard; |
| import org.eclipse.pde.internal.ui.wizards.extension.NewExtensionWizard; |
| import org.eclipse.pde.ui.IExtensionEditorWizard; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.BusyIndicator; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.graphics.Cursor; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.ToolBar; |
| import org.eclipse.swt.widgets.Tree; |
| import org.eclipse.swt.widgets.TreeItem; |
| import org.eclipse.ui.actions.ActionContext; |
| import org.eclipse.ui.actions.ActionFactory; |
| import org.eclipse.ui.dialogs.PatternFilter; |
| import org.eclipse.ui.forms.widgets.FormToolkit; |
| import org.eclipse.ui.forms.widgets.Section; |
| |
| public class ExtensionsSection extends TreeSection implements IModelChangedListener, IPropertyChangeListener { |
| private TreeViewer fExtensionTree; |
| private Image fExtensionImage; |
| private Image fGenericElementImage; |
| private FormFilteredTree fFilteredTree; |
| private SchemaRegistry fSchemaRegistry; |
| private Action fNewExtensionAction; |
| private Hashtable fEditorWizards; |
| private SortAction fSortAction; |
| private CollapseAction fCollapseAction; |
| |
| private static final String[] COMMON_LABEL_PROPERTIES = { |
| "label", //$NON-NLS-1$ |
| "name", //$NON-NLS-1$ |
| "id"}; //$NON-NLS-1$ |
| |
| class ExtensionContentProvider extends DefaultContentProvider |
| implements |
| ITreeContentProvider { |
| public Object[] getChildren(Object parent) { |
| Object[] children = null; |
| if (parent instanceof IPluginBase) |
| children = ((IPluginBase) parent).getExtensions(); |
| else if (parent instanceof IPluginExtension) { |
| children = ((IPluginExtension) parent).getChildren(); |
| } else if (parent instanceof IPluginElement) { |
| children = ((IPluginElement) parent).getChildren(); |
| } |
| if (children == null) |
| children = new Object[0]; |
| return children; |
| } |
| public boolean hasChildren(Object parent) { |
| return getChildren(parent).length > 0; |
| } |
| public Object getParent(Object child) { |
| if (child instanceof IPluginExtension) { |
| return ((IPluginModelBase)getPage().getModel()).getPluginBase(); |
| } |
| if (child instanceof IPluginObject) |
| return ((IPluginObject) child).getParent(); |
| return null; |
| } |
| public Object[] getElements(Object parent) { |
| return getChildren(parent); |
| } |
| } |
| class ExtensionLabelProvider extends LabelProvider { |
| public String getText(Object obj) { |
| return resolveObjectName(obj); |
| } |
| public Image getImage(Object obj) { |
| return resolveObjectImage(obj); |
| } |
| } |
| public ExtensionsSection(PDEFormPage page, Composite parent) { |
| super(page, parent, Section.DESCRIPTION, new String[]{ |
| PDEUIMessages.ManifestEditor_DetailExtension_new, |
| PDEUIMessages.ManifestEditor_DetailExtension_edit, |
| null, |
| PDEUIMessages.ManifestEditor_DetailExtension_up, |
| PDEUIMessages.ManifestEditor_DetailExtension_down}); |
| fHandleDefaultButton = false; |
| } |
| private static void addItemsForExtensionWithSchema(MenuManager menu, |
| IPluginExtension extension, IPluginParent parent) { |
| ISchema schema = getSchema(extension); |
| String tagName = (parent == extension ? "extension" : parent.getName()); //$NON-NLS-1$ |
| ISchemaElement elementInfo = schema.findElement(tagName); |
| |
| if ((elementInfo != null) && |
| (elementInfo.getType() instanceof ISchemaComplexType) && |
| (parent instanceof IDocumentNode)) { |
| // We have a schema complex type. Either the element has attributes |
| // or the element has children. |
| // Generate the list of element proposals |
| HashSet elementSet = XMLElementProposalComputer |
| .computeElementProposal(elementInfo, (IDocumentNode)parent); |
| // Create a corresponding menu entry for each element proposal |
| Iterator iterator = elementSet.iterator(); |
| while (iterator.hasNext()) { |
| Action action = new NewElementAction((ISchemaElement) iterator |
| .next(), parent); |
| menu.add(action); |
| } |
| } |
| } |
| |
| /** |
| * @param parent |
| * @return |
| */ |
| private static ISchema getSchema(IPluginParent parent) { |
| if (parent instanceof IPluginExtension) { |
| return getSchema((IPluginExtension)parent); |
| } else if (parent instanceof IPluginElement) { |
| return getSchema((IPluginElement)parent); |
| } else { |
| return null; |
| } |
| } |
| |
| private static ISchema getSchema(IPluginExtension extension) { |
| String point = extension.getPoint(); |
| SchemaRegistry registry = PDECore.getDefault().getSchemaRegistry(); |
| return registry.getSchema(point); |
| } |
| |
| /** |
| * @param element |
| * @return |
| */ |
| static ISchemaElement getSchemaElement(IPluginElement element) { |
| ISchema schema = getSchema(element); |
| if (schema != null) { |
| return schema.findElement(element.getName()); |
| } |
| return null; |
| } |
| |
| /** |
| * @param element |
| * @return |
| */ |
| private static ISchema getSchema(IPluginElement element) { |
| IPluginObject parent = element.getParent(); |
| while (parent != null && !(parent instanceof IPluginExtension)) { |
| parent = parent.getParent(); |
| } |
| if (parent != null) { |
| return getSchema((IPluginExtension) parent); |
| } |
| return null; |
| } |
| |
| public void createClient(Section section, FormToolkit toolkit) { |
| initializeImages(); |
| Composite container = createClientContainer(section, 2, toolkit); |
| TreePart treePart = getTreePart(); |
| createViewerPartControl(container, SWT.MULTI, 2, toolkit); |
| fExtensionTree = treePart.getTreeViewer(); |
| fExtensionTree.setContentProvider(new ExtensionContentProvider()); |
| fExtensionTree.setLabelProvider(new ExtensionLabelProvider()); |
| toolkit.paintBordersFor(container); |
| section.setClient(container); |
| section.setDescription(PDEUIMessages.ExtensionsSection_sectionDescExtensionsMaster); |
| // See Bug # 160554: Set text before text client |
| section.setText(PDEUIMessages.ManifestEditor_DetailExtension_title); |
| initialize((IPluginModelBase) getPage().getModel()); |
| createSectionToolbar(section, toolkit); |
| // Create the adapted listener for the filter entry field |
| fFilteredTree.createUIListenerEntryFilter(this); |
| } |
| |
| /** |
| * @param section |
| * @param toolkit |
| */ |
| private void createSectionToolbar(Section section, FormToolkit toolkit) { |
| ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT); |
| ToolBar toolbar = toolBarManager.createControl(section); |
| final Cursor handCursor = new Cursor(Display.getCurrent(), SWT.CURSOR_HAND); |
| toolbar.setCursor(handCursor); |
| // Cursor needs to be explicitly disposed |
| toolbar.addDisposeListener(new DisposeListener() { |
| public void widgetDisposed(DisposeEvent e) { |
| if ((handCursor != null) && |
| (handCursor.isDisposed() == false)) { |
| handCursor.dispose(); |
| } |
| } |
| }); |
| // Add sort action to the tool bar |
| fSortAction = new SortAction(fExtensionTree, |
| PDEUIMessages.ExtensionsPage_sortAlpha, null, null, this); |
| toolBarManager.add(fSortAction); |
| // Add collapse action to the tool bar |
| fCollapseAction = new CollapseAction(fExtensionTree, |
| PDEUIMessages.ExtensionsPage_collapseAll); |
| toolBarManager.add(fCollapseAction); |
| |
| toolBarManager.update(true); |
| |
| section.setTextClient(toolbar); |
| } |
| |
| protected void selectionChanged(IStructuredSelection selection) { |
| getPage().getPDEEditor().setSelection(selection); |
| updateUpDownButtons(selection.getFirstElement()); |
| getTreePart().setButtonEnabled(1, isSelectionEditable(selection)); |
| } |
| protected void handleDoubleClick(IStructuredSelection selection) { |
| /* |
| * PropertiesAction action = new |
| * PropertiesAction(getFormPage().getEditor()); action.run(); |
| */ |
| } |
| protected void buttonSelected(int index) { |
| switch (index) { |
| case 0 : |
| handleNew(); |
| break; |
| case 1 : |
| handleEdit(); |
| break; |
| case 2: |
| // blank |
| break; |
| case 3 : |
| handleMove(true); |
| break; |
| case 4 : |
| handleMove(false); |
| break; |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.forms.AbstractFormPart#dispose() |
| */ |
| public void dispose() { |
| // Explicitly call the dispose method on the extensions tree |
| if (fFilteredTree != null) { |
| fFilteredTree.dispose(); |
| } |
| fEditorWizards = null; |
| IPluginModelBase model = (IPluginModelBase) getPage().getPDEEditor() |
| .getAggregateModel(); |
| if (model!=null) |
| model.removeModelChangedListener(this); |
| super.dispose(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.pde.internal.ui.editor.PDESection#doGlobalAction(java.lang.String) |
| */ |
| public boolean doGlobalAction(String actionId) { |
| |
| if (!isEditable()) { return false; } |
| |
| if (actionId.equals(ActionFactory.DELETE.getId())) { |
| handleDelete(); |
| return true; |
| } |
| if (actionId.equals(ActionFactory.CUT.getId())) { |
| // delete here and let the editor transfer |
| // the selection to the clipboard |
| handleDelete(); |
| return false; |
| } |
| if (actionId.equals(ActionFactory.PASTE.getId())) { |
| doPaste(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| public boolean setFormInput(Object object) { |
| if (object instanceof IPluginExtension |
| || object instanceof IPluginElement) { |
| fExtensionTree.setSelection(new StructuredSelection(object), true); |
| return true; |
| } |
| return false; |
| } |
| protected void fillContextMenu(IMenuManager manager) { |
| ISelection selection = fExtensionTree.getSelection(); |
| IStructuredSelection ssel = (IStructuredSelection) selection; |
| IMenuManager newMenu = null; |
| if (ssel.size() == 1) { |
| Object object = ssel.getFirstElement(); |
| if (object instanceof IPluginParent) { |
| IPluginParent parent = (IPluginParent) object; |
| if (parent.getModel().getUnderlyingResource() != null) { |
| newMenu = fillContextMenu(getPage(), parent, manager); |
| manager.add(new Separator()); |
| } |
| } |
| } else if (ssel.size() > 1) { |
| // multiple |
| Action delAction = new Action() { |
| public void run() { |
| handleDelete(); |
| } |
| }; |
| delAction.setText(PDEUIMessages.Actions_delete_label); |
| manager.add(delAction); |
| manager.add(new Separator()); |
| delAction.setEnabled(isEditable()); |
| } |
| if (newMenu == null) { |
| newMenu = new MenuManager(PDEUIMessages.Menus_new_label); |
| manager.add(newMenu); |
| } |
| if (ssel.size() == 1) { |
| manager.add(new Separator()); |
| Object object = ssel.getFirstElement(); |
| if (object instanceof IPluginExtension) { |
| PluginSearchActionGroup actionGroup = new PluginSearchActionGroup(); |
| actionGroup.setContext(new ActionContext(selection)); |
| actionGroup.fillContextMenu(manager); |
| manager.add(new Separator()); |
| } |
| //manager.add(new PropertiesAction(getFormPage().getEditor())); |
| } |
| if (!newMenu.isEmpty()) |
| newMenu.add(new Separator()); |
| newMenu.add(fNewExtensionAction); |
| manager.add(new Separator()); |
| manager.add(new Separator()); |
| getPage().getPDEEditor().getContributor().addClipboardActions(manager); |
| getPage().getPDEEditor().getContributor().contextMenuAboutToShow( |
| manager, false); |
| |
| } |
| static IMenuManager fillContextMenu(PDEFormPage page, |
| final IPluginParent parent, IMenuManager manager) { |
| return fillContextMenu(page, parent, manager, false); |
| } |
| static IMenuManager fillContextMenu(PDEFormPage page, |
| final IPluginParent parent, IMenuManager manager, |
| boolean addSiblingItems) { |
| return fillContextMenu(page, parent, manager, addSiblingItems, true); |
| } |
| static IMenuManager fillContextMenu(PDEFormPage page, |
| final IPluginParent parent, IMenuManager manager, |
| boolean addSiblingItems, boolean fullMenu) { |
| MenuManager menu = new MenuManager(PDEUIMessages.Menus_new_label); |
| IPluginExtension extension = getExtension(parent); |
| ISchema schema = getSchema(extension); |
| if (schema == null) { |
| menu.add(new NewElementAction(null, parent)); |
| } else { |
| addItemsForExtensionWithSchema(menu, extension, parent); |
| if (addSiblingItems) { |
| IPluginObject parentsParent = parent.getParent(); |
| if (!(parentsParent instanceof IPluginExtension)) { |
| IPluginParent pparent = (IPluginParent) parentsParent; |
| menu.add(new Separator()); |
| addItemsForExtensionWithSchema(menu, extension, pparent); |
| } |
| } |
| } |
| manager.add(menu); |
| manager.add(new Separator()); |
| if (fullMenu) { |
| Action deleteAction = new Action(PDEUIMessages.Actions_delete_label) { |
| public void run() { |
| try { |
| IPluginObject parentsParent = parent.getParent(); |
| if (parent instanceof IPluginExtension) { |
| IPluginBase plugin = (IPluginBase) parentsParent; |
| plugin.remove((IPluginExtension) parent); |
| } else { |
| IPluginParent parentElement = (IPluginParent) parent |
| .getParent(); |
| parentElement.remove(parent); |
| } |
| } catch (CoreException e) { |
| } |
| } |
| }; |
| deleteAction.setEnabled(page.getModel().isEditable()); |
| manager.add(deleteAction); |
| } |
| return menu; |
| } |
| static IPluginExtension getExtension(IPluginParent parent) { |
| while (parent != null && !(parent instanceof IPluginExtension)) { |
| parent = (IPluginParent) parent.getParent(); |
| } |
| return (IPluginExtension) parent; |
| } |
| private void handleDelete() { |
| IStructuredSelection sel = (IStructuredSelection) fExtensionTree |
| .getSelection(); |
| if (sel.isEmpty()) |
| return; |
| for (Iterator iter = sel.iterator(); iter.hasNext();) { |
| IPluginObject object = (IPluginObject) iter.next(); |
| try { |
| if (object instanceof IPluginElement) { |
| IPluginElement ee = (IPluginElement) object; |
| IPluginParent parent = (IPluginParent) ee.getParent(); |
| parent.remove(ee); |
| } else if (object instanceof IPluginExtension) { |
| IPluginExtension extension = (IPluginExtension) object; |
| IPluginBase plugin = extension.getPluginBase(); |
| plugin.remove(extension); |
| } |
| } catch (CoreException e) { |
| PDEPlugin.logException(e); |
| } |
| } |
| } |
| private void handleNew() { |
| final IProject project = getPage().getPDEEditor().getCommonProject(); |
| BusyIndicator.showWhile(fExtensionTree.getTree().getDisplay(), |
| new Runnable() { |
| public void run() { |
| ((ManifestEditor)getPage().getEditor()).ensurePluginContextPresence(); |
| NewExtensionWizard wizard = new NewExtensionWizard( |
| project, (IPluginModelBase) getPage() |
| .getModel(), (ManifestEditor) getPage() |
| .getPDEEditor()) { |
| public boolean performFinish() { |
| return super.performFinish(); |
| } |
| }; |
| WizardDialog dialog = new WizardDialog(PDEPlugin |
| .getActiveWorkbenchShell(), wizard); |
| dialog.create(); |
| SWTUtil.setDialogSize(dialog, 500, 500); |
| dialog.open(); |
| } |
| }); |
| } |
| private void handleEdit(IConfigurationElement element, IStructuredSelection selection) { |
| IProject project = getPage().getPDEEditor().getCommonProject(); |
| IPluginModelBase model = (IPluginModelBase)getPage().getModel(); |
| try { |
| final IExtensionEditorWizard wizard = (IExtensionEditorWizard)element.createExecutableExtension("class"); //$NON-NLS-1$ |
| wizard.init(project, model, selection); |
| BusyIndicator.showWhile(fExtensionTree.getTree().getDisplay(), |
| new Runnable() { |
| public void run() { |
| WizardDialog dialog = new WizardDialog(PDEPlugin |
| .getActiveWorkbenchShell(), wizard); |
| dialog.create(); |
| SWTUtil.setDialogSize(dialog, 500, 500); |
| dialog.open(); |
| } |
| }); |
| } |
| catch (CoreException e) { |
| PDEPlugin.logException(e); |
| } |
| } |
| private void handleEdit() { |
| final IStructuredSelection selection = (IStructuredSelection)fExtensionTree.getSelection(); |
| ArrayList editorWizards = getEditorWizards(selection); |
| if (editorWizards==null) return; |
| if (editorWizards.size()==1) { |
| // open the wizard directly |
| handleEdit((IConfigurationElement)editorWizards.get(0), selection); |
| } |
| else { |
| IProject project = getPage().getPDEEditor().getCommonProject(); |
| IPluginModelBase model = (IPluginModelBase)getPage().getModel(); |
| final ExtensionEditorWizard wizard = new ExtensionEditorWizard(project, model, selection); |
| BusyIndicator.showWhile(fExtensionTree.getTree().getDisplay(), |
| new Runnable() { |
| public void run() { |
| WizardDialog dialog = new WizardDialog(PDEPlugin |
| .getActiveWorkbenchShell(), wizard); |
| dialog.create(); |
| SWTUtil.setDialogSize(dialog, 500, 500); |
| dialog.open(); |
| } |
| }); |
| } |
| } |
| private ArrayList getEditorWizards(IStructuredSelection selection) { |
| if (selection.size()!=1) return null; |
| Object obj = selection.getFirstElement(); |
| String pointId = null; |
| if (obj instanceof IPluginExtension) { |
| pointId = ((IPluginExtension)obj).getPoint(); |
| } |
| else if (obj instanceof IPluginElement) { |
| IPluginObject parent = ((IPluginElement)obj).getParent(); |
| while (parent!=null) { |
| if (parent instanceof IPluginExtension) { |
| pointId = ((IPluginExtension)parent).getPoint(); |
| break; |
| } |
| parent = parent.getParent(); |
| } |
| } |
| if (pointId==null) return null; |
| if (fEditorWizards==null) |
| loadExtensionWizards(); |
| return (ArrayList)fEditorWizards.get(pointId); |
| } |
| |
| private void loadExtensionWizards() { |
| fEditorWizards = new Hashtable(); |
| IConfigurationElement [] elements = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.pde.ui.newExtension"); //$NON-NLS-1$ |
| for (int i=0; i<elements.length; i++) { |
| IConfigurationElement element = elements[i]; |
| if (element.getName().equals("editorWizard")) { //$NON-NLS-1$ |
| String pointId = element.getAttribute("point"); //$NON-NLS-1$ |
| if (pointId==null) continue; |
| ArrayList list = (ArrayList)fEditorWizards.get(pointId); |
| if (list==null) { |
| list = new ArrayList(); |
| fEditorWizards.put(pointId, list); |
| } |
| list.add(element); |
| } |
| } |
| } |
| private boolean isSelectionEditable(IStructuredSelection selection) { |
| if (!getPage().getModel().isEditable()) |
| return false; |
| return getEditorWizards(selection)!=null; |
| } |
| |
| public void initialize(IPluginModelBase model) { |
| fExtensionTree.setInput(model.getPluginBase()); |
| selectFirstExtension(); |
| boolean editable = model.isEditable(); |
| TreePart treePart = getTreePart(); |
| treePart.setButtonEnabled(0, editable); |
| treePart.setButtonEnabled(1, false); |
| treePart.setButtonEnabled(3, false); |
| treePart.setButtonEnabled(4, false); |
| model.addModelChangedListener(this); |
| fNewExtensionAction = new Action() { |
| public void run() { |
| handleNew(); |
| } |
| }; |
| fNewExtensionAction.setText(PDEUIMessages.ManifestEditor_DetailExtension_newExtension); |
| fNewExtensionAction |
| .setImageDescriptor(PDEPluginImages.DESC_EXTENSION_OBJ); |
| fNewExtensionAction.setEnabled(editable); |
| } |
| private void selectFirstExtension() { |
| Tree tree = fExtensionTree.getTree(); |
| TreeItem [] items = tree.getItems(); |
| if (items.length==0) return; |
| TreeItem firstItem = items[0]; |
| Object obj = firstItem.getData(); |
| fExtensionTree.setSelection(new StructuredSelection(obj)); |
| } |
| void fireSelection() { |
| fExtensionTree.setSelection(fExtensionTree.getSelection()); |
| } |
| public void initializeImages() { |
| PDELabelProvider provider = PDEPlugin.getDefault().getLabelProvider(); |
| fExtensionImage = provider.get(PDEPluginImages.DESC_EXTENSION_OBJ); |
| fGenericElementImage = provider |
| .get(PDEPluginImages.DESC_GENERIC_XML_OBJ); |
| } |
| public void refresh() { |
| IPluginModelBase model = (IPluginModelBase)getPage().getModel(); |
| fExtensionTree.setInput(model.getPluginBase()); |
| selectFirstExtension(); |
| getManagedForm().fireSelectionChanged(ExtensionsSection.this, |
| fExtensionTree.getSelection()); |
| super.refresh(); |
| } |
| |
| public void modelChanged(IModelChangedEvent event) { |
| if (event.getChangeType() == IModelChangedEvent.WORLD_CHANGED) { |
| markStale(); |
| return; |
| } |
| Object changeObject = event.getChangedObjects()[0]; |
| if (changeObject instanceof IPluginBase |
| && event.getChangeType() == IModelChangedEvent.CHANGE |
| && event.getChangedProperty().equals( |
| IExtensions.P_EXTENSION_ORDER)) { |
| IStructuredSelection sel = (IStructuredSelection) fExtensionTree |
| .getSelection(); |
| IPluginExtension extension = (IPluginExtension) sel |
| .getFirstElement(); |
| fExtensionTree.refresh(); |
| fExtensionTree.setSelection(new StructuredSelection(extension)); |
| return; |
| } |
| if (changeObject instanceof IPluginExtension |
| || (changeObject instanceof IPluginElement && ((IPluginElement)changeObject).getParent() instanceof IPluginParent)) { |
| IPluginObject pobj = (IPluginObject) changeObject; |
| IPluginObject parent = changeObject instanceof IPluginExtension |
| ? ((IPluginModelBase) getPage().getModel()).getPluginBase() |
| : pobj.getParent(); |
| if (event.getChangeType() == IModelChangedEvent.INSERT) { |
| fExtensionTree.add(parent, pobj); |
| fExtensionTree.setSelection( |
| new StructuredSelection(changeObject), true); |
| fExtensionTree.getTree().setFocus(); |
| } else if (event.getChangeType() == IModelChangedEvent.REMOVE) { |
| fExtensionTree.remove(pobj); |
| } else { |
| if (event.getChangedProperty().equals( |
| IPluginParent.P_SIBLING_ORDER)) { |
| IStructuredSelection sel = (IStructuredSelection) fExtensionTree |
| .getSelection(); |
| IPluginObject child = (IPluginObject) sel.getFirstElement(); |
| fExtensionTree.refresh(child.getParent()); |
| fExtensionTree.setSelection(new StructuredSelection(child)); |
| } else { |
| fExtensionTree.update(changeObject, null); |
| } |
| } |
| } |
| } |
| |
| private Image resolveObjectImage(Object obj) { |
| if (obj instanceof IPluginExtension) { |
| return fExtensionImage; |
| } |
| Image elementImage = fGenericElementImage; |
| if (obj instanceof IPluginElement) { |
| IPluginElement element = (IPluginElement) obj; |
| Image customImage = getCustomImage(element); |
| if (customImage != null) |
| elementImage = customImage; |
| String bodyText = element.getText(); |
| boolean hasBodyText = bodyText!=null&&bodyText.length()>0; |
| if (hasBodyText) { |
| elementImage = PDEPlugin.getDefault().getLabelProvider().get( |
| elementImage, SharedLabelProvider.F_EDIT); |
| } |
| } |
| return elementImage; |
| } |
| |
| private static boolean isStorageModel(IPluginObject object) { |
| IPluginModelBase modelBase = object.getPluginModel(); |
| return modelBase.getInstallLocation()==null; |
| } |
| |
| static Image getCustomImage(IPluginElement element) { |
| if (isStorageModel(element))return null; |
| ISchemaElement elementInfo = getSchemaElement(element); |
| if (elementInfo != null && elementInfo.getIconProperty() != null) { |
| String iconProperty = elementInfo.getIconProperty(); |
| IPluginAttribute att = element.getAttribute(iconProperty); |
| String iconPath = null; |
| if (att != null && att.getValue() != null) { |
| iconPath = att.getValue(); |
| } |
| if (iconPath != null) { |
| //OK, we have an icon path relative to the plug-in |
| return getImageFromPlugin(element, iconPath); |
| } |
| } |
| return null; |
| } |
| |
| private static Image getImageFromPlugin(IPluginElement element, |
| String iconPathName) { |
| // 39283 - ignore icon paths that |
| // point at plugin.properties |
| if (iconPathName.startsWith("%")) //$NON-NLS-1$ |
| return null; |
| |
| IPluginModelBase model = element.getPluginModel(); |
| if (model == null) |
| return null; |
| |
| return PDEPlugin.getDefault().getLabelProvider().getImageFromPlugin(model, iconPathName); |
| } |
| private String resolveObjectName(Object obj) { |
| return resolveObjectName(getSchemaRegistry(), obj); |
| } |
| |
| private SchemaRegistry getSchemaRegistry() { |
| if (fSchemaRegistry == null) |
| fSchemaRegistry = PDECore.getDefault().getSchemaRegistry(); |
| return fSchemaRegistry; |
| } |
| |
| public static String resolveObjectName(SchemaRegistry schemaRegistry, Object obj) { |
| boolean fullNames = PDEPlugin.isFullNameModeEnabled(); |
| if (obj instanceof IPluginExtension) { |
| IPluginExtension extension = (IPluginExtension) obj; |
| if (!fullNames) { |
| return extension.getPoint(); |
| } |
| if (extension.getName() != null) |
| return extension.getTranslatedName(); |
| ISchema schema = schemaRegistry.getSchema(extension.getPoint()); |
| // try extension point schema definition |
| if (schema != null) { |
| // exists |
| return schema.getName(); |
| } |
| return extension.getPoint(); |
| } else if (obj instanceof IPluginElement) { |
| IPluginElement element = (IPluginElement) obj; |
| String baseName = element.getName(); |
| String fullName = null; |
| ISchemaElement elementInfo = getSchemaElement(element); |
| IPluginAttribute labelAtt = null; |
| if (elementInfo != null && elementInfo.getLabelProperty() != null) { |
| labelAtt = element.getAttribute(elementInfo.getLabelProperty()); |
| } |
| if (labelAtt == null) { |
| // try some hard-coded attributes that |
| // are used frequently |
| for (int i = 0; i < COMMON_LABEL_PROPERTIES.length; i++) { |
| labelAtt = element.getAttribute(COMMON_LABEL_PROPERTIES[i]); |
| if (labelAtt != null) |
| break; |
| } |
| if (labelAtt == null) { |
| // Last try - if there is only one attribute, |
| // use that |
| if (element.getAttributeCount() == 1) |
| labelAtt = element.getAttributes()[0]; |
| } |
| } |
| if (labelAtt != null && labelAtt.getValue() != null) |
| fullName = stripShortcuts(labelAtt.getValue()); |
| fullName = element.getResourceString(fullName); |
| if (fullNames) |
| return fullName != null ? fullName : baseName; |
| return fullName != null |
| ? (fullName + " (" + baseName + ")") //$NON-NLS-1$ //$NON-NLS-2$ |
| : baseName; |
| } |
| return obj.toString(); |
| } |
| public void setFocus() { |
| if (fExtensionTree != null) |
| fExtensionTree.getTree().setFocus(); |
| } |
| public static String stripShortcuts(String input) { |
| StringBuffer output = new StringBuffer(); |
| for (int i = 0; i < input.length(); i++) { |
| char c = input.charAt(i); |
| if (c == '&') |
| continue; |
| else if (c == '@') |
| break; |
| output.append(c); |
| } |
| return output.toString(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#canPaste(java.lang.Object, java.lang.Object[]) |
| */ |
| protected boolean canPaste(Object targetObject, Object[] sourceObjects) { |
| // Note: Multi-select in tree viewer is disabled; but, this function |
| // can support multiple source objects |
| // Rule: Element source objects are always pasted as children of the |
| // target object (if allowable) |
| // Rule: Extension source objects are always pasted and are independent |
| // of the target object |
| // Ensure all the sourceObjects are either extensions or elements |
| boolean allExtensions = true; |
| boolean allElements = true; |
| for (int i = 0; i < sourceObjects.length; i++) { |
| if (sourceObjects[i] instanceof IPluginExtension) { |
| allElements = false; |
| } else if (sourceObjects[i] instanceof IPluginElement) { |
| allExtensions = false; |
| } else { |
| return false; |
| } |
| } |
| // Because of the extension rule, we can paste all extension source |
| // objects |
| if (allExtensions) { |
| return true; |
| } |
| // Pasting a mixture of elements and extensions is not supported |
| // (or wise from the users perspective) |
| if (allElements == false) { |
| return false; |
| } |
| // Ensure the target object can have children |
| if ((targetObject instanceof IPluginParent) == false) { |
| return false; |
| } else if ((targetObject instanceof IDocumentNode) == false) { |
| return false; |
| } |
| // Retrieve the schema corresponding to the target object |
| IPluginParent targetParent = (IPluginParent)targetObject; |
| ISchema schema = getSchema(targetParent); |
| // If there is no schema, then a source object can be pasted as a |
| // child of any target object |
| if (schema == null) { |
| return true; |
| } |
| // Determine the element name of the target object |
| // getName() does not work for extensions for some reason |
| String tagName = null; |
| if (targetParent instanceof IPluginExtension) { |
| tagName = "extension"; //$NON-NLS-1$ |
| } else { |
| tagName = targetParent.getName(); |
| } |
| // Retrieve the element schema for the target object |
| ISchemaElement schemaElement = schema.findElement(tagName); |
| // Ensure we found a schema element and it is a schema complex type |
| if (schemaElement == null) { |
| // Something is seriously wrong, we have a schema |
| return false; |
| } else if ((schemaElement.getType() instanceof ISchemaComplexType) == false) { |
| // Something is seriously wrong, we are a plugin parent |
| return false; |
| } |
| // We have a schema complex type. Either the target object has |
| // attributes or the element has children. |
| // Generate the list of element proposals |
| HashSet elementSet = |
| XMLElementProposalComputer.computeElementProposal( |
| schemaElement, (IDocumentNode)targetObject); |
| // Determine whether we can paste the source elements as children of |
| // the target object |
| if (sourceObjects.length > 1) { |
| return canPasteSourceElements((IPluginElement[])sourceObjects, elementSet); |
| } |
| return canPasteSourceElement((IPluginElement)sourceObjects[0], elementSet); |
| } |
| |
| /** |
| * @param sourceElements |
| * @param targetElementSet |
| * @return |
| */ |
| private boolean canPasteSourceElements(IPluginElement[] sourceElements, |
| HashSet targetElementSet) { |
| // Performance optimization |
| // HashSet of schema elements is not comparable for the source |
| // objects (schema elements are transient) |
| // Create a new HashSet with element names for comparison |
| HashSet targetElementNameSet = new HashSet(); |
| Iterator iterator = targetElementSet.iterator(); |
| while (iterator.hasNext()) { |
| targetElementNameSet.add(((ISchemaElement)iterator.next()).getName()); |
| } |
| // Paste will be enabled only if all source objects can be pasted |
| // as children into the target element |
| // Limitation: Multiplicity checks will be compromised because we |
| // are pasting multiple elements as a single transaction. The |
| // mulitplicity check is computed on the current static state of the |
| // target object with the assumption one new element will be added. |
| // Obviously, adding more than one element can invalidate the check |
| // due to choice, sequence multiplicity constraints. Even if source |
| // elements that are pasted violate multiplicity constraints the |
| // extensions builder will flag them with errors |
| for (int i = 0; i < sourceElements.length; i++) { |
| String sourceTagName = sourceElements[i].getName(); |
| if (targetElementNameSet.contains(sourceTagName) == false) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * @param sourceElement |
| * @param targetElementSet |
| * @return |
| */ |
| private boolean canPasteSourceElement(IPluginElement sourceElement, |
| HashSet targetElementSet) { |
| boolean canPaste = false; |
| // Get the source element tag name |
| String sourceTagName = sourceElement.getName(); |
| // Iterate over set of valid element proposals |
| Iterator iterator = targetElementSet.iterator(); |
| while (iterator.hasNext()) { |
| // Get the proposal element tag name |
| String targetTagName = ((ISchemaElement)iterator.next()).getName(); |
| // Only a source element that is found ithin the set of element |
| // proposals can be pasted |
| if (sourceTagName.equals(targetTagName)) { |
| canPaste = true; |
| break; |
| } |
| } |
| return canPaste; |
| } |
| |
| /** |
| * @return |
| */ |
| private IPluginModelBase getPluginModelBase() { |
| // Note: This method will work with fragments as long as a fragment.xml |
| // is defined first. Otherwise, paste will not work out of the box. |
| // Get the model |
| IPluginModelBase model = (IPluginModelBase) getPage().getModel(); |
| // Ensure the model is a bundle plugin model |
| if ((model instanceof IBundlePluginModelBase) == false) { |
| return null; |
| } |
| // Get the extension model |
| ISharedExtensionsModel extensionModel = |
| ((IBundlePluginModelBase)model).getExtensionsModel(); |
| // Ensure the extension model is defined |
| if ((extensionModel == null) || |
| ((extensionModel instanceof IPluginModelBase) == false)) { |
| return null; |
| } |
| return ((IPluginModelBase)extensionModel); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#doPaste(java.lang.Object, java.lang.Object[]) |
| */ |
| protected void doPaste(Object targetObject, Object[] sourceObjects) { |
| // By default, fragment.xml does not exist until the first extension |
| // or extension point is created. |
| // Ensure the file exists before pasting because the model will be |
| // null and the paste will fail if it does not exist |
| ((ManifestEditor)getPage().getEditor()).ensurePluginContextPresence(); |
| // Note: Multi-select in tree viewer is disabled; but, this function |
| // can support multiple source objects |
| // Get the model |
| IPluginModelBase model = getPluginModelBase(); |
| // Ensure the model is defined |
| if (model == null) { |
| return; |
| } |
| IPluginBase pluginBase = model.getPluginBase(); |
| try { |
| // Paste all source objects into the target object |
| for (int i = 0; i < sourceObjects.length; i++) { |
| Object sourceObject = sourceObjects[i]; |
| |
| if ((sourceObject instanceof IDocumentExtension) && |
| (sourceObject instanceof IPluginExtension) && |
| (pluginBase instanceof IDocumentNode)) { |
| // Extension object |
| IDocumentExtension extension = (IDocumentExtension)sourceObject; |
| // Retrieve the associated schema if there is one |
| ISchema schema = getSchema((IPluginExtension)extension); |
| // Adjust all the source object transient field values to |
| // acceptable values |
| extension.reconnect(model, schema, (IDocumentNode)pluginBase); |
| pluginBase.add((IPluginExtension)extension); |
| |
| } else if ((sourceObject instanceof IDocumentElement) && |
| (sourceObject instanceof IPluginElement) && |
| (targetObject instanceof IPluginParent) && |
| (targetObject instanceof IDocumentNode)) { |
| // Element object |
| IDocumentElement element = (IDocumentElement)sourceObject; |
| // Retrieve the associated schema if there is one |
| ISchema schema = getSchema((IPluginElement)element); |
| // Adjust all the source object transient field values to |
| // acceptable values |
| element.reconnect(model, schema, (IDocumentNode)targetObject); |
| // Add the element to the plugin parent (extension or |
| // element) |
| ((IPluginParent)targetObject).add((IPluginElement)element); |
| } |
| } |
| } catch (CoreException e) { |
| PDEPlugin.logException(e); |
| } |
| } |
| |
| private void handleMove(boolean up) { |
| IStructuredSelection sel = (IStructuredSelection) fExtensionTree |
| .getSelection(); |
| IPluginObject object = (IPluginObject) sel.getFirstElement(); |
| if (object instanceof IPluginElement) { |
| IPluginParent parent = (IPluginParent) object.getParent(); |
| IPluginObject[] children = parent.getChildren(); |
| int index = parent.getIndexOf(object); |
| int newIndex = up ? index - 1 : index + 1; |
| IPluginObject child2 = children[newIndex]; |
| try { |
| parent.swap(object, child2); |
| } catch (CoreException e) { |
| PDEPlugin.logException(e); |
| } |
| } else if (object instanceof IPluginExtension) { |
| IPluginExtension extension = (IPluginExtension) object; |
| IPluginBase plugin = extension.getPluginBase(); |
| IPluginExtension[] extensions = plugin.getExtensions(); |
| int index = plugin.getIndexOf(extension); |
| int newIndex = up ? index - 1 : index + 1; |
| IPluginExtension e2 = extensions[newIndex]; |
| try { |
| plugin.swap(extension, e2); |
| } catch (CoreException e) { |
| PDEPlugin.logException(e); |
| } |
| } |
| } |
| private void updateUpDownButtons(Object item) { |
| if (getPage().getModel().isEditable() == false) |
| return; |
| boolean sorted = fSortAction != null && fSortAction.isChecked(); |
| if (sorted) { |
| getTreePart().setButtonEnabled(3, false); |
| getTreePart().setButtonEnabled(4, false); |
| return; |
| } |
| |
| boolean upEnabled = false; |
| boolean downEnabled = false; |
| if (item instanceof IPluginElement) { |
| IPluginElement element = (IPluginElement) item; |
| IPluginParent parent = (IPluginParent) element.getParent(); |
| // check up |
| int index = parent.getIndexOf(element); |
| if (index > 0) |
| upEnabled = true; |
| if (index < parent.getChildCount() - 1) |
| downEnabled = true; |
| } else if (item instanceof IPluginExtension) { |
| IPluginExtension extension = (IPluginExtension) item; |
| IExtensions extensions = (IExtensions) extension.getParent(); |
| int index = extensions.getIndexOf(extension); |
| int size = extensions.getExtensions().length; |
| if (index > 0) |
| upEnabled = true; |
| if (index < size - 1) |
| downEnabled = true; |
| } |
| |
| getTreePart().setButtonEnabled(3, upEnabled); |
| getTreePart().setButtonEnabled(4, downEnabled); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.pde.internal.ui.editor.TreeSection#createTreeViewer(org.eclipse.swt.widgets.Composite, int) |
| */ |
| protected TreeViewer createTreeViewer(Composite parent, int style) { |
| fFilteredTree = new FormFilteredTree(parent, style, new PatternFilter()); |
| parent.setData("filtered", Boolean.TRUE); //$NON-NLS-1$ |
| return fFilteredTree.getViewer(); |
| } |
| |
| public void propertyChange(PropertyChangeEvent event) { |
| if (fSortAction.equals(event.getSource()) && IAction.RESULT.equals(event.getProperty())) { |
| StructuredViewer viewer = getStructuredViewerPart().getViewer(); |
| IStructuredSelection ssel = (IStructuredSelection)viewer.getSelection(); |
| updateUpDownButtons(ssel.size() != 1 ? null : ssel.getFirstElement()); |
| } |
| } |
| |
| protected void selectExtensionElement(ISelection selection) { |
| fExtensionTree.setSelection(selection, true); |
| } |
| } |