| /******************************************************************************* |
| * 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)); |
| } |
| } |
| |
| } |