blob: 5eef5b52af7a203a354381d1741b3d31e86337ed [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 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
* Lars Vogel <Lars.Vogel@vogella.com> - Bug 487943
* Martin Karpisek <martin.karpisek@gmail.com> - Bug 351356
*******************************************************************************/
package org.eclipse.pde.internal.ui.editor.plugin;
import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter;
import java.util.ArrayList;
import java.util.HashSet;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jface.action.*;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.window.Window;
import org.eclipse.pde.core.*;
import org.eclipse.pde.core.build.*;
import org.eclipse.pde.core.plugin.*;
import org.eclipse.pde.internal.build.IBuildPropertiesConstants;
import org.eclipse.pde.internal.core.ClasspathUtilCore;
import org.eclipse.pde.internal.core.bundle.BundlePluginBase;
import org.eclipse.pde.internal.core.plugin.PluginLibrary;
import org.eclipse.pde.internal.core.project.PDEProject;
import org.eclipse.pde.internal.ui.*;
import org.eclipse.pde.internal.ui.editor.*;
import org.eclipse.pde.internal.ui.editor.build.*;
import org.eclipse.pde.internal.ui.editor.context.InputContextManager;
import org.eclipse.pde.internal.ui.parts.EditableTablePart;
import org.eclipse.pde.internal.ui.parts.TablePart;
import org.eclipse.pde.internal.ui.util.SWTUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.forms.editor.IFormPage;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.views.navigator.ResourceComparator;
public class LibrarySection extends TableSection implements IBuildPropertiesConstants {
private static final int NEW_INDEX = 0;
private static final int ADD_INDEX = 1;
private static final int REMOVE_INDEX = 2;
private static final int UP_INDEX = 3;
private static final int DOWN_INDEX = 4;
private Action fRenameAction;
private Action fRemoveAction;
private Action fNewAction;
private TableViewer fLibraryTable;
class LibraryFilter extends JARFileFilter {
public LibraryFilter(HashSet<IPath> set) {
super(set);
}
@Override
public boolean select(Viewer viewer, Object parent, Object element) {
if (element instanceof IFolder)
return isPathValid(((IFolder) element).getProjectRelativePath());
if (element instanceof IFile)
return isFileValid(((IFile) element).getProjectRelativePath());
return false;
}
}
class LibrarySelectionValidator extends JarSelectionValidator {
public LibrarySelectionValidator(Class<?>[] acceptedTypes, boolean allowMultipleSelection) {
super(acceptedTypes, allowMultipleSelection);
}
@Override
public boolean isValid(Object element) {
return (element instanceof IFolder) ? true : super.isValid(element);
}
}
class TableContentProvider implements IStructuredContentProvider {
@Override
public Object[] getElements(Object parent) {
return getModel().getPluginBase().getLibraries();
}
}
public LibrarySection(PDEFormPage page, Composite parent) {
super(page, parent, Section.DESCRIPTION, new String[] {PDEUIMessages.NewManifestEditor_LibrarySection_new, PDEUIMessages.NewManifestEditor_LibrarySection_add, PDEUIMessages.NewManifestEditor_LibrarySection_remove, PDEUIMessages.ManifestEditor_LibrarySection_up, PDEUIMessages.ManifestEditor_LibrarySection_down});
}
private String getSectionDescription() {
IPluginModelBase model = getModel();
if (isBundle()) {
return (model.isFragmentModel()) ? PDEUIMessages.ClasspathSection_fragment : PDEUIMessages.ClasspathSection_plugin;
}
return (model.isFragmentModel()) ? PDEUIMessages.ManifestEditor_LibrarySection_fdesc : PDEUIMessages.ManifestEditor_LibrarySection_desc;
}
protected boolean isBundle() {
return getBundleContext() != null;
}
private BundleInputContext getBundleContext() {
InputContextManager manager = getPage().getPDEEditor().getContextManager();
return (BundleInputContext) manager.findContext(BundleInputContext.CONTEXT_ID);
}
@Override
public void createClient(Section section, FormToolkit toolkit) {
section.setText(PDEUIMessages.ManifestEditor_LibrarySection_title);
section.setDescription(getSectionDescription());
Composite container = createClientContainer(section, 2, toolkit);
EditableTablePart tablePart = getTablePart();
tablePart.setEditable(isEditable());
createViewerPartControl(container, SWT.MULTI, 2, toolkit);
fLibraryTable = tablePart.getTableViewer();
fLibraryTable.setContentProvider(new TableContentProvider());
fLibraryTable.setLabelProvider(PDEPlugin.getDefault().getLabelProvider());
toolkit.paintBordersFor(container);
makeActions();
updateButtons();
section.setLayout(FormLayoutFactory.createClearGridLayout(false, 1));
section.setLayoutData(new GridData(GridData.FILL_BOTH));
section.setClient(container);
IPluginModelBase model = getModel();
fLibraryTable.setInput(model.getPluginBase());
model.addModelChangedListener(this);
}
private void updateButtons() {
Table table = fLibraryTable.getTable();
boolean hasSelection = table.getSelection().length > 0;
boolean singleSelection = table.getSelection().length == 1;
int count = table.getItemCount();
int index = table.getSelectionIndex();
boolean canMoveUp = singleSelection && index > 0;
boolean canMoveDown = singleSelection && index < count - 1;
TablePart tablePart = getTablePart();
tablePart.setButtonEnabled(ADD_INDEX, isEditable());
tablePart.setButtonEnabled(NEW_INDEX, isEditable());
tablePart.setButtonEnabled(REMOVE_INDEX, isEditable() && hasSelection);
tablePart.setButtonEnabled(UP_INDEX, isEditable() && canMoveUp);
tablePart.setButtonEnabled(DOWN_INDEX, isEditable() && canMoveDown);
}
private void makeActions() {
fNewAction = new Action(PDEUIMessages.ManifestEditor_LibrarySection_newLibrary) {
@Override
public void run() {
handleNew();
}
};
fNewAction.setEnabled(isEditable());
fRenameAction = new Action(PDEUIMessages.EditableTablePart_renameAction) {
@Override
public void run() {
getRenameAction().run();
}
};
fRenameAction.setEnabled(isEditable());
fRemoveAction = new Action(PDEUIMessages.NewManifestEditor_LibrarySection_remove) {
@Override
public void run() {
handleRemove();
}
};
fRemoveAction.setEnabled(isEditable());
}
@Override
protected void selectionChanged(IStructuredSelection selection) {
getPage().getPDEEditor().setSelection(selection);
if (getPage().getModel().isEditable())
updateButtons();
}
@Override
protected void buttonSelected(int index) {
switch (index) {
case NEW_INDEX :
handleNew();
break;
case ADD_INDEX :
handleAdd();
break;
case REMOVE_INDEX :
handleRemove();
break;
case UP_INDEX :
handleUp();
break;
case DOWN_INDEX :
handleDown();
break;
}
}
@Override
public void dispose() {
IPluginModelBase model = getModel();
if (model != null)
model.removeModelChangedListener(this);
super.dispose();
}
@Override
public boolean doGlobalAction(String actionId) {
if (!isEditable()) {
return false;
}
if (actionId.equals(ActionFactory.DELETE.getId())) {
handleRemove();
return true;
}
if (actionId.equals(ActionFactory.CUT.getId())) {
// delete here and let the editor transfer
// the selection to the clipboard
handleRemove();
return false;
}
if (actionId.equals(ActionFactory.PASTE.getId())) {
doPaste();
return true;
}
return super.doGlobalAction(actionId);
}
@Override
public boolean setFormInput(Object object) {
if (object instanceof IPluginLibrary) {
fLibraryTable.setSelection(new StructuredSelection(object), true);
return true;
}
return false;
}
@Override
protected void fillContextMenu(IMenuManager manager) {
manager.add(fNewAction);
if (!fLibraryTable.getStructuredSelection().isEmpty()) {
manager.add(new Separator());
manager.add(fRenameAction);
manager.add(fRemoveAction);
}
// Copy, cut, and paste operations not supported for plug-ins that do
// not have a MANIFEST.MF (not a Bundle)
getPage().getPDEEditor().getContributor().contextMenuAboutToShow(manager, isBundle());
}
private void handleRemove() {
Object[] selection = fLibraryTable.getStructuredSelection().toArray();
int index = fLibraryTable.getTable().getSelectionIndex();
int[] indices = fLibraryTable.getTable().getSelectionIndices();
for (int indice : indices)
if (indice < index)
index = indice;
String[] remove = new String[selection.length];
for (int i = 0; i < selection.length; i++) {
if (selection[i] != null && selection[i] instanceof IPluginLibrary) {
IPluginLibrary ep = (IPluginLibrary) selection[i];
IPluginBase plugin = ep.getPluginBase();
try {
plugin.remove(ep);
} catch (CoreException e) {
PDEPlugin.logException(e);
}
remove[i] = ep.getName();
}
}
updateBuildProperties(remove, new String[remove.length], true);
updateJavaClasspathLibs(remove, new String[remove.length]);
int itemCount = fLibraryTable.getTable().getItemCount();
if (itemCount > 0) {
if (index >= itemCount)
index = itemCount - 1;
fLibraryTable.getTable().setSelection(index);
fLibraryTable.getTable().setFocus();
}
updateButtons();
}
private void handleDown() {
Table table = getTablePart().getTableViewer().getTable();
int index = table.getSelectionIndex();
if (index != table.getItemCount() - 1)
swap(index, index + 1);
}
private void handleUp() {
int index = getTablePart().getTableViewer().getTable().getSelectionIndex();
if (index >= 1)
swap(index, index - 1);
}
public void swap(int index1, int index2) {
Table table = getTablePart().getTableViewer().getTable();
IPluginLibrary l1 = (IPluginLibrary) table.getItem(index1).getData();
IPluginLibrary l2 = (IPluginLibrary) table.getItem(index2).getData();
try {
IPluginModelBase model = getModel();
IPluginBase pluginBase = model.getPluginBase();
pluginBase.swap(l1, l2);
refresh();
table.setSelection(index2);
table.setFocus();
updateButtons();
} catch (CoreException e) {
PDEPlugin.logException(e);
}
}
private void handleNew() {
IPluginModelBase model = getModel();
NewRuntimeLibraryDialog dialog = new NewRuntimeLibraryDialog(getPage().getSite().getShell(), model.getPluginBase().getLibraries());
dialog.create();
dialog.getShell().setText(PDEUIMessages.ManifestEditor_LibrarySection_newLibraryEntry);
SWTUtil.setDialogSize(dialog, 250, 175);
if (dialog.open() == Window.OK) {
String libName = dialog.getLibraryName();
if (libName == null || libName.length() == 0)
return;
try {
IPluginLibrary library = model.getPluginFactory().createLibrary();
library.setName(libName);
library.setExported(true);
model.getPluginBase().add(library);
checkSourceRootEntry();
updateBuildProperties(new String[] {null}, new String[] {library.getName()}, true);
fLibraryTable.setSelection(new StructuredSelection(library));
fLibraryTable.getTable().setFocus();
} catch (CoreException e) {
PDEPlugin.logException(e);
}
}
}
private void checkSourceRootEntry() {
IPluginModelBase pluginModel = getModel();
IPluginLibrary[] libraries = pluginModel.getPluginBase().getLibraries();
for (IPluginLibrary library : libraries)
if (library.getName().equals(".")) //$NON-NLS-1$
return;
IBuildModel model = getBuildModel();
if (model == null)
return;
IBuildEntry[] entires = model.getBuild().getBuildEntries();
for (IBuildEntry entry : entires) {
if (entry.getName().equals(PROPERTY_SOURCE_PREFIX + '.')) {
IPluginLibrary library = pluginModel.getPluginFactory().createLibrary();
try {
library.setName("."); //$NON-NLS-1$
pluginModel.getPluginBase().add(library);
} catch (CoreException e) {
}
}
}
}
private IBuildModel getBuildModel() {
IFormPage page = getPage().getEditor().findPage(BuildInputContext.CONTEXT_ID);
IBaseModel model = null;
if (page instanceof BuildSourcePage)
model = ((BuildSourcePage) page).getInputContext().getModel();
if (model != null && model instanceof IBuildModel)
return (IBuildModel) model;
return null;
}
private void configureSourceBuildEntry(IBuildModel bmodel, String oldPath, String newPath) throws CoreException {
IBuild build = bmodel.getBuild();
IBuildEntry entry = build.getEntry(PROPERTY_SOURCE_PREFIX + (oldPath != null ? oldPath : newPath));
try {
if (newPath != null) {
if (entry == null) {
IProject project = ((IModel) getPage().getModel()).getUnderlyingResource().getProject();
IJavaProject jproject = JavaCore.create(project);
ArrayList<String> tokens = new ArrayList<>();
IClasspathEntry[] entries = jproject.getRawClasspath();
for (IClasspathEntry cpe : entries)
if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE)
tokens.add(cpe.getPath().removeFirstSegments(1).addTrailingSeparator().toString());
if (tokens.size() == 0)
return;
entry = bmodel.getFactory().createEntry(PROPERTY_SOURCE_PREFIX + newPath);
for (int i = 0; i < tokens.size(); i++)
entry.addToken(tokens.get(i));
build.add(entry);
} else
entry.setName(PROPERTY_SOURCE_PREFIX + newPath);
} else if (entry != null)
build.remove(entry);
} catch (JavaModelException e) {
}
}
private void handleAdd() {
final boolean[] updateClasspath = new boolean[] {true};
ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getPage().getSite().getShell(), new WorkbenchLabelProvider(), new WorkbenchContentProvider()) {
@Override
protected Control createDialogArea(Composite parent) {
Composite comp = (Composite) super.createDialogArea(parent);
final Button button = new Button(comp, SWT.CHECK);
button.setText(PDEUIMessages.LibrarySection_addDialogButton);
button.setSelection(updateClasspath[0]);
button.addSelectionListener(widgetSelectedAdapter(e -> updateClasspath[0] = button.getSelection()));
applyDialogFont(button);
return comp;
}
};
Class<?>[] acceptedClasses = new Class[] {IFile.class};
dialog.setValidator(new LibrarySelectionValidator(acceptedClasses, true));
dialog.setTitle(PDEUIMessages.BuildEditor_ClasspathSection_jarsTitle);
dialog.setMessage(PDEUIMessages.ClasspathSection_jarsMessage);
IPluginLibrary[] libraries = getModel().getPluginBase().getLibraries();
IProject project = ((IModel) getPage().getModel()).getUnderlyingResource().getProject();
HashSet<IPath> set = new HashSet<>();
for (IPluginLibrary library : libraries) {
IPath bundlePath = new Path(ClasspathUtilCore.expandLibraryName(library.getName()));
IPath buildPath = PDEProject.getBundleRoot(project).getProjectRelativePath().append(bundlePath);
set.add(buildPath);
}
dialog.addFilter(new LibraryFilter(set));
dialog.setInput(project);
dialog.setComparator(new ResourceComparator(ResourceComparator.NAME));
dialog.create();
PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IHelpContextIds.ADD_LIBRARY);
if (dialog.open() == Window.OK) {
Object[] elements = dialog.getResult();
String[] bundlePaths = new String[elements.length];
String[] buildPaths = new String[elements.length];
IPluginModelBase model = getModel();
ArrayList<IPluginLibrary> list = new ArrayList<>();
for (int i = 0; i < elements.length; i++) {
IResource elem = (IResource) elements[i];
IContainer bundleRoot = PDEProject.getBundleRoot(project);
IPath rootPath = bundleRoot.getFullPath();
// make path relative to bundle root
IPath bundlePath = elem.getFullPath().makeRelativeTo(rootPath);
IPath buildPath = elem.getProjectRelativePath();
if (elem instanceof IFolder) {
bundlePath = bundlePath.addTrailingSeparator();
buildPath = buildPath.addTrailingSeparator();
}
bundlePaths[i] = bundlePath.toString();
buildPaths[i] = buildPath.toString();
IPluginLibrary library = model.getPluginFactory().createLibrary();
try {
library.setName(bundlePaths[i]);
library.setExported(true);
model.getPluginBase().add(library);
list.add(library);
} catch (CoreException e) {
PDEPlugin.logException(e);
}
}
checkSourceRootEntry();
updateBuildProperties(new String[bundlePaths.length], bundlePaths, false);
if (updateClasspath[0])
updateJavaClasspathLibs(new String[buildPaths.length], buildPaths);
fLibraryTable.setSelection(new StructuredSelection(list.toArray()));
fLibraryTable.getTable().setFocus();
}
}
private void updateBuildProperties(final String[] oldPaths, final String[] newPaths, boolean modifySourceEntry) {
IBuildModel bmodel = getBuildModel();
if (bmodel == null)
return;
IBuild build = bmodel.getBuild();
IBuildEntry entry = build.getEntry(PROPERTY_BIN_INCLUDES);
if (entry == null)
entry = bmodel.getFactory().createEntry(PROPERTY_BIN_INCLUDES);
try {
// adding new entries
if (oldPaths[0] == null) {
for (String newPath : newPaths)
if (newPath != null) {
entry.addToken(newPath);
if (modifySourceEntry)
configureSourceBuildEntry(bmodel, null, newPath);
}
// removing entries
} else if (newPaths[0] == null) {
for (String oldPath : oldPaths)
if (oldPath != null) {
entry.removeToken(oldPath);
if (modifySourceEntry)
configureSourceBuildEntry(bmodel, oldPath, null);
}
if (entry.getTokens().length == 0)
build.remove(entry);
// rename entries
} else {
for (int i = 0; i < oldPaths.length; i++)
if (newPaths[i] != null && oldPaths[i] != null) {
entry.renameToken(oldPaths[i], newPaths[i]);
if (modifySourceEntry)
configureSourceBuildEntry(bmodel, oldPaths[i], newPaths[i]);
}
}
} catch (CoreException e) {
}
}
private void updateJavaClasspathLibs(String[] oldPaths, String[] newPaths) {
IProject project = ((IModel) getPage().getModel()).getUnderlyingResource().getProject();
IJavaProject jproject = JavaCore.create(project);
try {
IClasspathEntry[] entries = jproject.getRawClasspath();
ArrayList<IClasspathEntry> toBeAdded = new ArrayList<>();
int index = -1;
entryLoop: for (int i = 0; i < entries.length; i++) {
if (entries[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
if (index == -1)
index = i;
// do not add the old paths (handling deletion/renaming)
IPath path = entries[i].getPath().removeFirstSegments(1).removeTrailingSeparator();
for (int j = 0; j < oldPaths.length; j++)
if (oldPaths[j] != null && path.equals(new Path(oldPaths[j]).removeTrailingSeparator()))
continue entryLoop;
} else if (entries[i].getEntryKind() == IClasspathEntry.CPE_CONTAINER)
if (index == -1)
index = i;
toBeAdded.add(entries[i]);
}
if (index == -1)
index = entries.length;
// add paths
for (String newPath : newPaths) {
if (newPath == null)
continue;
IClasspathEntry entry = JavaCore.newLibraryEntry(project.getFullPath().append(newPath), null, null, true);
if (!toBeAdded.contains(entry))
toBeAdded.add(index++, entry);
}
if (toBeAdded.size() == entries.length)
return;
IClasspathEntry[] updated = toBeAdded.toArray(new IClasspathEntry[toBeAdded.size()]);
jproject.setRawClasspath(updated, null);
} catch (JavaModelException e) {
}
}
@Override
public void refresh() {
if (fLibraryTable.getControl().isDisposed())
return;
fLibraryTable.setSelection(null);
fLibraryTable.refresh();
super.refresh();
}
@Override
public void modelChanged(IModelChangedEvent event) {
if (event.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
markStale();
return;
}
Object changeObject = event.getChangedObjects()[0];
if (changeObject instanceof IPluginLibrary) {
if (event.getChangeType() == IModelChangedEvent.INSERT) {
fLibraryTable.refresh();
} else if (event.getChangeType() == IModelChangedEvent.REMOVE) {
fLibraryTable.remove(changeObject);
} else {
fLibraryTable.update(changeObject, null);
}
} else if (changeObject.equals(fLibraryTable.getInput())) {
markStale();
} else if (changeObject instanceof IPluginElement && ((IPluginElement) changeObject).getParent() instanceof IPluginLibrary) {
fLibraryTable.update(((IPluginElement) changeObject).getParent(), null);
}
}
@Override
public void setFocus() {
fLibraryTable.getTable().setFocus();
}
@Override
protected void doPaste(Object targetObject, Object[] sourceObjects) {
// Get the model
IPluginModelBase model = getModel();
IPluginBase plugin = model.getPluginBase();
try {
// Paste all source objects
for (Object sourceObject : sourceObjects) {
if (sourceObject instanceof PluginLibrary) {
// Plugin library object
PluginLibrary library = (PluginLibrary) sourceObject;
// Adjust all the source object transient field values to
// acceptable values
library.reconnect(model, plugin);
// Add the library to the plug-in
plugin.add(library);
}
}
} catch (CoreException e) {
PDEPlugin.logException(e);
}
}
@Override
protected boolean canPaste(Object targetObject, Object[] sourceObjects) {
HashSet<Path> librarySet = null;
// Only source objects that are plugin libraries that have not already
// been specified can be pasted
for (Object sourceObject : sourceObjects) {
// Only plugin libraries are allowed
if ((sourceObject instanceof IPluginLibrary) == false) {
return false;
}
// We have a plugin library
// Get the current libraries already specified and store them in
// a set to assist with searching
if (librarySet == null) {
librarySet = createPluginLibrarySet();
}
// No duplicate libraries are allowed
IPluginLibrary library = (IPluginLibrary) sourceObject;
if (librarySet.contains(new Path(ClasspathUtilCore.expandLibraryName(library.getName())))) {
return false;
}
}
return true;
}
private HashSet<Path> createPluginLibrarySet() {
// Get the current libraries and add them to a set for easy searching
IPluginLibrary[] libraries = getModel().getPluginBase().getLibraries();
HashSet<Path> librarySet = new HashSet<>();
for (IPluginLibrary library : libraries) {
librarySet.add(new Path(ClasspathUtilCore.expandLibraryName(library.getName())));
}
return librarySet;
}
@Override
protected void entryModified(Object entry, String value) {
try {
IPluginModelBase model = getModel();
IProject project = model.getUnderlyingResource().getProject();
IPluginLibrary library = (IPluginLibrary) entry;
model.getPluginBase().remove(library);
String[] oldValue = {library.getName()};
String[] newValue = {value};
library.setName(value);
boolean memberExists = project.findMember(value) != null;
updateBuildProperties(oldValue, newValue, !memberExists);
updateJavaClasspathLibs(oldValue, memberExists ? newValue : new String[] {null});
model.getPluginBase().add(library);
} catch (CoreException e) {
PDEPlugin.logException(e);
}
}
private IPluginModelBase getModel() {
return (IPluginModelBase) getPage().getModel();
}
@Override
protected boolean isDragAndDropEnabled() {
return true;
}
@Override
public boolean canDragMove(Object[] sourceObjects) {
if (validateDragMoveSanity(sourceObjects) == false) {
return false;
}
return true;
}
/**
* @param sourceObjects
*/
private boolean validateDragMoveSanity(Object[] sourceObjects) {
// Validate source
if (sourceObjects == null) {
// No objects
return false;
} else if (sourceObjects.length != 1) {
// Multiple selection not supported
return false;
} else if ((sourceObjects[0] instanceof IPluginLibrary) == false) {
// Must be the right type
return false;
}
return true;
}
@Override
public boolean canDropMove(Object targetObject, Object[] sourceObjects, int targetLocation) {
// Sanity check
if (validateDropMoveSanity(targetObject, sourceObjects) == false) {
return false;
}
// Multiple selection not supported
IPluginLibrary sourcePluginLibrary = (IPluginLibrary) sourceObjects[0];
IPluginLibrary targetPluginLibrary = (IPluginLibrary) targetObject;
// Validate model
if (validateDropMoveModel(sourcePluginLibrary, targetPluginLibrary) == false) {
return false;
}
// Get the bundle plug-in base
BundlePluginBase bundlePluginBase = (BundlePluginBase) getModel().getPluginBase();
// Validate move
if (targetLocation == ViewerDropAdapter.LOCATION_BEFORE) {
// Get the previous element of the target
IPluginLibrary previousLibrary = bundlePluginBase.getPreviousLibrary(targetPluginLibrary);
// Ensure the previous element is not the source
if (sourcePluginLibrary.equals(previousLibrary)) {
return false;
}
return true;
} else if (targetLocation == ViewerDropAdapter.LOCATION_AFTER) {
// Get the next element of the target
IPluginLibrary nextLibrary = bundlePluginBase.getNextLibrary(targetPluginLibrary);
// Ensure the next element is not the source
if (sourcePluginLibrary.equals(nextLibrary)) {
return false;
}
return true;
} else if (targetLocation == ViewerDropAdapter.LOCATION_ON) {
// Not supported
return false;
}
return false;
}
/**
* @param targetObject
* @param sourceObjects
*/
private boolean validateDropMoveSanity(Object targetObject, Object[] sourceObjects) {
// Validate target object
if ((targetObject instanceof IPluginLibrary) == false) {
return false;
}
// Validate source objects
if (validateDragMoveSanity(sourceObjects) == false) {
return false;
}
return true;
}
/**
* @param sourcePluginLibrary
* @param targetPluginLibrary
*/
private boolean validateDropMoveModel(IPluginLibrary sourcePluginLibrary, IPluginLibrary targetPluginLibrary) {
// Objects have to be from the same model
ISharedPluginModel sourceModel = sourcePluginLibrary.getModel();
ISharedPluginModel targetModel = targetPluginLibrary.getModel();
if (sourceModel.equals(targetModel) == false) {
return false;
} else if ((getModel().getPluginBase() instanceof BundlePluginBase) == false) {
return false;
}
return true;
}
@Override
public void doDropMove(Object targetObject, Object[] sourceObjects, int targetLocation) {
// Sanity check
if (validateDropMoveSanity(targetObject, sourceObjects) == false) {
Display.getDefault().beep();
return;
}
// Multiple selection not supported
IPluginLibrary sourcePluginLibrary = (IPluginLibrary) sourceObjects[0];
IPluginLibrary targetPluginLibrary = (IPluginLibrary) targetObject;
// Validate move
if ((targetLocation == ViewerDropAdapter.LOCATION_BEFORE) || (targetLocation == ViewerDropAdapter.LOCATION_AFTER)) {
// Do move
doDropMove(sourcePluginLibrary, targetPluginLibrary, targetLocation);
} else if (targetLocation == ViewerDropAdapter.LOCATION_ON) {
// Not supported
}
}
/**
* @param sourcePluginLibrary
* @param targetPluginLibrary
* @param targetLocation
*/
private void doDropMove(IPluginLibrary sourcePluginLibrary, IPluginLibrary targetPluginLibrary, int targetLocation) {
// Remove the original source object
// Normally we remove the original source object after inserting the
// serialized source object; however, the libraries are removed via ID
// and having both objects with the same ID co-existing will confound
// the remove operation
doDragRemove();
// Get the bundle plug-in base
IPluginModelBase model = getModel();
BundlePluginBase bundlePluginBase = (BundlePluginBase) model.getPluginBase();
// Get the index of the target
int index = bundlePluginBase.getIndexOf(targetPluginLibrary);
// Ensure the target index was found
if (index == -1) {
return;
}
// Determine the location index
int targetIndex = index;
if (targetLocation == ViewerDropAdapter.LOCATION_AFTER) {
targetIndex++;
}
// Ensure the plugin library is concrete
if ((sourcePluginLibrary instanceof PluginLibrary) == false) {
return;
}
// Adjust all the source object transient field values to
// acceptable values
((PluginLibrary) sourcePluginLibrary).reconnect(model, bundlePluginBase);
// Add source as sibling of target
try {
bundlePluginBase.add(sourcePluginLibrary, targetIndex);
} catch (CoreException e) {
// CoreException only if model is not editable, which should never be the case
}
}
/**
*
*/
private void doDragRemove() {
// Get the bundle plug-in base
BundlePluginBase bundlePluginBase = (BundlePluginBase) getModel().getPluginBase();
// Retrieve the original non-serialized source objects dragged initially
Object[] sourceObjects = getDragSourceObjects();
// Validate source objects
if (validateDragMoveSanity(sourceObjects) == false) {
return;
}
// Remove the library
IPluginLibrary sourcePluginLibrary = (IPluginLibrary) sourceObjects[0];
try {
bundlePluginBase.remove(sourcePluginLibrary);
} catch (CoreException e) {
PDEPlugin.logException(e);
}
}
}