blob: eb362cfb4b1485b263366494e6b8972b39b3374c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2020 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
* Christian Georgi<christian.georgi@sap.com> - Bug 462770: Use OS symbol for 'Ctrl'
* Gábor Kövesdán - Contribution for Bug 350000 - [content assist] Include non-prefix matches in auto-complete suggestions
*******************************************************************************/
package org.eclipse.jdt.internal.ui.preferences;
import java.util.Map;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
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.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Text;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.bindings.keys.SWTKeySupport;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal;
import org.eclipse.jdt.internal.ui.text.java.ProposalSorterHandle;
import org.eclipse.jdt.internal.ui.text.java.ProposalSorterRegistry;
import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
/**
* Configures the content assist preferences.
*
* @since 3.0
*/
class CodeAssistConfigurationBlock extends OptionsConfigurationBlock {
private static final Key PREF_CODEASSIST_AUTOACTIVATION= getJDTUIKey(PreferenceConstants.CODEASSIST_AUTOACTIVATION);
private static final Key PREF_CODEASSIST_AUTOACTIVATION_DELAY= getJDTUIKey(PreferenceConstants.CODEASSIST_AUTOACTIVATION_DELAY);
private static final Key PREF_CODEASSIST_AUTOINSERT= getJDTUIKey(PreferenceConstants.CODEASSIST_AUTOINSERT);
private static final Key PREF_CODEASSIST_DISABLE_COMPLETION_PROPOSAL_TRIGGER_CHARS= getJDTUIKey(PreferenceConstants.CODEASSIST_DISABLE_COMPLETION_PROPOSAL_TRIGGER_CHARS);
private static final Key PREF_CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA= getJDTUIKey(PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA);
private static final Key PREF_CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVADOC= getJDTUIKey(PreferenceConstants.CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVADOC);
private static final Key PREF_CODEASSIST_SHOW_VISIBLE_PROPOSALS= getJDTUIKey(PreferenceConstants.CODEASSIST_SHOW_VISIBLE_PROPOSALS);
private static final Key PREF_CODEASSIST_SORTER= getJDTUIKey(PreferenceConstants.CODEASSIST_SORTER);
private static final Key PREF_CODEASSIST_CASE_SENSITIVITY= getJDTUIKey(PreferenceConstants.CODEASSIST_CASE_SENSITIVITY);
private static final Key PREF_CODEASSIST_ADDIMPORT= getJDTUIKey(PreferenceConstants.CODEASSIST_ADDIMPORT);
private static final Key PREF_CODEASSIST_SUGGEST_STATIC_IMPORTS= getJDTCoreKey(JavaCore.CODEASSIST_SUGGEST_STATIC_IMPORTS);
private static final Key PREF_CODEASSIST_INSERT_COMPLETION= getJDTUIKey(PreferenceConstants.CODEASSIST_INSERT_COMPLETION);
private static final Key PREF_CODEASSIST_FILL_ARGUMENT_NAMES= getJDTUIKey(PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES);
private static final Key PREF_CODEASSIST_GUESS_METHOD_ARGUMENTS= getJDTUIKey(PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS);
private static final Key PREF_CODEASSIST_PREFIX_COMPLETION= getJDTUIKey(PreferenceConstants.CODEASSIST_PREFIX_COMPLETION);
private static final Key PREF_CODEASSIST_DEPRECATION_CHECK= getJDTCoreKey(JavaCore.CODEASSIST_DEPRECATION_CHECK);
private static final Key PREF_CODEASSIST_CAMEL_CASE_MATCH= getJDTCoreKey(JavaCore.CODEASSIST_CAMEL_CASE_MATCH);
private static final Key PREF_CODEASSIST_SUBWORD_MATCH= getJDTCoreKey(JavaCore.CODEASSIST_SUBWORD_MATCH);
private static Key[] getAllKeys() {
return new Key[] {
PREF_CODEASSIST_AUTOACTIVATION,
PREF_CODEASSIST_AUTOACTIVATION_DELAY,
PREF_CODEASSIST_AUTOINSERT,
PREF_CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA,
PREF_CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVADOC,
PREF_CODEASSIST_SHOW_VISIBLE_PROPOSALS,
PREF_CODEASSIST_SORTER,
PREF_CODEASSIST_CASE_SENSITIVITY,
PREF_CODEASSIST_ADDIMPORT,
PREF_CODEASSIST_SUGGEST_STATIC_IMPORTS,
PREF_CODEASSIST_INSERT_COMPLETION,
PREF_CODEASSIST_FILL_ARGUMENT_NAMES,
PREF_CODEASSIST_GUESS_METHOD_ARGUMENTS,
PREF_CODEASSIST_PREFIX_COMPLETION,
PREF_CODEASSIST_DEPRECATION_CHECK,
PREF_CODEASSIST_CAMEL_CASE_MATCH,
PREF_CODEASSIST_SUBWORD_MATCH,
PREF_CODEASSIST_DISABLE_COMPLETION_PROPOSAL_TRIGGER_CHARS
};
}
private static final String[] trueFalse= new String[] { IPreferenceStore.TRUE, IPreferenceStore.FALSE };
private static final String[] enabledDisabled= new String[] { JavaCore.ENABLED, JavaCore.DISABLED };
private Button fCompletionInsertsRadioButton;
private Button fCompletionOverwritesRadioButton;
private Button fInsertParameterNamesRadioButton;
private Button fInsertBestGuessRadioButton;
public CodeAssistConfigurationBlock(IStatusChangeListener statusListener, IWorkbenchPreferenceContainer workbenchcontainer) {
super(statusListener, null, getAllKeys(), workbenchcontainer);
}
@Override
protected Control createContents(Composite parent) {
ScrolledPageContent scrolled= new ScrolledPageContent(parent, SWT.H_SCROLL | SWT.V_SCROLL);
scrolled.setExpandHorizontal(true);
scrolled.setExpandVertical(true);
Composite control= new Composite(scrolled, SWT.NONE);
GridLayout layout= new GridLayout();
layout.marginHeight= 0;
layout.marginWidth= 0;
control.setLayout(layout);
Composite composite;
composite= createSubsection(control, PreferencesMessages.CodeAssistConfigurationBlock_insertionSection_title);
addInsertionSection(composite);
composite= createSubsection(control, PreferencesMessages.CodeAssistConfigurationBlock_sortingSection_title);
addSortingSection(composite);
composite= createSubsection(control, PreferencesMessages.CodeAssistConfigurationBlock_autoactivationSection_title);
addAutoActivationSection(composite);
initialize();
scrolled.setContent(control);
final Point size= control.computeSize(SWT.DEFAULT, SWT.DEFAULT);
scrolled.setMinSize(size.x, size.y);
return scrolled;
}
protected Composite createSubsection(Composite parent, String label) {
Group group= new Group(parent, SWT.SHADOW_NONE);
group.setText(label);
GridData data= new GridData(SWT.FILL, SWT.CENTER, true, false);
group.setLayoutData(data);
GridLayout layout= new GridLayout();
layout.numColumns= 3;
group.setLayout(layout);
return group;
}
private void addInsertionSection(Composite composite) {
addCompletionRadioButtons(composite);
String label;
label= PreferencesMessages.JavaEditorPreferencePage_insertSingleProposalsAutomatically;
addCheckBox(composite, label, PREF_CODEASSIST_AUTOINSERT, trueFalse, 0);
label= PreferencesMessages.JavaEditorPreferencePage_completePrefixes;
addCheckBox(composite, label, PREF_CODEASSIST_PREFIX_COMPLETION, trueFalse, 0);
addCheckBox(composite, PreferencesMessages.JavaEditorPreferencePage_disableCompletionProposalTriggerChars, PREF_CODEASSIST_DISABLE_COMPLETION_PROPOSAL_TRIGGER_CHARS, trueFalse, 0);
label= PreferencesMessages.JavaEditorPreferencePage_automaticallyAddImportInsteadOfQualifiedName;
Button master= addCheckBox(composite, label, PREF_CODEASSIST_ADDIMPORT, trueFalse, 0);
label= PreferencesMessages.JavaEditorPreferencePage_suggestStaticImports;
Button slave= addCheckBoxWithLink(composite, label, PREF_CODEASSIST_SUGGEST_STATIC_IMPORTS, enabledDisabled, 20, SWT.DEFAULT, new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
openStaticImportFavoritesPage();
}
});
createSelectionDependency(master, slave.getParent());
label= PreferencesMessages.JavaEditorPreferencePage_fillArgumentsOnMethodCompletion;
master= addCheckBox(composite, label, PREF_CODEASSIST_FILL_ARGUMENT_NAMES, trueFalse, 0);
Composite fillComposite= new Composite(composite, SWT.NONE);
GridData gd= new GridData();
gd.horizontalSpan= 2;
gd.horizontalIndent= LayoutUtil.getIndent();
fillComposite.setLayoutData(gd);
GridLayout layout= new GridLayout();
layout.marginWidth= 0;
layout.marginHeight= 0;
layout.numColumns= 2;
fillComposite.setLayout(layout);
SelectionListener completionSelectionListener= new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
boolean state= fInsertBestGuessRadioButton.getSelection();
setValue(PREF_CODEASSIST_GUESS_METHOD_ARGUMENTS, state);
}
};
fInsertParameterNamesRadioButton= new Button(fillComposite, SWT.RADIO | SWT.LEFT);
fInsertParameterNamesRadioButton.setText(PreferencesMessages.JavaEditorPreferencePage_fillParameterNamesOnMethodCompletion);
fInsertParameterNamesRadioButton.setLayoutData(new GridData());
fInsertParameterNamesRadioButton.addSelectionListener(completionSelectionListener);
fInsertBestGuessRadioButton= new Button(fillComposite, SWT.RADIO | SWT.LEFT);
fInsertBestGuessRadioButton.setText(PreferencesMessages.JavaEditorPreferencePage_fillBestGuessedArgumentsOnMethodCompletion);
fInsertBestGuessRadioButton.setLayoutData(new GridData());
fInsertBestGuessRadioButton.addSelectionListener(completionSelectionListener);
createSelectionDependency(master, fInsertParameterNamesRadioButton);
createSelectionDependency(master, fInsertBestGuessRadioButton);
}
protected final void openStaticImportFavoritesPage() {
if (getPreferenceContainer() != null) {
getPreferenceContainer().openPage(CodeAssistFavoritesPreferencePage.PAGE_ID, null);
} else {
PreferencesUtil.createPreferenceDialogOn(getShell(), CodeAssistFavoritesPreferencePage.PAGE_ID, null, null).open();
}
}
/**
* Creates a selection dependency between a master and a slave control.
*
* @param master
* The master button that controls the state of the slave
* @param slave
* The slave control that is enabled only if the master is
* selected
*/
protected static void createSelectionDependency(final Button master, final Control slave) {
master.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
deepSetEnabled(slave, master.getSelection());
}
private void deepSetEnabled(final Control control, boolean enabled) {
control.setEnabled(enabled);
if (control instanceof Composite) {
for (Control child : ((Composite)control).getChildren()) {
deepSetEnabled(child, enabled);
}
}
}
});
slave.setEnabled(master.getSelection());
}
private void addSortingSection(Composite composite) {
String label;
label= PreferencesMessages.CodeAssistConfigurationBlock_typeFilters_link;
createPreferencePageLink(composite, label, null);
new Label(composite, SWT.NONE);
label= PreferencesMessages.JavaEditorPreferencePage_presentProposalsInAlphabeticalOrder;
ProposalSorterHandle[] sorters= ProposalSorterRegistry.getDefault().getSorters();
String[] labels= new String[sorters.length];
String[] values= new String[sorters.length];
for (int i= 0; i < sorters.length; i++) {
ProposalSorterHandle handle= sorters[i];
labels[i]= handle.getName();
values[i]= handle.getId();
}
addComboBox(composite, label, PREF_CODEASSIST_SORTER, values, labels, 0);
label= PreferencesMessages.CodeAssistConfigurationBlock_matchCamelCase_label;
addCheckBox(composite, label, PREF_CODEASSIST_CAMEL_CASE_MATCH, enabledDisabled, 0);
label= PreferencesMessages.CodeAssistConfigurationBlock_matchSubword_label;
addCheckBox(composite, label, PREF_CODEASSIST_SUBWORD_MATCH, enabledDisabled, 0);
label= PreferencesMessages.JavaEditorPreferencePage_showOnlyProposalsVisibleInTheInvocationContext;
addCheckBox(composite, label, PREF_CODEASSIST_SHOW_VISIBLE_PROPOSALS, trueFalse, 0);
label= PreferencesMessages.CodeAssistConfigurationBlock_hideDeprecated_label;
addCheckBox(composite, label, PREF_CODEASSIST_DEPRECATION_CHECK, enabledDisabled, 0);
}
private void createPreferencePageLink(Composite composite, String label, final Map<String, String> targetInfo) {
final Link link= new Link(composite, SWT.NONE);
link.setText(label);
link.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
PreferencesUtil.createPreferenceDialogOn(link.getShell(), e.text, null, targetInfo);
}
});
}
private void addAutoActivationSection(Composite composite) {
String label;
label= PreferencesMessages.JavaEditorPreferencePage_enableAutoActivation;
final Button autoactivation= addCheckBox(composite, label, PREF_CODEASSIST_AUTOACTIVATION, trueFalse, 0);
autoactivation.addSelectionListener(new SelectionAdapter(){
@Override
public void widgetSelected(SelectionEvent e) {
updateAutoactivationControls();
}
});
label= PreferencesMessages.JavaEditorPreferencePage_autoActivationDelay;
addLabelledTextField(composite, label, PREF_CODEASSIST_AUTOACTIVATION_DELAY, 4, 20);
label= PreferencesMessages.JavaEditorPreferencePage_autoActivationTriggersForJava;
addLabelledTextField(composite, label, PREF_CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA, 100, 4, 20);
label= PreferencesMessages.JavaEditorPreferencePage_autoActivationTriggersForJavaDoc;
addLabelledTextField(composite, label, PREF_CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVADOC, 100, 4, 20);
}
protected Text addLabelledTextField(Composite parent, String label, Key key, int textlimit, int indent) {
return addLabelledTextField(parent, label, key, textlimit, textlimit, indent);
}
protected Text addLabelledTextField(Composite parent, String label, Key key, int modelTextLimit, int fieldTextLimit, int indent) {
PixelConverter pixelConverter= new PixelConverter(parent);
Label labelControl= new Label(parent, SWT.NONE);
labelControl.setText(label);
GridData data= new GridData();
data.horizontalIndent= indent;
labelControl.setLayoutData(data);
Text textBox= new Text(parent, SWT.BORDER | SWT.SINGLE);
textBox.setData(key);
textBox.setLayoutData(new GridData());
fLabels.put(textBox, labelControl);
String currValue= getValue(key);
if (currValue != null) {
textBox.setText(currValue);
}
textBox.addModifyListener(getTextModifyListener());
data= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
if (modelTextLimit != 0)
textBox.setTextLimit(modelTextLimit);
if (fieldTextLimit != 0)
data.widthHint= pixelConverter.convertWidthInCharsToPixels(fieldTextLimit + 1);
data.horizontalSpan= 2;
textBox.setLayoutData(data);
fTextBoxes.add(textBox);
return textBox;
}
private void addCompletionRadioButtons(Composite contentAssistComposite) {
Composite completionComposite= new Composite(contentAssistComposite, SWT.NONE);
GridData ccgd= new GridData();
ccgd.horizontalSpan= 2;
completionComposite.setLayoutData(ccgd);
GridLayout ccgl= new GridLayout();
ccgl.marginWidth= 0;
ccgl.numColumns= 2;
completionComposite.setLayout(ccgl);
SelectionListener completionSelectionListener= new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
boolean insert= fCompletionInsertsRadioButton.getSelection();
setValue(PREF_CODEASSIST_INSERT_COMPLETION, insert);
}
};
fCompletionInsertsRadioButton= new Button(completionComposite, SWT.RADIO | SWT.LEFT);
fCompletionInsertsRadioButton.setText(PreferencesMessages.JavaEditorPreferencePage_completionInserts);
fCompletionInsertsRadioButton.setLayoutData(new GridData());
fCompletionInsertsRadioButton.addSelectionListener(completionSelectionListener);
fCompletionOverwritesRadioButton= new Button(completionComposite, SWT.RADIO | SWT.LEFT);
fCompletionOverwritesRadioButton.setText(PreferencesMessages.JavaEditorPreferencePage_completionOverwrites);
fCompletionOverwritesRadioButton.setLayoutData(new GridData());
fCompletionOverwritesRadioButton.addSelectionListener(completionSelectionListener);
Label label= new Label(completionComposite, SWT.NONE);
String modifier= SWTKeySupport.getKeyFormatterForPlatform().format(AbstractJavaCompletionProposal.MODIFIER_TOGGLE_COMPLETION_MODE);
label.setText(NLS.bind(PreferencesMessages.JavaEditorPreferencePage_completionToggleHint, modifier));
GridData gd= new GridData();
gd.horizontalIndent= LayoutUtil.getIndent();
gd.horizontalSpan= 2;
label.setLayoutData(gd);
}
public void initialize() {
initializeFields();
}
private void initializeFields() {
boolean value= getBooleanValue(PREF_CODEASSIST_INSERT_COMPLETION);
fCompletionInsertsRadioButton.setSelection(value);
fCompletionOverwritesRadioButton.setSelection(!value);
value= getBooleanValue(PREF_CODEASSIST_GUESS_METHOD_ARGUMENTS);
fInsertBestGuessRadioButton.setSelection(value);
fInsertParameterNamesRadioButton.setSelection(!value);
value= getBooleanValue(PREF_CODEASSIST_FILL_ARGUMENT_NAMES);
fInsertParameterNamesRadioButton.setEnabled(value);
fInsertBestGuessRadioButton.setEnabled(value);
updateAutoactivationControls();
}
private void updateAutoactivationControls() {
boolean autoactivation= getBooleanValue(PREF_CODEASSIST_AUTOACTIVATION);
setControlEnabled(PREF_CODEASSIST_AUTOACTIVATION_DELAY, autoactivation);
setControlEnabled(PREF_CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVA, autoactivation);
setControlEnabled(PREF_CODEASSIST_AUTOACTIVATION_TRIGGERS_JAVADOC, autoactivation);
}
@Override
public void performDefaults() {
super.performDefaults();
initializeFields();
}
@Override
protected String[] getFullBuildDialogStrings(boolean workspaceSettings) {
return null;
}
/**
* Validates that the specified number is positive.
*
* @param number
* The number to validate
* @return The status of the validation
*/
protected static IStatus validatePositiveNumber(final String number) {
final StatusInfo status= new StatusInfo();
if (number.length() == 0) {
status.setError(PreferencesMessages.SpellingPreferencePage_empty_threshold);
} else {
try {
final int value= Integer.parseInt(number);
if (value < 0) {
status.setError(Messages.format(PreferencesMessages.SpellingPreferencePage_invalid_threshold, number));
}
} catch (NumberFormatException exception) {
status.setError(Messages.format(PreferencesMessages.SpellingPreferencePage_invalid_threshold, number));
}
}
return status;
}
@Override
protected void validateSettings(Key key, String oldValue, String newValue) {
if (key == null || PREF_CODEASSIST_AUTOACTIVATION_DELAY.equals(key))
fContext.statusChanged(validatePositiveNumber(getValue(PREF_CODEASSIST_AUTOACTIVATION_DELAY)));
}
protected void setControlEnabled(Key key, boolean enabled) {
Control control= getControl(key);
control.setEnabled(enabled);
Label label= fLabels.get(control);
if (label != null)
label.setEnabled(enabled);
}
private Control getControl(Key key) {
for (int i= fComboBoxes.size() - 1; i >= 0; i--) {
Control curr= fComboBoxes.get(i);
ControlData data= (ControlData) curr.getData();
if (key.equals(data.getKey())) {
return curr;
}
}
for (int i= fCheckBoxes.size() - 1; i >= 0; i--) {
Control curr= fCheckBoxes.get(i);
ControlData data= (ControlData) curr.getData();
if (key.equals(data.getKey())) {
return curr;
}
}
for (int i= fTextBoxes.size() - 1; i >= 0; i--) {
Control curr= fTextBoxes.get(i);
Key currKey= (Key) curr.getData();
if (key.equals(currKey)) {
return curr;
}
}
return null;
}
}