blob: 74048b530db97ea5caa21408e60705115ac5630c [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 487988
* Martin Karpisek <martin.karpisek@gmail.com> - Bug 351356
*******************************************************************************/
package org.eclipse.pde.internal.ui.editor.plugin;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jface.action.*;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.window.Window;
import org.eclipse.pde.core.IModelChangedEvent;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.core.plugin.PluginRegistry;
import org.eclipse.pde.internal.core.ClasspathComputer;
import org.eclipse.pde.internal.core.ibundle.*;
import org.eclipse.pde.internal.core.text.bundle.*;
import org.eclipse.pde.internal.ui.*;
import org.eclipse.pde.internal.ui.editor.*;
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.swt.SWT;
import org.eclipse.swt.graphics.Image;
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.ElementListSelectionDialog;
import org.eclipse.ui.forms.IFormColors;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.events.IHyperlinkListener;
import org.eclipse.ui.forms.widgets.*;
import org.osgi.framework.Constants;
public class ExecutionEnvironmentSection extends TableSection {
private TableViewer fEETable;
private Action fRemoveAction;
private Action fAddAction;
class EELabelProvider extends LabelProvider {
private Image fImage;
public EELabelProvider() {
fImage = PDEPluginImages.DESC_JAVA_LIB_OBJ.createImage();
}
@Override
public Image getImage(Object element) {
return fImage;
}
@Override
public String getText(Object element) {
if (element instanceof IExecutionEnvironment)
return ((IExecutionEnvironment) element).getId();
return super.getText(element);
}
@Override
public void dispose() {
if (fImage != null)
fImage.dispose();
super.dispose();
}
}
class ContentProvider implements IStructuredContentProvider {
@Override
public Object[] getElements(Object inputElement) {
if (inputElement instanceof IBundleModel) {
IBundleModel model = (IBundleModel) inputElement;
IBundle bundle = model.getBundle();
IManifestHeader header = bundle.getManifestHeader(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
if (header instanceof RequiredExecutionEnvironmentHeader) {
return ((RequiredExecutionEnvironmentHeader) header).getEnvironments();
}
}
return new Object[0];
}
}
public ExecutionEnvironmentSection(PDEFormPage page, Composite parent) {
super(page, parent, Section.DESCRIPTION, new String[] {PDEUIMessages.RequiredExecutionEnvironmentSection_add, PDEUIMessages.RequiredExecutionEnvironmentSection_remove, PDEUIMessages.RequiredExecutionEnvironmentSection_up, PDEUIMessages.RequiredExecutionEnvironmentSection_down});
createClient(getSection(), page.getEditor().getToolkit());
}
@Override
protected void createClient(Section section, FormToolkit toolkit) {
section.setText(PDEUIMessages.RequiredExecutionEnvironmentSection_title);
if (isFragment())
section.setDescription(PDEUIMessages.RequiredExecutionEnvironmentSection_fragmentDesc);
else
section.setDescription(PDEUIMessages.RequiredExecutionEnvironmentSection_pluginDesc);
section.setLayout(FormLayoutFactory.createClearTableWrapLayout(false, 1));
TableWrapData data = new TableWrapData(TableWrapData.FILL_GRAB);
section.setLayoutData(data);
Composite container = createClientContainer(section, 2, toolkit);
EditableTablePart tablePart = getTablePart();
tablePart.setEditable(isEditable());
createViewerPartControl(container, SWT.FULL_SELECTION | SWT.MULTI, 2, toolkit);
fEETable = tablePart.getTableViewer();
fEETable.setContentProvider(new ContentProvider());
fEETable.setLabelProvider(PDEPlugin.getDefault().getLabelProvider());
Hyperlink link = toolkit.createHyperlink(container, PDEUIMessages.BuildExecutionEnvironmentSection_configure, SWT.NONE);
link.setForeground(toolkit.getColors().getColor(IFormColors.TITLE));
link.addHyperlinkListener(new IHyperlinkListener() {
@Override
public void linkEntered(HyperlinkEvent e) {
}
@Override
public void linkExited(HyperlinkEvent e) {
}
@Override
public void linkActivated(HyperlinkEvent e) {
SWTFactory.showPreferencePage(PDEPlugin.getActiveWorkbenchShell(), "org.eclipse.jdt.debug.ui.jreProfiles", null); //$NON-NLS-1$
}
});
GridData gd = new GridData();
gd.horizontalSpan = 2;
link.setLayoutData(gd);
final IProject project = getPage().getPDEEditor().getCommonProject();
try {
if (project != null && project.hasNature(JavaCore.NATURE_ID)) {
link = toolkit.createHyperlink(container, PDEUIMessages.ExecutionEnvironmentSection_updateClasspath, SWT.NONE);
link.setForeground(toolkit.getColors().getColor(IFormColors.TITLE));
link.addHyperlinkListener(new IHyperlinkListener() {
@Override
public void linkEntered(HyperlinkEvent e) {
}
@Override
public void linkExited(HyperlinkEvent e) {
}
@Override
public void linkActivated(HyperlinkEvent e) {
try {
getPage().getEditor().doSave(null);
IPluginModelBase model = PluginRegistry.findModel(project);
if (model != null) {
ClasspathComputer.setClasspath(project, model);
if (PDEPlugin.getWorkspace().isAutoBuilding()) {
doFullBuild(project);
}
}
} catch (CoreException e1) {
}
}
});
gd = new GridData();
gd.horizontalSpan = 2;
link.setLayoutData(gd);
}
} catch (CoreException e1) {
}
makeActions();
IBundleModel model = getBundleModel();
if (model != null) {
fEETable.setInput(model);
model.addModelChangedListener(this);
}
toolkit.paintBordersFor(container);
section.setClient(container);
}
@Override
public void dispose() {
IBundleModel model = getBundleModel();
if (model != null)
model.removeModelChangedListener(this);
}
@Override
public void refresh() {
fEETable.refresh();
updateButtons();
}
@Override
protected void buttonSelected(int index) {
switch (index) {
case 0 :
handleAdd();
break;
case 1 :
handleRemove();
break;
case 2 :
handleUp();
break;
case 3 :
handleDown();
break;
}
}
@Override
protected void fillContextMenu(IMenuManager manager) {
manager.add(fAddAction);
if (!fEETable.getStructuredSelection().isEmpty()) {
manager.add(new Separator());
manager.add(fRemoveAction);
}
getPage().getPDEEditor().getContributor().contextMenuAboutToShow(manager);
}
private void makeActions() {
fAddAction = new Action(PDEUIMessages.RequiredExecutionEnvironmentSection_add) {
@Override
public void run() {
handleAdd();
}
};
fAddAction.setEnabled(isEditable());
fRemoveAction = new Action(PDEUIMessages.NewManifestEditor_LibrarySection_remove) {
@Override
public void run() {
handleRemove();
}
};
fRemoveAction.setEnabled(isEditable());
}
private void updateButtons() {
Table table = fEETable.getTable();
int count = table.getItemCount();
boolean canMoveUp = count > 0 && table.getSelection().length == 1 && table.getSelectionIndex() > 0;
boolean canMoveDown = count > 0 && table.getSelection().length == 1 && table.getSelectionIndex() < count - 1;
TablePart tablePart = getTablePart();
tablePart.setButtonEnabled(0, isEditable());
tablePart.setButtonEnabled(1, isEditable() && table.getSelection().length > 0);
tablePart.setButtonEnabled(2, isEditable() && canMoveUp);
tablePart.setButtonEnabled(3, isEditable() && canMoveDown);
}
private void handleDown() {
int selection = fEETable.getTable().getSelectionIndex();
swap(selection, selection + 1);
}
private void handleUp() {
int selection = fEETable.getTable().getSelectionIndex();
swap(selection, selection - 1);
}
public void swap(int index1, int index2) {
RequiredExecutionEnvironmentHeader header = getHeader();
header.swap(index1, index2);
}
private void handleRemove() {
IStructuredSelection ssel = fEETable.getStructuredSelection();
if (ssel.size() > 0) {
Iterator<?> iter = ssel.iterator();
while (iter.hasNext()) {
Object object = iter.next();
if (object instanceof ExecutionEnvironment) {
getHeader().removeExecutionEnvironment((ExecutionEnvironment) object);
}
}
}
}
private void handleAdd() {
ElementListSelectionDialog dialog = new ElementListSelectionDialog(PDEPlugin.getActiveWorkbenchShell(), new EELabelProvider());
dialog.setElements(getEnvironments());
dialog.setAllowDuplicates(false);
dialog.setMultipleSelection(true);
dialog.setTitle(PDEUIMessages.RequiredExecutionEnvironmentSection_dialog_title);
dialog.setMessage(PDEUIMessages.RequiredExecutionEnvironmentSection_dialogMessage);
dialog.create();
PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IHelpContextIds.EXECUTION_ENVIRONMENT_SELECTION);
if (dialog.open() == Window.OK) {
addExecutionEnvironments(dialog.getResult());
}
}
private void addExecutionEnvironments(Object[] result) {
IManifestHeader header = getHeader();
if (header == null) {
StringBuilder buffer = new StringBuilder();
for (Object resultObject : result) {
String id = null;
if (resultObject instanceof IExecutionEnvironment)
id = ((IExecutionEnvironment) resultObject).getId();
else if (resultObject instanceof ExecutionEnvironment)
id = ((ExecutionEnvironment) resultObject).getName();
else
continue;
if (buffer.length() > 0) {
buffer.append(","); //$NON-NLS-1$
buffer.append(getLineDelimiter());
buffer.append(" "); //$NON-NLS-1$
}
buffer.append(id);
}
getBundle().setHeader(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT, buffer.toString());
} else {
RequiredExecutionEnvironmentHeader ee = (RequiredExecutionEnvironmentHeader) header;
ee.addExecutionEnvironments(result);
}
}
private String getLineDelimiter() {
BundleInputContext inputContext = getBundleContext();
if (inputContext != null) {
return inputContext.getLineDelimiter();
}
return System.getProperty("line.separator"); //$NON-NLS-1$
}
private Object[] getEnvironments() {
RequiredExecutionEnvironmentHeader header = getHeader();
IExecutionEnvironment[] envs = JavaRuntime.getExecutionEnvironmentsManager().getExecutionEnvironments();
if (header == null)
return envs;
ArrayList<Object> list = new ArrayList<>();
for (int i = 0; i < envs.length; i++) {
if (!header.hasExecutionEnvironment(envs[i]))
list.add(envs[i]);
}
return list.toArray();
}
@Override
public void modelChanged(IModelChangedEvent e) {
if (e.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
markStale();
} else if (e.getChangeType() == IModelChangedEvent.REMOVE) {
Object[] objects = e.getChangedObjects();
for (Object object : objects) {
Table table = fEETable.getTable();
if (object instanceof ExecutionEnvironment) {
int index = table.getSelectionIndex();
fEETable.remove(object);
if (canSelect()) {
table.setSelection(index < table.getItemCount() ? index : table.getItemCount() - 1);
}
}
}
updateButtons();
} else if (e.getChangeType() == IModelChangedEvent.INSERT) {
Object[] objects = e.getChangedObjects();
if (objects.length > 0) {
fEETable.refresh();
fEETable.setSelection(new StructuredSelection(objects[objects.length - 1]));
}
updateButtons();
} else if (Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT.equals(e.getChangedProperty())) {
refresh();
// Bug 171896
// Since the model sends a CHANGE event instead of
// an INSERT event on the very first addition to the empty table
// Selection should fire here to take this first insertion into account
Object lastElement = fEETable.getElementAt(fEETable.getTable().getItemCount() - 1);
if (lastElement != null) {
fEETable.setSelection(new StructuredSelection(lastElement));
}
}
}
private BundleInputContext getBundleContext() {
InputContextManager manager = getPage().getPDEEditor().getContextManager();
return (BundleInputContext) manager.findContext(BundleInputContext.CONTEXT_ID);
}
private IBundle getBundle() {
IBundleModel model = getBundleModel();
return model == null ? null : model.getBundle();
}
private IBundleModel getBundleModel() {
BundleInputContext context = getBundleContext();
return context == null ? null : (IBundleModel) context.getModel();
}
protected RequiredExecutionEnvironmentHeader getHeader() {
IBundle bundle = getBundle();
if (bundle == null)
return null;
IManifestHeader header = bundle.getManifestHeader(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
if (header instanceof RequiredExecutionEnvironmentHeader)
return (RequiredExecutionEnvironmentHeader) header;
return null;
}
protected boolean isFragment() {
InputContextManager manager = getPage().getPDEEditor().getContextManager();
IPluginModelBase model = (IPluginModelBase) manager.getAggregateModel();
return model.isFragmentModel();
}
@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
protected boolean canPaste(Object target, Object[] objects) {
RequiredExecutionEnvironmentHeader header = getHeader();
for (Object object : objects) {
if (object instanceof ExecutionEnvironment) {
String env = ((ExecutionEnvironment) object).getName();
if (header == null || !header.hasElement(env))
return true;
}
}
return false;
}
@Override
protected void selectionChanged(IStructuredSelection selection) {
getPage().getPDEEditor().setSelection(selection);
if (getPage().getModel().isEditable())
updateButtons();
}
@Override
protected void doPaste(Object target, Object[] objects) {
addExecutionEnvironments(objects);
}
private void doFullBuild(final IProject project) {
Job buildJob = new Job(PDEUIMessages.CompilersConfigurationBlock_building) {
@Override
public boolean belongsTo(Object family) {
return ResourcesPlugin.FAMILY_MANUAL_BUILD == family;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
project.build(IncrementalProjectBuilder.FULL_BUILD, JavaCore.BUILDER_ID, null, monitor);
} catch (CoreException e) {
}
return Status.OK_STATUS;
}
};
buildJob.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule());
buildJob.schedule();
}
@Override
protected boolean isDragAndDropEnabled() {
return true;
}
@Override
public boolean canDragMove(Object[] sourceObjects) {
if (validateDragMoveSanity(sourceObjects) == false) {
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
ExecutionEnvironment sourceEEObject = (ExecutionEnvironment) sourceObjects[0];
ExecutionEnvironment targetEEObject = (ExecutionEnvironment) targetObject;
// Validate model
if (validateDropMoveModel(sourceEEObject, targetEEObject) == false) {
return false;
}
// Validate move
if (targetLocation == ViewerDropAdapter.LOCATION_BEFORE) {
// Get the previous element of the target
RequiredExecutionEnvironmentHeader header = getHeader();
// Ensure we have a header
if (header == null) {
return false;
}
// Get the previous element of the target
PDEManifestElement previousElement = header.getPreviousElement(targetEEObject);
// Ensure the previous element is not the source
if (sourceEEObject.equals(previousElement)) {
return false;
}
return true;
} else if (targetLocation == ViewerDropAdapter.LOCATION_AFTER) {
// Get the next element of the target
RequiredExecutionEnvironmentHeader header = getHeader();
// Ensure we have a header
if (header == null) {
return false;
}
// Get the next element of the target
PDEManifestElement nextElement = header.getNextElement(targetEEObject);
// Ensure the next element is not the source
if (sourceEEObject.equals(nextElement)) {
return false;
}
return true;
} else if (targetLocation == ViewerDropAdapter.LOCATION_ON) {
// Not supported
return false;
}
return false;
}
private boolean validateDropMoveModel(ExecutionEnvironment sourceEEObject, ExecutionEnvironment targetEEObject) {
// Objects have to be from the same model
IBundleModel sourceModel = sourceEEObject.getModel();
IBundleModel targetModel = targetEEObject.getModel();
if (sourceModel.equals(targetModel)) {
return true;
}
return false;
}
private boolean validateDropMoveSanity(Object targetObject, Object[] sourceObjects) {
// Validate target object
if ((targetObject instanceof ExecutionEnvironment) == false) {
return false;
}
// Validate source objects
if (validateDragMoveSanity(sourceObjects) == 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
ExecutionEnvironment sourceEEObject = (ExecutionEnvironment) sourceObjects[0];
ExecutionEnvironment targetEEObject = (ExecutionEnvironment) targetObject;
// Validate move
if (targetLocation == ViewerDropAdapter.LOCATION_BEFORE) {
// Get the header
RequiredExecutionEnvironmentHeader header = getHeader();
// Ensure we have a header
if (header == null) {
return;
}
// Get the index of the target
int index = header.indexOf(targetEEObject);
// Ensure the target index was found
if (index == -1) {
return;
}
// Add source as sibling of target (before)
header.addExecutionEnvironment(sourceEEObject, index);
return;
} else if (targetLocation == ViewerDropAdapter.LOCATION_AFTER) {
// Get the header
RequiredExecutionEnvironmentHeader header = getHeader();
// Ensure we have a header
if (header == null) {
return;
}
// Get the index of the target
int index = header.indexOf(targetEEObject);
// Ensure the target index was found
if (index == -1) {
return;
}
// Add source as sibling of target (before)
header.addExecutionEnvironment(sourceEEObject, index + 1);
return;
} else if (targetLocation == ViewerDropAdapter.LOCATION_ON) {
// NO-OP. Not supported
}
}
@Override
public void doDragRemove(Object[] sourceObjects) {
// Validate source
if (validateDragMoveSanity(sourceObjects) == false) {
return;
}
// Get the source
ExecutionEnvironment environment = (ExecutionEnvironment) sourceObjects[0];
// Get the header
RequiredExecutionEnvironmentHeader header = getHeader();
// Ensure we have a header
if (header == null) {
return;
}
// Remove the source
doSelect(false);
header.removeExecutionEnvironmentUnique(environment);
doSelect(true);
}
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 ExecutionEnvironment) == false) {
// Must be the right type
return false;
}
return true;
}
}