blob: 3f8aa87ae00bfcb7cd68f0c8382c3445067ea7cd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2018 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Manumitting Technologies Inc - bug 324310
*******************************************************************************/
package org.eclipse.pde.api.tools.ui.internal.wizards;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.pde.api.tools.internal.model.ApiModelFactory;
import org.eclipse.pde.api.tools.internal.model.SystemLibraryApiComponent;
import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
import org.eclipse.pde.api.tools.ui.internal.ApiToolsLabelProvider;
import org.eclipse.pde.api.tools.ui.internal.IApiToolsHelpContextIds;
import org.eclipse.pde.api.tools.ui.internal.SWTFactory;
import org.eclipse.pde.core.target.ITargetDefinition;
import org.eclipse.pde.core.target.ITargetHandle;
import org.eclipse.pde.core.target.ITargetPlatformService;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.PlatformUI;
/**
* Define a baseline from a Target Definition
*
* @since 1.0.600
*/
public class TargetBasedApiBaselineWizardPage extends ApiBaselineWizardPage {
public static boolean isApplicable(IApiBaseline profile) {
return ApiModelFactory.isDerivedFromTarget(profile);
}
/**
* Resets the baseline contents based on current settings and a target
* definition from which to read plug-ins.
*/
class ReloadTargetOperation implements IRunnableWithProgress {
private ITargetDefinition definition;
private String name;
/**
* Constructor
*
* @param platformPath
*/
public ReloadTargetOperation(ITargetDefinition definition, String name) {
this.definition = definition;
this.name = name;
}
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
fProfile = ApiModelFactory.newApiBaselineFromTarget(name, definition, monitor);
TargetBasedApiBaselineWizardPage.this.contentchange = true;
} catch (CoreException e) {
// error reported via the definition's status in pageValid()
ApiPlugin.log(e);
}
}
}
private static class TargetLabelProvider extends StyledCellLabelProvider {
@SuppressWarnings("restriction")
private final org.eclipse.pde.internal.ui.PDELabelProvider pdeLabelProvider = org.eclipse.pde.internal.ui.PDEPlugin
.getDefault().getLabelProvider();
public TargetLabelProvider() {
pdeLabelProvider.connect(this);
}
@Override
@SuppressWarnings("restriction")
public void update(ViewerCell cell) {
final Object element = cell.getElement();
ITargetDefinition targetDef = (ITargetDefinition) element;
ITargetHandle targetHandle = targetDef.getHandle();
String name = targetDef.getName();
if (name == null || name.length() == 0) {
name = targetHandle.toString();
}
StyledString styledString = new StyledString(name);
if (targetHandle instanceof org.eclipse.pde.internal.core.target.WorkspaceFileTargetHandle) {
IFile file = ((org.eclipse.pde.internal.core.target.WorkspaceFileTargetHandle) targetHandle)
.getTargetFile();
String location = " - " + file.getFullPath(); //$NON-NLS-1$
styledString.append(location, StyledString.DECORATIONS_STYLER);
} else if (targetHandle instanceof org.eclipse.pde.internal.core.target.ExternalFileTargetHandle) {
URI uri = ((org.eclipse.pde.internal.core.target.ExternalFileTargetHandle) targetHandle).getLocation();
String location = " - " + uri.toASCIIString(); //$NON-NLS-1$
styledString.append(location, StyledString.DECORATIONS_STYLER);
}
cell.setText(styledString.toString());
cell.setStyleRanges(styledString.getStyleRanges());
cell.setImage(getImage(targetDef));
super.update(cell);
}
@SuppressWarnings("restriction")
public Image getImage(Object e) {
return pdeLabelProvider.get(org.eclipse.pde.internal.ui.PDEPluginImages.DESC_TARGET_DEFINITION);
}
@Override
public void dispose() {
pdeLabelProvider.disconnect(this);
super.dispose();
}
}
/**
* Initial collection of targets (handles are realized into definitions as
* working copies)
*/
private List<ITargetDefinition> fTargets = new ArrayList<>();
private ITargetDefinition selectedTargetDefinition;
/**
* widgets
*/
private Text nametext = null;
private CheckboxTableViewer targetsViewer;
private TreeViewer treeviewer = null;
private Button reloadbutton = null;
public TargetBasedApiBaselineWizardPage(IApiBaseline profile) {
super(profile);
}
@Override
public void createControl(Composite parent) {
Composite comp = SWTFactory.createComposite(parent, 4, 1, GridData.FILL_HORIZONTAL);
SWTFactory.createWrapLabel(comp, WizardMessages.ApiProfileWizardPage_5, 1);
nametext = SWTFactory.createText(comp, SWT.BORDER | SWT.SINGLE, 3, GridData.FILL_HORIZONTAL | GridData.BEGINNING);
nametext.addModifyListener(e -> setPageComplete(pageValid()));
SWTFactory.createVerticalSpacer(comp, 1);
targetsViewer = CheckboxTableViewer.newCheckList(comp, SWT.MULTI | SWT.BORDER);
GridDataFactory.fillDefaults().span(3, 1).grab(true, true).applyTo(targetsViewer.getControl());
targetsViewer.setLabelProvider(new TargetLabelProvider());
targetsViewer.setContentProvider(ArrayContentProvider.getInstance());
targetsViewer.addCheckStateListener(event -> {
if (event.getChecked()) {
targetsViewer.setCheckedElements(new Object[] { event.getElement() });
selectedTargetDefinition = (ITargetDefinition) event.getElement();
} else {
selectedTargetDefinition = null;
}
updateButtons();
setPageComplete(pageValid());
});
// add the targets
ITargetPlatformService service = getTargetService();
if (service != null) {
for (ITargetHandle handle : service.getTargets(null)) {
try {
fTargets.add(handle.getTargetDefinition());
} catch (CoreException e) {
PDECore.log(e);
}
}
if (fTargets.isEmpty()) {
// Ensure we have at least a default TP
try {
fTargets.add(service.getWorkspaceTargetDefinition());
} catch (CoreException e) {
PDECore.log(e);
}
}
targetsViewer.setInput(fTargets);
}
targetsViewer.setComparator(new ViewerComparator() {
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
String name1 = ((ITargetDefinition) e1).getName();
String name2 = ((ITargetDefinition) e2).getName();
if (name1 == null) {
return -1;
}
if (name2 == null) {
return 1;
}
return name1.compareToIgnoreCase(name2);
}
});
reloadbutton = SWTFactory.createPushButton(comp, WizardMessages.ApiProfileWizardPage_12, null);
reloadbutton.setEnabled(targetsViewer.getCheckedElements().length == 1);
reloadbutton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> doReload()));
SWTFactory.createWrapLabel(comp, WizardMessages.ApiProfileWizardPage_13, 4);
Tree tree = new Tree(comp, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.heightHint = 100;
gd.horizontalSpan = 4;
tree.setLayoutData(gd);
treeviewer = new TreeViewer(tree);
treeviewer.setLabelProvider(new ApiToolsLabelProvider());
treeviewer.setContentProvider(new ContentProvider());
treeviewer.setComparator(new ViewerComparator());
treeviewer.setInput(getCurrentComponents());
treeviewer.addSelectionChangedListener(event -> updateButtons());
treeviewer.addFilter(new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (element instanceof IApiComponent) {
IApiComponent component = (IApiComponent) element;
try {
if (component.isSourceComponent() || component.isSystemComponent()) {
return false;
}
} catch (CoreException e) {
ApiPlugin.log(e);
}
return true;
}
return !(element instanceof SystemLibraryApiComponent);
}
});
setControl(comp);
if (fProfile != null) {
nametext.setText(fProfile.getName());
ITargetDefinition found = null;
// Use isDerivedFromTarget as the target may have had its
// sequence number bumped several times
for (ITargetDefinition target : fTargets) {
if (ApiModelFactory.isDerivedFromTarget(fProfile, target)) {
found = target;
break;
}
}
if (found != null) {
selectedTargetDefinition = found;
targetsViewer.setCheckedElements(new Object[] { found });
}
}
initialize();
updateButtons();
setPageComplete(pageValid());
PlatformUI.getWorkbench().getHelpSystem().setHelp(comp, IApiToolsHelpContextIds.APIPROFILES_WIZARD_PAGE);
Dialog.applyDialogFont(comp);
}
/**
* @return if the page is valid, such that it is considered complete and can
* be 'finished'
*/
protected boolean pageValid() {
setErrorMessage(null);
// If a target is selected then report any resolving problems before
// any missing-name errors. It's strange to click on 'reset' and see
// the progress bar and having any resolving errors masked by a
// missing-name or no-bundles-error
ITargetDefinition selected = getSelectedTargetDefinition();
if (selected != null && selected.getStatus() != null && !selected.getStatus().isOK()) {
setErrorMessage(WizardMessages.TargetBasedApiBaselineWizardPage_loading_error);
return false;
}
if (!isNameValid(nametext.getText().trim())) {
return false;
}
if(targetsViewer.getCheckedElements().length != 1) {
setErrorMessage(WizardMessages.ApiProfileWizardPage_select_target);
reloadbutton.setEnabled(false);
return false;
}
if (fProfile != null) {
if (fProfile.getApiComponents().length == 0) {
setErrorMessage(WizardMessages.ApiProfileWizardPage_2);
return false;
}
IStatus status = fProfile.getExecutionEnvironmentStatus();
if (status.getSeverity() == IStatus.ERROR) {
setErrorMessage(status.getMessage());
return false;
}
if (!ApiModelFactory.isUpToDateWithTarget(fProfile, selected)) {
setErrorMessage(WizardMessages.ApiProfileWizardPage_location_needs_reset);
return false;
}
} else {
setErrorMessage(WizardMessages.ApiProfileWizardPage_location_needs_reset);
return false;
}
return true;
}
private ITargetDefinition getSelectedTargetDefinition() {
// don't query the table directly as may be called from non-UI thread
return selectedTargetDefinition;
}
/**
* Updates the state of a variety of buttons on this page
*/
protected void updateButtons() {
reloadbutton.setEnabled(getSelectedTargetDefinition() != null);
}
@Override
public IApiBaseline finish() throws IOException, CoreException {
if (fProfile != null) {
fProfile.setName(nametext.getText().trim());
}
return fProfile;
}
/**
* Reloads all of the plugins from the location specified in the location
* text field.
*/
protected void doReload() {
IRunnableWithProgress op = new ReloadTargetOperation(getSelectedTargetDefinition(), nametext.getText().trim());
try {
getContainer().run(true, true, op);
treeviewer.setInput(getCurrentComponents());
treeviewer.refresh();
setPageComplete(pageValid());
} catch (InvocationTargetException | InterruptedException ie) {
}
}
private ITargetPlatformService getTargetService() {
return ApiPlugin.getDefault().acquireService(ITargetPlatformService.class);
}
}