/*******************************************************************************
* Copyright (c) 2010, 2013 Andrew Gvozdev 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:
* Andrew Gvozdev - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.language.settings.providers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsEditableProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsSerializableProvider;
import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICResourceDescription;
import org.eclipse.cdt.ui.CDTSharedImages;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.dialogs.ICOptionPage;
import org.eclipse.cdt.ui.language.settings.providers.AbstractLanguageSettingProviderOptionPage;
import org.eclipse.cdt.ui.newui.AbstractCPropertyTab;
import org.eclipse.cdt.utils.ui.controls.TabFolderLayout;
import org.eclipse.cdt.internal.ui.newui.Messages;
import org.eclipse.cdt.internal.ui.newui.StatusMessageLine;
/**
* This tab presents language settings entries categorized by language
* settings providers.
*
*@noinstantiate This class is not intended to be instantiated by clients.
*@noextend This class is not intended to be subclassed by clients.
*/
public class LanguageSettingsProviderTab extends AbstractCPropertyTab {
private static final String WORKSPACE_PREFERENCE_PAGE = "org.eclipse.cdt.ui.preferences.BuildSettingProperties"; //$NON-NLS-1$
private static final String TEST_PLUGIN_ID_PATTERN = "org.eclipse.cdt.*.tests.*"; //$NON-NLS-1$
private static final String CLEAR_STR = Messages.LanguageSettingsProviderTab_Clear;
private static final String RESET_STR = Messages.LanguageSettingsProviderTab_Reset;
private static final int BUTTON_CLEAR = 0;
private static final int BUTTON_RESET = 1;
// there is a separator instead of button #2
private static final int BUTTON_MOVE_UP = 3;
private static final int BUTTON_MOVE_DOWN = 4;
private static final int[] DEFAULT_CONFIGURE_SASH_WEIGHTS = new int[] { 50, 50 };
private SashForm sashFormProviders;
private Table tableProviders;
private CheckboxTableViewer tableProvidersViewer;
private Group groupOptionsPage;
private ICOptionPage currentOptionsPage = null;
private Composite compositeOptionsPage;
private StatusMessageLine fStatusLine;
private Button sharedProviderCheckBox = null;
private Link linkToWorkspacePreferences = null;
private Button projectStorageCheckBox = null;
private LanguageSettingsProvidersPage masterPropertyPage = null;
/**
* List of providers presented to the user.
* For global providers included in a configuration this contains references
* not raw providers.
*/
private List<ILanguageSettingsProvider> presentedProviders = null;
private final Map<String, ICOptionPage> optionsPageMap = new HashMap<String, ICOptionPage>();
private Map<String/*cfgId*/, List<ILanguageSettingsProvider>> initialProvidersByCfg = new HashMap<String, List<ILanguageSettingsProvider>>();
/**
* Label provider for language settings providers displayed by this tab.
*/
private class ProvidersTableLabelProvider extends LanguageSettingsProvidersLabelProvider {
@Override
protected String[] getOverlayKeys(ILanguageSettingsProvider provider) {
String[] overlayKeys = super.getOverlayKeys(provider);
if (provider.getName() == null) {
return overlayKeys;
}
if (page.isForProject()) {
if (isEditedForProject(provider)) {
overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_EDITED;
} else if (!LanguageSettingsManager.getExtensionProviderIds().contains(provider.getId())) {
overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_USER;
} else if (isReconfiguredForProject(provider)) {
overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_SETTING;
}
} else if (page.isForPrefs()) {
if (isWorkingCopy(provider) && !provider.equals(LanguageSettingsManager.getRawProvider(LanguageSettingsManager.getWorkspaceProvider(provider.getId())))) {
overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_EDITED;
} else if (!LanguageSettingsManager.getExtensionProviderIds().contains(provider.getId())) {
overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_USER;
} else {
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider);
if (rawProvider instanceof ILanguageSettingsEditableProvider && !LanguageSettingsManager.isEqualExtensionProvider(rawProvider, false)) {
overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_SETTING;
}
}
}
return overlayKeys;
}
@Override
public String getText(Object element) {
if (element instanceof ILanguageSettingsProvider) {
ILanguageSettingsProvider provider = (ILanguageSettingsProvider) element;
String name = provider.getName();
if (name != null && (page.isForPrefs() || isPresentedAsShared(provider))) {
return name + Messages.LanguageSettingsProvidersLabelProvider_TextDecorator_Shared;
}
}
return super.getText(element);
}
}
/**
* Returns the provider which is being presented to the user in UI.
* Used by option pages when there is a need.
* Warning: Do not cache the result as the provider can be replaced at any time.
* @param id - id of the provider.
*
* @return the provider.
*/
public ILanguageSettingsProvider getProvider(String id) {
return findProvider(id, presentedProviders);
}
/**
* Returns the provider equal to provider at the point from which editing started.
* Used by option pages when there is a need.
* @param id - id of the provider.
*
* @return the initial provider.
*/
public ILanguageSettingsProvider getInitialProvider(String id) {
ILanguageSettingsProvider initialProvider = null;
if (page.isForPrefs()) {
initialProvider = LanguageSettingsManager.getWorkspaceProvider(id);
} else {
ICConfigurationDescription cfgDescription = getConfigurationDescription();
List<ILanguageSettingsProvider> initialProviders = initialProvidersByCfg.get(cfgDescription.getId());
initialProvider = findProvider(id, initialProviders);
}
return initialProvider;
}
/**
* Check if the provider is a working copy and can be modified.
*/
private boolean isWorkingCopy(ILanguageSettingsProvider provider) {
boolean isWorkingCopy = false;
if (page.isForPrefs()) {
isWorkingCopy = ! LanguageSettingsManager.isWorkspaceProvider(provider);
} else {
if (!LanguageSettingsManager.isWorkspaceProvider(provider)) {
ICConfigurationDescription cfgDescription = getConfigurationDescription();
List<ILanguageSettingsProvider> initialProviders = initialProvidersByCfg.get(cfgDescription.getId());
isWorkingCopy = initialProviders != null && ! initialProviders.contains(provider);
}
}
return isWorkingCopy;
}
/**
* Returns current working copy of the provider. Creates one if it has not been created yet.
* A working copy will be discarded if user pushes [Cancel] or it will replace original
* provider on [Apply] or [OK].
*
* This method is used also by option pages when there is a need to modify the provider.
* Warning: Do not cache the result as the provider can be replaced at any time.
*
* @param id - id of the provider.
* @return working copy of the provider.
*/
public ILanguageSettingsProvider getWorkingCopy(String id) {
ILanguageSettingsProvider provider = findProvider(id, presentedProviders);
if (isWorkingCopy(provider)) {
return provider;
}
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider);
ILanguageSettingsEditableProvider newProvider = LanguageSettingsManager.getProviderCopy((ILanguageSettingsEditableProvider)rawProvider, true);
if (newProvider != null) {
replaceSelectedProvider(newProvider);
// Warning: Do not initializeOptionsPage() here as the method can be called from an existing page
}
return newProvider;
}
/**
* Refresh provider item in the table and update buttons.
* This method is intended for use by an Options Page of the provider.
*
* @param provider - provider item in the table to refresh.
*/
public void refreshItem(ILanguageSettingsProvider provider) {
tableProvidersViewer.refresh(provider);
updateButtons();
}
/**
* Check if provider should get "reconfigured" overlay in UI.
*/
private boolean isReconfiguredForProject(ILanguageSettingsProvider provider) {
String id = provider.getId();
ICConfigurationDescription cfgDescription = getConfigurationDescription();
String[] defaultIds = ((ILanguageSettingsProvidersKeeper) cfgDescription).getDefaultLanguageSettingsProvidersIds();
List<ILanguageSettingsProvider> providers = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
// check for the provider mismatch in configuration list vs. default list from the tool-chain
if (defaultIds != null && (Arrays.asList(defaultIds).contains(id) != providers.contains(provider))) {
return true;
}
// check if provider belongs to configuration (i.e. checked in the table)
if (!providers.contains(provider)) {
return false;
}
// check if "shared" flag matches default shared preference from extension point definition
if (LanguageSettingsManager.isPreferShared(id) != LanguageSettingsManager.isWorkspaceProvider(provider)) {
return true;
}
// check if configuration provider equals to the default one from extension point
if (!LanguageSettingsManager.isWorkspaceProvider(provider) && !LanguageSettingsManager.isEqualExtensionProvider(provider, false)) {
return true;
}
return false;
}
/**
* Check if provider should get "edited" overlay in UI.
*/
private boolean isEditedForProject(ILanguageSettingsProvider provider) {
String id = provider.getId();
ICConfigurationDescription cfgDescription = getConfigurationDescription();
List<ILanguageSettingsProvider> initialProviders = initialProvidersByCfg.get(cfgDescription.getId());
List<ILanguageSettingsProvider> providers = getCheckedProviders();
// check for the provider mismatch in configuration list vs. initial list
ILanguageSettingsProvider initialProvider = findProvider(id, initialProviders);
if ((initialProvider != null) != providers.contains(provider)) {
return true;
}
// check if "shared" flag matches that of initial provider
if (providers.contains(provider) && LanguageSettingsManager.isWorkspaceProvider(initialProvider) != LanguageSettingsManager.isWorkspaceProvider(provider)) {
return true;
}
// check if configuration provider equals to the initial one
if (!LanguageSettingsManager.isWorkspaceProvider(provider) && !provider.equals(initialProvider)) {
return true;
}
return false;
}
/**
* Checks if the provider should be presented as shared. Unchecked providers are shown as non-shared
* if they are defined as non-shared in extension point even if in fact shared instance is used to display
* the options page.
*/
private boolean isPresentedAsShared(ILanguageSettingsProvider provider) {
ICConfigurationDescription cfgDescription = getConfigurationDescription();
List<ILanguageSettingsProvider> providers = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
return LanguageSettingsManager.isWorkspaceProvider(provider) &&
( providers.contains(provider) || LanguageSettingsManager.isPreferShared(provider.getId()) );
}
/**
* Find provider with a given ID in the list or {@code null}.
*/
private ILanguageSettingsProvider findProvider(String id, List<ILanguageSettingsProvider> providers) {
if (providers != null) {
for (ILanguageSettingsProvider provider : providers) {
if (provider.getId().equals(id)) {
return provider;
}
}
}
return null;
}
/**
* Shortcut for getting the currently selected provider.
* Do not use if you need to change provider's settings or entries, use {@link #getWorkingCopy(String)}.
*/
private ILanguageSettingsProvider getSelectedProvider() {
ILanguageSettingsProvider provider = null;
int pos = tableProviders.getSelectionIndex();
if (pos >= 0 && pos < tableProviders.getItemCount()) {
provider = (ILanguageSettingsProvider)tableProvidersViewer.getElementAt(pos);
}
return provider;
}
/**
* Shortcut for getting the current configuration description.
*/
private ICConfigurationDescription getConfigurationDescription() {
if (page.isForPrefs()) {
return null;
}
return getResDesc().getConfiguration();
}
/**
* Get the list of providers checked in the table in UI.
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private List<ILanguageSettingsProvider> getCheckedProviders() {
return (List)Arrays.asList(tableProvidersViewer.getCheckedElements());
}
/**
* Replace the selected provider in UI and in configuration.
*/
private void replaceSelectedProvider(ILanguageSettingsProvider newProvider) {
int pos = tableProviders.getSelectionIndex();
boolean isChecked = tableProvidersViewer.getChecked(tableProvidersViewer.getElementAt(pos));
presentedProviders.set(pos, newProvider);
tableProvidersViewer.refresh();
tableProvidersViewer.setChecked(newProvider, isChecked);
tableProviders.setSelection(pos);
saveCheckedProviders();
tableProvidersViewer.refresh(newProvider);
}
/**
* Save checked providers from UI table into configuration.
*/
private void saveCheckedProviders() {
ICConfigurationDescription cfgDescription = getConfigurationDescription();
if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(getCheckedProviders());
}
}
/**
* Store original providers to be able to tell whether they were changed by user.
*/
private void trackInitialSettings() {
if (!page.isForPrefs()) {
ICConfigurationDescription[] cfgDescriptions = page.getCfgsEditable();
for (ICConfigurationDescription cfgDescription : cfgDescriptions) {
if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
String cfgId = cfgDescription.getId();
List<ILanguageSettingsProvider> initialProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
initialProvidersByCfg.put(cfgId, initialProviders);
}
}
}
}
/**
* Create table to display providers.
*/
private void createProvidersPane(Composite parent) {
Composite composite = new Composite(parent, SWT.BORDER | SWT.SINGLE);
composite.setLayout(new GridLayout());
// items checkboxes only for project properties page
tableProviders = new Table(composite, page.isForPrefs() ? SWT.NONE : SWT.CHECK);
tableProviders.setLayoutData(new GridData(GridData.FILL_BOTH));
tableProviders.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
displaySelectedOptionPage();
updateButtons();
}
});
tableProvidersViewer = new CheckboxTableViewer(tableProviders);
tableProvidersViewer.setContentProvider(new ArrayContentProvider());
tableProvidersViewer.setLabelProvider(new ProvidersTableLabelProvider());
tableProvidersViewer.addCheckStateListener(new ICheckStateListener() {
@Override
public void checkStateChanged(CheckStateChangedEvent event) {
ILanguageSettingsProvider checkedProvider = (ILanguageSettingsProvider) event.getElement();
String id = checkedProvider.getId();
ILanguageSettingsProvider newProvider = null;
if (event.getChecked()) {
if (LanguageSettingsManager.isWorkspaceProvider(checkedProvider) && !LanguageSettingsManager.isPreferShared(id)) {
newProvider = getInitialProvider(id);
if(newProvider == null) {
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(checkedProvider);
if (rawProvider instanceof ILanguageSettingsEditableProvider) {
newProvider = LanguageSettingsManager.getProviderCopy((ILanguageSettingsEditableProvider) rawProvider, false);
}
}
}
} else {
if (!LanguageSettingsManager.isWorkspaceProvider(checkedProvider)) {
newProvider = LanguageSettingsManager.getWorkspaceProvider(id);
}
}
int pos = presentedProviders.indexOf(checkedProvider);
tableProviders.setSelection(pos);
if (newProvider != null) {
replaceSelectedProvider(newProvider); // will refresh and save checked providers
createOptionsPage(newProvider);
} else {
saveCheckedProviders();
tableProvidersViewer.refresh(checkedProvider);
// option page is reused
}
displaySelectedOptionPage();
updateButtons();
}
});
}
/**
* Change "globality" of a provider.
*/
private ILanguageSettingsProvider toggleGlobalProvider(ILanguageSettingsProvider provider, boolean toGlobal) {
ILanguageSettingsProvider newProvider = null;
String id = provider.getId();
if (toGlobal) {
newProvider = LanguageSettingsManager.getWorkspaceProvider(id);
} else {
// Toggle to configuration-owned provider
newProvider = getInitialProvider(id);
if(newProvider == null || LanguageSettingsManager.isWorkspaceProvider(newProvider)) {
try {
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider);
if (rawProvider instanceof ILanguageSettingsEditableProvider) {
newProvider = ((ILanguageSettingsEditableProvider) rawProvider).cloneShallow();
}
} catch (CloneNotSupportedException e) {
CUIPlugin.log("Error cloning provider " + id, e); //$NON-NLS-1$
}
}
}
if (newProvider != null) {
replaceSelectedProvider(newProvider);
createOptionsPage(newProvider);
displaySelectedOptionPage();
updateButtons();
} else {
newProvider = provider;
}
return newProvider;
}
/**
* Create a check-box for "shared" or "global" property of a provider.
*/
private void createSharedProviderCheckBox(Composite parent) {
sharedProviderCheckBox = new Button(parent, SWT.CHECK);
sharedProviderCheckBox.setText(Messages.LanguageSettingsProviderTab_ShareProviders);
sharedProviderCheckBox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
boolean isGlobal = sharedProviderCheckBox.getSelection();
ILanguageSettingsProvider provider = getSelectedProvider();
if (isGlobal != LanguageSettingsManager.isWorkspaceProvider(provider)) {
// globality changed
provider = toggleGlobalProvider(provider, isGlobal);
}
projectStorageCheckBox.setSelection(provider instanceof LanguageSettingsSerializableProvider
&& LanguageSettingsManager.isStoringEntriesInProjectArea((LanguageSettingsSerializableProvider) provider));
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
}
/**
* Create a check-box defining where to store entries of a provider.
*/
private void createProjectStorageCheckBox(Composite parent) {
projectStorageCheckBox = new Button(parent, SWT.CHECK);
projectStorageCheckBox.setLayoutData(new GridData(SWT.END, SWT.NONE, false, false));
projectStorageCheckBox.setText(Messages.LanguageSettingsProviderTab_StoreEntriesInsideProject);
projectStorageCheckBox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
boolean inProjectArea = projectStorageCheckBox.getSelection();
ILanguageSettingsProvider newProvider = getWorkingCopy(getSelectedProvider().getId());
LanguageSettingsManager.setStoringEntriesInProjectArea((LanguageSettingsSerializableProvider) newProvider, inProjectArea);
replaceSelectedProvider(newProvider);
createOptionsPage(newProvider);
displaySelectedOptionPage();
updateButtons();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
}
/**
* Create a link to Preferences page.
*/
private void createLinkToPreferences(final Composite parent, int span) {
linkToWorkspacePreferences = new Link(parent, SWT.NONE);
String href = NLS.bind("<a href=\"workspace\">{0}</a>", Messages.LanguageSettingsProviderTab_WorkspaceSettings); //$NON-NLS-1$
linkToWorkspacePreferences.setText(NLS.bind(Messages.LanguageSettingsProviderTab_OptionsCanBeChangedInPreferencesDiscoveryTab, href));
GridData gd = new GridData();
gd.horizontalSpan = span;
linkToWorkspacePreferences.setLayoutData(gd);
linkToWorkspacePreferences.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
// Use event.text to tell which link was used
PreferencesUtil.createPreferenceDialogOn(parent.getShell(), WORKSPACE_PREFERENCE_PAGE, null, null).open();
}
});
}
/**
* Create Options pane.
*/
private void createOptionsPane(Composite parent) {
groupOptionsPage = new Group(parent, SWT.SHADOW_ETCHED_IN);
groupOptionsPage.setText(Messages.LanguageSettingsProviderTab_LanguageSettingsProvidersOptions);
groupOptionsPage.setLayout(new GridLayout(2, false));
if (!page.isForPrefs()) {
createSharedProviderCheckBox(groupOptionsPage);
createProjectStorageCheckBox(groupOptionsPage);
createLinkToPreferences(groupOptionsPage, 2);
}
// composite to span over 2 columns
Composite comp = new Composite(groupOptionsPage, SWT.NONE);
comp.setLayout(new GridLayout());
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
gd.horizontalSpan = 2;
comp.setLayoutData(gd);
compositeOptionsPage = new Composite(comp, SWT.NONE);
compositeOptionsPage.setLayout(new TabFolderLayout());
compositeOptionsPage.addControlListener(new ControlListener() {
@Override
public void controlResized(ControlEvent e) {
compositeOptionsPage.setBounds(compositeOptionsPage.getParent().getClientArea());
}
@Override
public void controlMoved(ControlEvent e) {
}
});
}
/**
* Create sash form.
*/
private void createSashForm() {
sashFormProviders = new SashForm(usercomp, SWT.VERTICAL);
GridLayout layout = new GridLayout();
sashFormProviders.setLayout(layout);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = 2;
sashFormProviders.setLayoutData(gd);
createProvidersPane(sashFormProviders);
createOptionsPane(sashFormProviders);
sashFormProviders.setWeights(DEFAULT_CONFIGURE_SASH_WEIGHTS);
}
/**
* Gray out or restore all controls except enabling check-box.
*/
private void enableTabControls(boolean enable) {
sashFormProviders.setEnabled(enable);
tableProviders.setEnabled(enable);
compositeOptionsPage.setEnabled(enable);
buttoncomp.setEnabled(enable);
if (enable) {
displaySelectedOptionPage();
} else {
if (currentOptionsPage != null) {
currentOptionsPage.setVisible(false);
}
buttonSetEnabled(BUTTON_CLEAR, false);
buttonSetEnabled(BUTTON_RESET, false);
buttonSetEnabled(BUTTON_MOVE_UP, false);
buttonSetEnabled(BUTTON_MOVE_DOWN, false);
}
}
@Override
public void createControls(Composite parent) {
super.createControls(parent);
usercomp.setLayout(new GridLayout());
GridData gd = (GridData) usercomp.getLayoutData();
// Discourage settings entry table from trying to show all its items at once, see bug 264330
gd.heightHint = 1;
if (page instanceof LanguageSettingsProvidersPage) {
masterPropertyPage = (LanguageSettingsProvidersPage) page;
}
trackInitialSettings();
createSashForm();
fStatusLine = new StatusMessageLine(usercomp, SWT.LEFT, 2);
if (!page.isForPrefs() && !page.isMultiCfg()) {
enableTabControls(masterPropertyPage.isLanguageSettingsProvidersEnabled());
}
String[] buttonLabels;
if (page.isForPrefs()) {
buttonLabels = new String[2];
buttonLabels[BUTTON_CLEAR] = CLEAR_STR;
buttonLabels[BUTTON_RESET] = RESET_STR;
} else {
buttonLabels = new String[5];
buttonLabels[BUTTON_CLEAR] = CLEAR_STR;
buttonLabels[BUTTON_RESET] = RESET_STR;
buttonLabels[BUTTON_MOVE_UP] = MOVEUP_STR;
buttonLabels[BUTTON_MOVE_DOWN] = MOVEDOWN_STR;
}
initButtons(buttonLabels);
updateData(getResDesc());
}
/**
* Clear entries of the selected provider.
*/
private void performClear(ILanguageSettingsProvider selectedProvider) {
if (isWorkingCopy(selectedProvider)) {
if (selectedProvider instanceof LanguageSettingsSerializableProvider) {
LanguageSettingsSerializableProvider editableProvider = (LanguageSettingsSerializableProvider) selectedProvider;
editableProvider.clear();
tableProvidersViewer.update(selectedProvider, null);
}
} else {
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(selectedProvider);
if (rawProvider instanceof ILanguageSettingsEditableProvider) {
ILanguageSettingsEditableProvider newProvider = LanguageSettingsManager.getProviderCopy((ILanguageSettingsEditableProvider) rawProvider, false);
if (newProvider != null) {
replaceSelectedProvider(newProvider);
createOptionsPage(newProvider);
displaySelectedOptionPage();
}
}
}
updateButtons();
}
/**
* Reset settings of the selected provider.
*/
private void performReset(ILanguageSettingsProvider selectedProvider) {
String id = selectedProvider.getId();
ILanguageSettingsProvider newProvider = null;
if (page.isForPrefs()) {
newProvider = LanguageSettingsManager.getExtensionProviderCopy(id, true);
if (newProvider == null) {
Status status = new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, IStatus.ERROR, Messages.GeneralMessages_InternalError_ReportLogToCdtTeam,
new Exception("Internal Error getting copy of provider id="+id)); //$NON-NLS-1$
fStatusLine.setErrorStatus(status);
CUIPlugin.log(status);
}
} else {
ICConfigurationDescription cfgDescription = getConfigurationDescription();
String[] defaultIds = ((ILanguageSettingsProvidersKeeper) cfgDescription).getDefaultLanguageSettingsProvidersIds();
boolean isDefault = Arrays.asList(defaultIds).contains(id);
if (isDefault && !LanguageSettingsManager.isPreferShared(id)) {
newProvider = LanguageSettingsManager.getExtensionProviderCopy(id, true);
if (newProvider == null) {
Status status = new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, IStatus.ERROR, Messages.GeneralMessages_InternalError_ReportLogToCdtTeam,
new Exception("Internal Error getting copy of provider id="+id)); //$NON-NLS-1$
fStatusLine.setErrorStatus(status);
CUIPlugin.log(status);
}
} else {
newProvider = LanguageSettingsManager.getWorkspaceProvider(id);
}
tableProvidersViewer.setChecked(selectedProvider, isDefault);
}
if (newProvider != null) {
replaceSelectedProvider(newProvider);
createOptionsPage(newProvider);
displaySelectedOptionPage();
updateButtons();
}
}
/**
* Move selected provider in the table.
*/
private void moveProvider(int oldPos, int newPos) {
Collections.swap(presentedProviders, oldPos, newPos);
tableProvidersViewer.refresh();
tableProviders.showSelection();
saveCheckedProviders();
updateButtons();
}
/**
* Move selected provider up.
*/
private void performMoveUp(ILanguageSettingsProvider selectedProvider) {
int pos = presentedProviders.indexOf(selectedProvider);
if (pos > 0) {
moveProvider(pos, pos-1);
}
}
/**
* Move selected provider down.
*/
private void performMoveDown(ILanguageSettingsProvider selectedProvider) {
int pos = presentedProviders.indexOf(selectedProvider);
int last = presentedProviders.size() - 1;
if (pos >= 0 && pos < last) {
moveProvider(pos, pos+1);
}
}
/**
* Handle pressed buttons.
*/
@Override
public void buttonPressed(int buttonIndex) {
ILanguageSettingsProvider selectedProvider = getSelectedProvider();
switch (buttonIndex) {
case BUTTON_CLEAR:
performClear(selectedProvider);
break;
case BUTTON_RESET:
performReset(selectedProvider);
break;
case BUTTON_MOVE_UP:
performMoveUp(selectedProvider);
break;
case BUTTON_MOVE_DOWN:
performMoveDown(selectedProvider);
break;
default:
}
}
/**
* Updates state for all buttons.
*/
@Override
protected void updateButtons() {
ILanguageSettingsProvider provider = getSelectedProvider();
boolean isProviderSelected = provider != null;
boolean canForWorkspace = isProviderSelected && page.isForPrefs();
boolean canForProject = isProviderSelected && page.isForProject();
int pos = tableProviders.getSelectionIndex();
int count = tableProviders.getItemCount();
int last = count - 1;
boolean isRangeOk = (pos >= 0 && pos <= last);
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider);
boolean isAllowedClearing = rawProvider instanceof ILanguageSettingsEditableProvider && rawProvider instanceof LanguageSettingsSerializableProvider
&& LanguageSettingsProviderAssociationManager.isAllowedToClear(rawProvider);
boolean canClear = isAllowedClearing && (canForWorkspace || (canForProject && !LanguageSettingsManager.isWorkspaceProvider(provider)));
if (rawProvider instanceof LanguageSettingsSerializableProvider) {
canClear = canClear && !((LanguageSettingsSerializableProvider)rawProvider).isEmpty();
}
boolean canResetForProject = canForProject && isReconfiguredForProject(provider);
boolean canResetForWorkspace = canForWorkspace &&
(rawProvider instanceof ILanguageSettingsEditableProvider
&& !LanguageSettingsManager.isEqualExtensionProvider(rawProvider, false))
&& ( LanguageSettingsManager.getExtensionProviderIds().contains(rawProvider.getId()) );
boolean canReset = canResetForProject || canResetForWorkspace;
boolean canMoveUp = canForProject && isRangeOk && pos != 0;
boolean canMoveDown = canForProject && isRangeOk && pos != last;
buttonSetEnabled(BUTTON_CLEAR, canClear);
buttonSetEnabled(BUTTON_RESET, canReset);
buttonSetEnabled(BUTTON_MOVE_UP, canMoveUp);
buttonSetEnabled(BUTTON_MOVE_DOWN, canMoveDown);
}
/**
* Sort providers displayed in UI. Sorting is by name except test providers are shown
* on bottom.
*/
private void sortByName(List<ILanguageSettingsProvider> providers) {
// ensure sorting by name all unchecked providers
Collections.sort(providers, new Comparator<ILanguageSettingsProvider>() {
@Override
public int compare(ILanguageSettingsProvider prov1, ILanguageSettingsProvider prov2) {
Boolean isTest1 = prov1.getId().matches(TEST_PLUGIN_ID_PATTERN);
Boolean isTest2 = prov2.getId().matches(TEST_PLUGIN_ID_PATTERN);
int result = isTest1.compareTo(isTest2);
if (result == 0) {
String name1 = prov1.getName();
String name2 = prov2.getName();
if (name1 != null && name2 != null) {
result = name1.compareTo(name2);
}
}
return result;
}
});
}
/**
* Initialize providers list.
*/
private void initializeProviders() {
// The providers list is formed to consist of configuration providers (checked elements on top of the table)
// and after that other providers which could be possible added (unchecked) sorted by name.
List<String> idsList = new ArrayList<String>();
List<ILanguageSettingsProvider> providers;
ICConfigurationDescription cfgDescription = getConfigurationDescription();
if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
providers = new ArrayList<ILanguageSettingsProvider>(((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders());
for (ILanguageSettingsProvider provider : providers) {
idsList.add(provider.getId());
}
} else {
providers = new ArrayList<ILanguageSettingsProvider>();
}
List<ILanguageSettingsProvider> allAvailableProvidersSet = LanguageSettingsManager.getWorkspaceProviders();
sortByName(allAvailableProvidersSet);
for (ILanguageSettingsProvider provider : allAvailableProvidersSet) {
String id = provider.getId();
if (!idsList.contains(id) && ScannerDiscoveryLegacySupport.isProviderCompatible(id, cfgDescription)) {
providers.add(provider);
idsList.add(id);
}
}
// renders better when using temporary
presentedProviders = providers;
ILanguageSettingsProvider selectedProvider = getSelectedProvider();
String selectedId = selectedProvider!=null ? selectedProvider.getId() : null;
tableProvidersViewer.setInput(presentedProviders);
if (selectedId!=null) {
for (int i=0; i<presentedProviders.size(); i++) {
if (selectedId.equals(presentedProviders.get(i).getId())) {
tableProviders.setSelection(i);
break;
}
}
}
}
/**
* Get option page from {@link LanguageSettingsProviderAssociationManager}.
*/
private ICOptionPage getOptionsPage(ILanguageSettingsProvider provider) {
ICOptionPage optionsPage = null;
if (provider != null) {
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider);
if (rawProvider != null) {
optionsPage = LanguageSettingsProviderAssociationManager.createOptionsPage(rawProvider);
}
if (optionsPage instanceof AbstractLanguageSettingProviderOptionPage) {
((AbstractLanguageSettingProviderOptionPage)optionsPage).init(this, provider.getId());
}
}
return optionsPage;
}
/**
* Create Options page for a provider.
*/
private void createOptionsPage(ILanguageSettingsProvider provider) {
ICOptionPage optionsPage = getOptionsPage(provider);
if (optionsPage != null) {
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider);
boolean isEditableForProject = page.isForProject() && provider instanceof ILanguageSettingsEditableProvider;
boolean isEditableForPrefs = page.isForPrefs() && rawProvider instanceof ILanguageSettingsEditableProvider;
boolean isEditable = isEditableForProject || isEditableForPrefs;
compositeOptionsPage.setEnabled(isEditable);
String id = (provider != null) ? provider.getId() : null;
optionsPageMap.put(id, optionsPage);
optionsPage.setContainer(page);
optionsPage.createControl(compositeOptionsPage);
optionsPage.setVisible(false);
compositeOptionsPage.layout(true);
}
}
/**
* Display selected option page.
*/
private void displaySelectedOptionPage() {
if (currentOptionsPage != null) {
currentOptionsPage.setVisible(false);
}
ILanguageSettingsProvider provider = getSelectedProvider();
String id = (provider != null) ? provider.getId() : null;
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider);
currentOptionsPage = optionsPageMap.get(id);
if (!page.isForPrefs() ) {
boolean isChecked = tableProvidersViewer.getChecked(provider);
boolean isShared = isPresentedAsShared(provider);
boolean isRawProviderEditable = rawProvider instanceof ILanguageSettingsEditableProvider;
sharedProviderCheckBox.setVisible(provider != null);
sharedProviderCheckBox.setEnabled(isChecked && isRawProviderEditable);
sharedProviderCheckBox.setSelection(isShared);
projectStorageCheckBox.setVisible(rawProvider instanceof LanguageSettingsSerializableProvider);
projectStorageCheckBox.setEnabled(isChecked && !isShared);
projectStorageCheckBox.setSelection(provider instanceof LanguageSettingsSerializableProvider
&& LanguageSettingsManager.isStoringEntriesInProjectArea((LanguageSettingsSerializableProvider) provider));
linkToWorkspacePreferences.setVisible(isShared && currentOptionsPage != null);
linkToWorkspacePreferences.setEnabled(isChecked);
}
if (currentOptionsPage != null) {
currentOptionsPage.setVisible(true);
boolean isEditableForProject = page.isForProject() && provider instanceof ILanguageSettingsEditableProvider;
boolean isEditableForPrefs = page.isForPrefs() && rawProvider instanceof ILanguageSettingsEditableProvider;
boolean isEditable = isEditableForProject || isEditableForPrefs;
currentOptionsPage.getControl().setEnabled(isEditable);
compositeOptionsPage.setEnabled(isEditable);
compositeOptionsPage.layout(true);
}
}
/**
* Populate provider tables and their option pages
*/
private void updateProvidersTable() {
ILanguageSettingsProvider selectedProvider = getSelectedProvider();
String selectedId = selectedProvider != null ? selectedProvider.getId() : null;
boolean wasChecked = selectedProvider != null && tableProvidersViewer.getChecked(selectedProvider);
// update viewer if the list of providers changed
int pos = tableProviders.getSelectionIndex();
tableProvidersViewer.setInput(presentedProviders);
tableProviders.setSelection(pos);
ICConfigurationDescription cfgDescription = getConfigurationDescription();
if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
List<ILanguageSettingsProvider> cfgProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
tableProvidersViewer.setCheckedElements(cfgProviders.toArray(new ILanguageSettingsProvider[0]));
}
if (selectedId != null) {
for (int i = 0; i < presentedProviders.size(); i++) {
ILanguageSettingsProvider provider = presentedProviders.get(i);
if (selectedId.equals(provider.getId())) {
boolean isChecked = tableProvidersViewer.getChecked(provider);
if (isChecked || isChecked == wasChecked) {
tableProviders.setSelection(i);
} else {
tableProviders.setSelection(0);
}
break;
}
}
}
tableProvidersViewer.refresh();
optionsPageMap.clear();
for (ILanguageSettingsProvider provider : presentedProviders) {
createOptionsPage(provider);
}
displaySelectedOptionPage();
}
/**
* Update the tab. Called when configuration changes.
*/
@Override
public void updateData(ICResourceDescription rcDes) {
if (!canBeVisible())
return;
ICConfigurationDescription cfgDescription = getConfigurationDescription();
if (cfgDescription != null) {
String cfgId = cfgDescription.getId();
if (!initialProvidersByCfg.containsKey(cfgId)) {
if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
List<ILanguageSettingsProvider> initialProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
initialProvidersByCfg.put(cfgId, initialProviders);
}
}
}
if (rcDes!=null) {
if (page.isMultiCfg()) {
setAllVisible(false, null);
return;
} else {
setAllVisible(true, null);
}
if (masterPropertyPage != null) {
boolean enabled = masterPropertyPage.isLanguageSettingsProvidersEnabled();
enableTabControls(enabled);
}
}
// for Preference page initialize providers list just once as no configuration here to change
// and re-initializing could overwrite modified providers in case of switching tabs or pages
if (!page.isForPrefs() || presentedProviders == null) {
initializeProviders();
}
updateProvidersTable();
updateButtons();
}
@Override
protected void performDefaults() {
if (page.isForPrefs() || page.isForProject()) {
if (MessageDialog.openQuestion(usercomp.getShell(),
Messages.LanguageSettingsProviderTab_TitleResetProviders,
Messages.LanguageSettingsProviderTab_AreYouSureToResetProviders)) {
if (page.isForProject()) {
// set project LSP enablement to that of workspace
masterPropertyPage.setLanguageSettingsProvidersEnabled(ScannerDiscoveryLegacySupport.isLanguageSettingsProvidersFunctionalityEnabled(null));
ICConfigurationDescription cfgDescription = getConfigurationDescription();
if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
List<ILanguageSettingsProvider> cfgProviders = new ArrayList<ILanguageSettingsProvider>(((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders());
String[] defaultIds = ((ILanguageSettingsProvidersKeeper) cfgDescription).getDefaultLanguageSettingsProvidersIds();
List<ILanguageSettingsProvider> newProviders = LanguageSettingsManager.createLanguageSettingsProviders(defaultIds);
if (!cfgProviders.equals(newProviders)) {
((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(newProviders);
}
}
} else if (page.isForPrefs()) {
presentedProviders = new ArrayList<ILanguageSettingsProvider>();
for (String id : LanguageSettingsManager.getExtensionProviderIds()) {
ILanguageSettingsProvider provider = LanguageSettingsManager.getWorkspaceProvider(id);
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider);
if (!LanguageSettingsManager.isEqualExtensionProvider(rawProvider, true)) {
ILanguageSettingsProvider extProvider = LanguageSettingsManager.getExtensionProviderCopy(id, true);
if (extProvider != null) {
provider = extProvider;
}
}
presentedProviders.add(provider);
}
sortByName(presentedProviders);
}
}
ICResourceDescription rcDescription = getResDesc();
updateData(rcDescription);
// update other tabs
if (masterPropertyPage != null) {
masterPropertyPage.informAll(UPDATE, rcDescription);
}
}
}
@Override
protected void performApply(ICResourceDescription srcRcDescription, ICResourceDescription destRcDescription) {
if (!page.isForPrefs()) {
ICConfigurationDescription sd = srcRcDescription.getConfiguration();
ICConfigurationDescription dd = destRcDescription.getConfiguration();
if (sd instanceof ILanguageSettingsProvidersKeeper && dd instanceof ILanguageSettingsProvidersKeeper) {
List<ILanguageSettingsProvider> newProviders = ((ILanguageSettingsProvidersKeeper) sd).getLanguageSettingProviders();
((ILanguageSettingsProvidersKeeper) dd).setLanguageSettingProviders(newProviders);
}
}
performOK();
trackInitialSettings();
updateData(getResDesc());
}
@Override
protected void performOK() {
// give option pages a chance for provider-specific pre-apply actions
Collection<ICOptionPage> optionPages = optionsPageMap.values();
for (ICOptionPage op : optionPages) {
try {
op.performApply(null);
} catch (CoreException e) {
CUIPlugin.log("Error applying options page", e); //$NON-NLS-1$
}
}
if (page.isForPrefs()) {
try {
LanguageSettingsManager.setWorkspaceProviders(presentedProviders);
} catch (CoreException e) {
CUIPlugin.log("Error setting user defined providers", e); //$NON-NLS-1$
}
initializeProviders();
}
if (masterPropertyPage != null && masterPropertyPage.isLanguageSettingsProvidersEnabled()) {
masterPropertyPage.applyLanguageSettingsProvidersEnabled();
}
}
@Override
public boolean canBeVisible() {
if (!ScannerDiscoveryLegacySupport.isLanguageSettingsProvidersFunctionalityEnabled(null)) {
return false;
}
return page.isForPrefs() || page.isForProject();
}
}