blob: 661c53527d82f8e99e0e3a8a43323503fde8839b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
*******************************************************************************/
package org.eclipse.dltk.ui.preferences;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IScriptLanguageProvider;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.internal.ui.actions.WorkbenchRunnableAdapter;
import org.eclipse.dltk.internal.ui.dialogs.StatusUtil;
import org.eclipse.dltk.ui.DLTKUIPlugin;
import org.eclipse.dltk.ui.util.ExceptionHandler;
import org.eclipse.dltk.ui.util.IStatusChangeListener;
import org.eclipse.dltk.ui.wizards.BuildpathsBlock;
import org.eclipse.dltk.utils.AdaptUtils;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.preference.IPreferencePageContainer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.dialogs.PropertyPage;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
/**
* Property page for configuring the DLTK build path
*/
public abstract class BuildPathsPropertyPage extends PropertyPage implements
IStatusChangeListener, IScriptLanguageProvider {
public static final String PROP_ID = "org.eclipse.dltk.ui.propertyPages.BuildPathsPropertyPage"; //$NON-NLS-1$
private static final String PAGE_SETTINGS = "BuildPathsPropertyPage"; //$NON-NLS-1$
protected static final String INDEX = "pageIndex"; //$NON-NLS-1$
public static final Object DATA_ADD_ENTRY = "add_buildpath_entry"; //$NON-NLS-1$
public static final Object DATA_REVEAL_ENTRY = "select_buildpath_entry"; //$NON-NLS-1$
public static final Object DATA_REVEAL_ATTRIBUTE_KEY = "select_buildpath_attribute_key"; //$NON-NLS-1$
public static final Object DATA_BLOCK = "block_until_buildpath_applied"; //$NON-NLS-1$
private BuildpathsBlock fBuildPathsBlock;
private boolean fBlockOnApply = false;
@Override
protected Control createContents(Composite parent) {
// ensure the page has no special buttons
noDefaultAndApplyButton();
IProject project = getProject();
Control result;
if (project == null || !isValidProject(project)) {
result = createWithoutScript(parent);
} else if (!project.isOpen()) {
result = createForClosedProject(parent);
} else {
result = createWith(parent, project);
}
Dialog.applyDialogFont(result);
return result;
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
// PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
// IHelpContextIds.BUILD_PATH_PROPERTY_PAGE);
}
protected IDialogSettings getSettings() {
IDialogSettings javaSettings = DLTKUIPlugin.getDefault()
.getDialogSettings();
IDialogSettings pageSettings = javaSettings.getSection(PAGE_SETTINGS);
if (pageSettings == null) {
pageSettings = javaSettings.addNewSection(PAGE_SETTINGS);
pageSettings.put(INDEX, 3);
}
return pageSettings;
}
@Override
public void setVisible(boolean visible) {
if (fBuildPathsBlock != null) {
if (!visible) {
if (fBuildPathsBlock.hasChangesInDialog()) {
String title = PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_title;
String message = PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_message;
String[] buttonLabels = new String[] {
PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_button_save,
PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_button_discard,
PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_button_ignore };
MessageDialog dialog = new MessageDialog(getShell(), title,
null, message, MessageDialog.QUESTION,
buttonLabels, 0);
int res = dialog.open();
if (res == 0) {
performOk();
} else if (res == 1) {
fBuildPathsBlock.init(DLTKCore.create(getProject()),
null);
} else {
// keep unsaved
}
}
} else {
if (!fBuildPathsBlock.hasChangesInDialog()
&& fBuildPathsBlock.hasChangesInBuildpathFile()) {
fBuildPathsBlock.init(DLTKCore.create(getProject()), null);
}
}
}
super.setVisible(visible);
}
/*
* Content for valid projects.
*/
private Control createWith(Composite parent, IProject project) {
IWorkbenchPreferenceContainer pageContainer = null;
IPreferencePageContainer container = getContainer();
if (container instanceof IWorkbenchPreferenceContainer) {
pageContainer = (IWorkbenchPreferenceContainer) container;
}
fBuildPathsBlock = createBuildPathBlock(pageContainer);
fBuildPathsBlock.init(DLTKCore.create(project), null);
return fBuildPathsBlock.createControl(parent);
}
protected BuildpathsBlock createBuildPathBlock(
IWorkbenchPreferenceContainer pageContainer) {
return new BuildpathsBlock(this, getSettings().getInt(INDEX), false,
pageContainer);
}
/*
* Content for non-script projects.
*/
private Control createWithoutScript(Composite parent) {
Label label = new Label(parent, SWT.LEFT);
label
.setText(PreferencesMessages.BuildPathsPropertyPage_no_script_project_message);
fBuildPathsBlock = null;
setValid(true);
return label;
}
/*
* Content for closed projects.
*/
private Control createForClosedProject(Composite parent) {
Label label = new Label(parent, SWT.LEFT);
label
.setText(PreferencesMessages.BuildPathsPropertyPage_closed_project_message);
fBuildPathsBlock = null;
setValid(true);
return label;
}
protected IProject getProject() {
final IAdaptable adaptable = getElement();
IProject project = AdaptUtils.getAdapter(adaptable, IProject.class);
if (project != null) {
return project;
}
final IModelElement elem = AdaptUtils.getAdapter(adaptable,
IModelElement.class);
if (elem instanceof IScriptProject) {
return ((IScriptProject) elem).getProject();
}
return null;
}
protected boolean isValidProject(IProject proj) {
return DLTKLanguageManager.hasScriptNature(proj);
}
@Override
public boolean performOk() {
if (fBuildPathsBlock != null) {
getSettings().put(INDEX, fBuildPathsBlock.getPageIndex());
if (fBuildPathsBlock.hasChangesInDialog()) {
IWorkspaceRunnable runnable = monitor -> fBuildPathsBlock.configureScriptProject(monitor);
WorkbenchRunnableAdapter op = new WorkbenchRunnableAdapter(
runnable);
if (fBlockOnApply) {
try {
new ProgressMonitorDialog(getShell()).run(true, true,
op);
} catch (InvocationTargetException e) {
ExceptionHandler
.handle(
e,
getShell(),
PreferencesMessages.BuildPathsPropertyPage_error_title,
PreferencesMessages.BuildPathsPropertyPage_error_message);
return false;
} catch (InterruptedException e) {
return false;
}
} else {
op
.runAsUserJob(
PreferencesMessages.BuildPathsPropertyPage_job_title,
null);
}
}
}
return true;
}
@Override
public void statusChanged(IStatus status) {
setValid(!status.matches(IStatus.ERROR));
StatusUtil.applyToStatusLine(this, status);
}
@Override
public void applyData(Object data) {
if (data instanceof Map) {
Map map = (Map) data;
Object selectedLibrary = map.get(DATA_REVEAL_ENTRY);
if (selectedLibrary instanceof IBuildpathEntry) {
IBuildpathEntry entry = (IBuildpathEntry) selectedLibrary;
Object attr = map.get(DATA_REVEAL_ATTRIBUTE_KEY);
String attributeKey = attr instanceof String ? (String) attr
: null;
if (fBuildPathsBlock != null) {
fBuildPathsBlock.setElementToReveal(entry, attributeKey);
}
}
Object entryToAdd = map.get(DATA_ADD_ENTRY);
if (entryToAdd instanceof IBuildpathEntry) {
if (fBuildPathsBlock != null) {
fBuildPathsBlock.addElement((IBuildpathEntry) entryToAdd);
}
}
fBlockOnApply = Boolean.TRUE.equals(map.get(DATA_BLOCK));
}
}
}