From db7ea396eab44c91d44b347f7e651e570b2f3c60 Mon Sep 17 00:00:00 2001
From: Anton Leherbauer Note that
+ * Clients may use but not subclass this class.
+ *
+ * Note: This method is called every time code assist is invoked and
+ * is not filtered by partition type.
+ *
+ * Note: This method is called every time code assist is invoked and
+ * is not filtered by partition type.
+ *
+ * TODO keep this or add some other singleton, e.g. JavaPlugin?
+ *
+ * A valid partition is either one of the constants defined in
+ * {@link org.eclipse.cdt.ui.text.ICPartitions} or
+ * {@link org.eclipse.jface.text.IDocument#DEFAULT_CONTENT_TYPE}. An empty list is returned if
+ * there are no extensions for the given partition.
+ *
+ * The returned list is read-only and is sorted in the order that the extensions were read in.
+ * There are no duplicate elements in the returned list. The returned list may change if plug-ins
+ * are loaded or unloaded while the application is running or if an extension violates the API
+ * contract of {@link org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer}. When
+ * computing proposals, it is therefore imperative to copy the returned list before iterating
+ * over it.
+ *
+ * The returned list is read-only and is sorted in the order that the extensions were read in.
+ * There are no duplicate elements in the returned list. The returned list may change if plug-ins
+ * are loaded or unloaded while the application is running or if an extension violates the API
+ * contract of {@link org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer}. When
+ * computing proposals, it is therefore imperative to copy the returned list before iterating
+ * over it.
+ *
+ *
+ * The returned list is read-only and is sorted in the order that the extensions were read in.
+ * There are no duplicate elements in the returned list. The returned list may change if
+ * plug-ins are loaded or unloaded while the application is running.
+ *
+ * This method can be called more than once in order to reload from
+ * a changed extension registry.
+ *
+ * Subclasses may extend:
+ * MessageDialog
which allows the user
+ * to choose that the dialog isn't shown again the next time.
+ */
+public class OptionalMessageDialog extends MessageDialog {
+
+ // String constants for widgets
+ private static final String CHECKBOX_TEXT= CUIMessages.getString("OptionalMessageDialog_dontShowAgain"); //$NON-NLS-1$
+
+ // Dialog store id constants
+ private static final String STORE_ID= "OptionalMessageDialog.hide."; //$NON-NLS-1$
+
+ public static final int NOT_SHOWN= IDialogConstants.CLIENT_ID + 1;
+
+ private Button fHideDialogCheckBox;
+ private String fId;
+
+ /**
+ * Opens the dialog but only if the user hasn't choosen to hide it.
+ * Returns NOT_SHOWN
if the dialog was not shown.
+ */
+ public static int open(String id, Shell parent, String title, Image titleImage, String message, int dialogType, String[] buttonLabels, int defaultButtonIndex) {
+ if (!isDialogEnabled(id))
+ return OptionalMessageDialog.NOT_SHOWN;
+
+ MessageDialog dialog= new OptionalMessageDialog(id, parent, title, titleImage, message, dialogType, buttonLabels, defaultButtonIndex);
+ return dialog.open();
+ }
+
+ protected OptionalMessageDialog(String id, Shell parent, String title, Image titleImage, String message, int dialogType, String[] buttonLabels, int defaultButtonIndex) {
+ super(parent, title, titleImage, message, dialogType, buttonLabels, defaultButtonIndex);
+ fId= id;
+ }
+
+ protected Control createCustomArea(Composite parent) {
+ Composite composite= new Composite(parent, SWT.NONE);
+ GridLayout layout= new GridLayout();
+ layout.marginHeight= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+ layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+ layout.horizontalSpacing= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ fHideDialogCheckBox= new Button(composite, SWT.CHECK | SWT.LEFT);
+ fHideDialogCheckBox.setText(CHECKBOX_TEXT);
+ fHideDialogCheckBox.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ setDialogEnabled(fId, !((Button)e.widget).getSelection());
+ }
+ });
+ applyDialogFont(fHideDialogCheckBox);
+ return fHideDialogCheckBox;
+ }
+
+ //--------------- Configuration handling --------------
+
+ /**
+ * Returns this dialog
+ *
+ * @return the settings to be used
+ */
+ private static IDialogSettings getDialogSettings() {
+ IDialogSettings settings= CUIPlugin.getDefault().getDialogSettings();
+ settings= settings.getSection(STORE_ID);
+ if (settings == null)
+ settings= CUIPlugin.getDefault().getDialogSettings().addNewSection(STORE_ID);
+ return settings;
+ }
+
+ /**
+ * Answers whether the optional dialog is enabled and should be shown.
+ */
+ public static boolean isDialogEnabled(String key) {
+ IDialogSettings settings= getDialogSettings();
+ return !settings.getBoolean(key);
+ }
+
+ /**
+ * Sets whether the optional dialog is enabled and should be shown.
+ */
+ public static void setDialogEnabled(String key, boolean isEnabled) {
+ IDialogSettings settings= getDialogSettings();
+ settings.put(key, !isEnabled);
+ }
+
+ /**
+ * Clears all remembered information about hidden dialogs
+ */
+ public static void clearAllRememberedStates() {
+ IDialogSettings settings= CUIPlugin.getDefault().getDialogSettings();
+ settings.addNewSection(STORE_ID);
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java
index 4a962bd29bd..a939ea0085b 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java
@@ -2271,9 +2271,10 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IR
setAction("ContentAssistProposal", action); //$NON-NLS-1$
markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
- action = new TextOperationAction(CEditorMessages.getResourceBundle(), "ContentAssistTip.", this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); //$NON-NLS-1$
+ action= new TextOperationAction(CEditorMessages.getResourceBundle(), "ContentAssistContextInformation.", this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); //$NON-NLS-1$
action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
- setAction("ContentAssistTip", action); //$NON-NLS-1$
+ setAction("ContentAssistContextInformation", action); //$NON-NLS-1$
+ markAsStateDependentAction("ContentAssistContextInformation", true); //$NON-NLS-1$
action = new OpenDeclarationsAction(this);
action.setActionDefinitionId(ICEditorActionDefinitionIds.OPEN_DECL);
@@ -2983,10 +2984,11 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IR
protected String[] collectContextMenuPreferencePages() {
// Add C/C++ Editor relevant pages
String[] parentPrefPageIds = super.collectContextMenuPreferencePages();
- String[] prefPageIds = new String[parentPrefPageIds.length + 8];
+ String[] prefPageIds = new String[parentPrefPageIds.length + 9];
int nIds = 0;
prefPageIds[nIds++] = "org.eclipse.cdt.ui.preferences.CEditorPreferencePage"; //$NON-NLS-1$
prefPageIds[nIds++] = "org.eclipse.cdt.ui.preferences.CodeAssistPreferencePage"; //$NON-NLS-1$
+ prefPageIds[nIds++] = "org.eclipse.cdt.ui.preferences.CodeAssistPreferenceAdvanced"; //$NON-NLS-1$
prefPageIds[nIds++] = "org.eclipse.cdt.ui.preferences.HoverPreferencePage"; //$NON-NLS-1$
prefPageIds[nIds++] = "org.eclipse.cdt.ui.preferences.FoldingPreferencePage"; //$NON-NLS-1$
prefPageIds[nIds++] = "org.eclipse.cdt.ui.preferences.CodeColoringPreferencePage"; //$NON-NLS-1$
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SpecificContentAssistAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SpecificContentAssistAction.java
new file mode 100644
index 00000000000..3384e607d41
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SpecificContentAssistAction.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.editor;
+
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextOperationTarget;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.IUpdate;
+
+import org.eclipse.cdt.ui.text.ICPartitions;
+
+import org.eclipse.cdt.internal.ui.text.contentassist.CompletionProposalCategory;
+import org.eclipse.cdt.internal.ui.text.contentassist.CompletionProposalComputerRegistry;
+
+/**
+ * Action to run content assist on a specific proposal category.
+ *
+ * @since 4.0
+ */
+final class SpecificContentAssistAction extends Action implements IUpdate {
+ /**
+ * The category represented by this action.
+ */
+ private final CompletionProposalCategory fCategory;
+ /**
+ * The content assist executor.
+ */
+ private final SpecificContentAssistExecutor fExecutor= new SpecificContentAssistExecutor(CompletionProposalComputerRegistry.getDefault());
+ /**
+ * The editor.
+ */
+ private CEditor fEditor;
+
+ /**
+ * Creates a new action for a certain proposal category.
+ *
+ * @param category
+ */
+ public SpecificContentAssistAction(CompletionProposalCategory category) {
+ fCategory= category;
+ setText(category.getName());
+ setImageDescriptor(category.getImageDescriptor());
+ setActionDefinitionId("org.eclipse.cdt.ui.specific_content_assist.command"); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.action.Action#run()
+ */
+ public void run() {
+ ITextEditor editor= getActiveEditor();
+ if (editor == null)
+ return;
+
+ fExecutor.invokeContentAssist(editor, fCategory.getId());
+
+ return;
+ }
+
+ private ITextEditor getActiveEditor() {
+ return fEditor;
+ }
+
+ /**
+ * Sets the active editor part.
+ *
+ * @param part the editor, possibly null
+ */
+ public void setActiveEditor(IEditorPart part) {
+ CEditor editor;
+ if (part instanceof CEditor)
+ editor= (CEditor) part;
+ else
+ editor= null;
+ fEditor= editor;
+ setEnabled(computeEnablement(fEditor));
+ }
+
+ private boolean computeEnablement(ITextEditor editor) {
+ if (editor == null)
+ return false;
+ ITextOperationTarget target= (ITextOperationTarget) editor.getAdapter(ITextOperationTarget.class);
+ boolean hasContentAssist= target != null && target.canDoOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
+ if (!hasContentAssist)
+ return false;
+
+ ISelection selection= editor.getSelectionProvider().getSelection();
+ return isValidSelection(selection);
+ }
+
+ /**
+ * Computes the partition type at the selection start and checks whether the proposal category
+ * has any computers for this partition.
+ *
+ * @param selection the selection
+ * @return true
if there are any computers for the selection
+ */
+ private boolean isValidSelection(ISelection selection) {
+ if (!(selection instanceof ITextSelection))
+ return false;
+ int offset= ((ITextSelection) selection).getOffset();
+
+ IDocument document= getDocument();
+ if (document == null)
+ return false;
+
+ String contentType;
+ try {
+ contentType= TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, offset, true);
+ } catch (BadLocationException x) {
+ return false;
+ }
+
+ return fCategory.hasComputers(contentType);
+ }
+
+ private IDocument getDocument() {
+ Assert.isTrue(fEditor != null);
+ IDocumentProvider provider= fEditor.getDocumentProvider();
+ if (provider == null)
+ return null;
+
+ IDocument document= provider.getDocument(fEditor.getEditorInput());
+ return document;
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.IUpdate#update()
+ */
+ public void update() {
+ setEnabled(computeEnablement(fEditor));
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SpecificContentAssistExecutor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SpecificContentAssistExecutor.java
new file mode 100644
index 00000000000..54fe92814e1
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SpecificContentAssistExecutor.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.editor;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.text.ITextOperationTarget;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+import org.eclipse.cdt.internal.ui.text.contentassist.CompletionProposalCategory;
+import org.eclipse.cdt.internal.ui.text.contentassist.CompletionProposalComputerRegistry;
+
+
+/**
+ * A content assist executor can invoke content assist for a specific proposal category on an editor.
+ *
+ * @since 4.0
+ */
+public final class SpecificContentAssistExecutor {
+
+ private final CompletionProposalComputerRegistry fRegistry;
+
+ /**
+ * Creates a new executor.
+ *
+ * @param registry the computer registry to use for the enablement of proposal categories
+ */
+ public SpecificContentAssistExecutor(CompletionProposalComputerRegistry registry) {
+ Assert.isNotNull(registry);
+ fRegistry= registry;
+ }
+
+ /**
+ * Invokes content assist on editor
, showing only proposals computed by the
+ * CompletionProposalCategory
with the given categoryId
.
+ *
+ * @param editor the editor to invoke code assist on
+ * @param categoryId the id of the proposal category to show proposals for
+ */
+ public void invokeContentAssist(final ITextEditor editor, String categoryId) {
+ Collection categories= fRegistry.getProposalCategories();
+ boolean[] inclusionState= new boolean[categories.size()];
+ boolean[] separateState= new boolean[categories.size()];
+ int i= 0;
+ for (Iterator it= categories.iterator(); it.hasNext(); i++) {
+ CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
+ inclusionState[i]= cat.isIncluded();
+ cat.setIncluded(cat.getId().equals(categoryId));
+ separateState[i]= cat.isSeparateCommand();
+ cat.setSeparateCommand(false);
+ }
+
+ try {
+ ITextOperationTarget target= (ITextOperationTarget) editor.getAdapter(ITextOperationTarget.class);
+ if (target != null && target.canDoOperation(ISourceViewer.CONTENTASSIST_PROPOSALS))
+ target.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
+ } finally {
+ i= 0;
+ for (Iterator it= categories.iterator(); it.hasNext(); i++) {
+ CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
+ cat.setIncluded(inclusionState[i]);
+ cat.setSeparateCommand(separateState[i]);
+ }
+ }
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistAdvancedConfigurationBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistAdvancedConfigurationBlock.java
new file mode 100644
index 00000000000..78549c01a6e
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistAdvancedConfigurationBlock.java
@@ -0,0 +1,698 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.preferences;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.IParameter;
+import org.eclipse.core.commands.Parameterization;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.common.NotDefinedException;
+
+import org.eclipse.core.runtime.Assert;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+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.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+import org.eclipse.jface.bindings.Binding;
+import org.eclipse.jface.bindings.TriggerSequence;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+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.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.ViewerComparator;
+
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.commands.ICommandService;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.ui.keys.IBindingService;
+import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+
+import org.eclipse.cdt.ui.PreferenceConstants;
+
+import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
+import org.eclipse.cdt.internal.ui.text.contentassist.CompletionProposalCategory;
+import org.eclipse.cdt.internal.ui.text.contentassist.CompletionProposalComputerRegistry;
+import org.eclipse.cdt.internal.ui.util.Messages;
+import org.eclipse.cdt.internal.ui.util.PixelConverter;
+import org.eclipse.cdt.internal.ui.util.SWTUtil;
+
+
+/**
+ *
+ * @since 3.2
+ */
+final class CodeAssistAdvancedConfigurationBlock extends OptionsConfigurationBlock {
+
+ private static final Key PREF_EXCLUDED_CATEGORIES= getCDTUIKey(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES);
+ private static final Key PREF_CATEGORY_ORDER= getCDTUIKey(PreferenceConstants.CODEASSIST_CATEGORY_ORDER);
+
+ private static Key[] getAllKeys() {
+ return new Key[] {
+ PREF_EXCLUDED_CATEGORIES,
+ PREF_CATEGORY_ORDER,
+ };
+ }
+
+ private final class DefaultTableLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+ /*
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
+ */
+ public Image getColumnImage(Object element, int columnIndex) {
+ if (columnIndex == 0)
+ return ((ModelElement) element).getImage();
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
+ */
+ public String getColumnText(Object element, int columnIndex) {
+ switch (columnIndex) {
+ case 0:
+ return ((ModelElement) element).getName();
+ case 1:
+ return ((ModelElement) element).getKeybindingAsString();
+ default:
+ Assert.isTrue(false);
+ return null;
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ return getColumnText(element, 0); // needed to make the sorter work
+ }
+ }
+
+ private final class SeparateTableLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+ /*
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
+ */
+ public Image getColumnImage(Object element, int columnIndex) {
+ if (columnIndex == 0)
+ return ((ModelElement) element).getImage();
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
+ */
+ public String getColumnText(Object element, int columnIndex) {
+ switch (columnIndex) {
+ case 0:
+ return ((ModelElement) element).getName();
+ default:
+ Assert.isTrue(false);
+ return null;
+ }
+ }
+ }
+
+ private final Comparator fCategoryComparator= new Comparator() {
+ private int getRank(Object o) {
+ return ((ModelElement) o).getRank();
+ }
+
+ public int compare(Object o1, Object o2) {
+ return getRank(o1) - getRank(o2);
+ }
+ };
+
+ private final class PreferenceModel {
+ private static final int LIMIT= 0xffff;
+ private static final String COLON= ":"; //$NON-NLS-1$
+ private static final String SEPARATOR= "\0"; //$NON-NLS-1$
+
+ private final List fElements;
+ /**
+ * The read-only list of elements.
+ */
+ final List elements;
+
+ public PreferenceModel(CompletionProposalComputerRegistry registry) {
+ List categories= registry.getProposalCategories();
+ fElements= new ArrayList();
+ for (Iterator it= categories.iterator(); it.hasNext();) {
+ CompletionProposalCategory category= (CompletionProposalCategory) it.next();
+ if (category.hasComputers()) {
+ fElements.add(new ModelElement(category, this));
+ }
+ }
+ Collections.sort(fElements, fCategoryComparator);
+ elements= Collections.unmodifiableList(fElements);
+ }
+
+ public void moveUp(ModelElement category) {
+ int index= fElements.indexOf(category);
+ if (index > 0) {
+ Object item= fElements.remove(index);
+ fElements.add(index - 1, item);
+ writeOrderPreference(null, false);
+ }
+ }
+
+ public void moveDown(ModelElement category) {
+ int index= fElements.indexOf(category);
+ if (index < fElements.size() - 1) {
+ Object item= fElements.remove(index);
+ fElements.add(index + 1, item);
+ writeOrderPreference(null, false);
+ }
+ }
+
+ private void writeInclusionPreference(ModelElement changed, boolean isInDefaultCategory) {
+ StringBuffer buf= new StringBuffer();
+ for (Iterator it= fElements.iterator(); it.hasNext();) {
+ ModelElement item= (ModelElement) it.next();
+ boolean included= changed == item ? isInDefaultCategory : item.isInDefaultCategory();
+ if (!included)
+ buf.append(item.getId() + SEPARATOR);
+ }
+
+ String newValue= buf.toString();
+ String oldValue= setValue(PREF_EXCLUDED_CATEGORIES, newValue);
+ validateSettings(PREF_EXCLUDED_CATEGORIES, oldValue, newValue);
+ }
+
+ private void writeOrderPreference(ModelElement changed, boolean isSeparate) {
+ StringBuffer buf= new StringBuffer();
+ int i= 0;
+ for (Iterator it= fElements.iterator(); it.hasNext(); i++) {
+ ModelElement item= (ModelElement) it.next();
+ boolean separate= changed == item ? isSeparate : item.isSeparateCommand();
+ int rank= separate ? i : i + LIMIT;
+ buf.append(item.getId() + COLON + rank + SEPARATOR);
+ }
+
+ String newValue= buf.toString();
+ String oldValue= setValue(PREF_CATEGORY_ORDER, newValue);
+ validateSettings(PREF_CATEGORY_ORDER, oldValue, newValue);
+ }
+
+
+ private boolean readInclusionPreference(CompletionProposalCategory cat) {
+ String[] ids= getTokens(getValue(PREF_EXCLUDED_CATEGORIES), SEPARATOR);
+ for (int i= 0; i < ids.length; i++) {
+ if (ids[i].equals(cat.getId()))
+ return false;
+ }
+ return true;
+ }
+
+ private int readOrderPreference(CompletionProposalCategory cat) {
+ String[] sortOrderIds= getTokens(getValue(PREF_CATEGORY_ORDER), SEPARATOR);
+ for (int i= 0; i < sortOrderIds.length; i++) {
+ String[] idAndRank= getTokens(sortOrderIds[i], COLON);
+ if (idAndRank[0].equals(cat.getId()))
+ return Integer.parseInt(idAndRank[1]);
+ }
+ return LIMIT + 1;
+ }
+
+ public void update() {
+ Collections.sort(fElements, fCategoryComparator);
+ }
+ }
+
+ private final class ModelElement {
+ private final CompletionProposalCategory fCategory;
+ private final Command fCommand;
+ private final IParameter fParam;
+ private final PreferenceModel fPreferenceModel;
+
+ ModelElement(CompletionProposalCategory category, PreferenceModel model) {
+ fCategory= category;
+ ICommandService commandSvc= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class);
+ fCommand= commandSvc.getCommand("org.eclipse.cdt.ui.specific_content_assist.command"); //$NON-NLS-1$
+ IParameter type;
+ try {
+ type= fCommand.getParameters()[0];
+ } catch (NotDefinedException x) {
+ Assert.isTrue(false);
+ type= null;
+ }
+ fParam= type;
+ fPreferenceModel= model;
+ }
+ Image getImage() {
+ return CodeAssistAdvancedConfigurationBlock.this.getImage(fCategory.getImageDescriptor());
+ }
+ String getName() {
+ return fCategory.getDisplayName();
+ }
+ String getKeybindingAsString() {
+ final Parameterization[] params= { new Parameterization(fParam, fCategory.getId()) };
+ final ParameterizedCommand pCmd= new ParameterizedCommand(fCommand, params);
+ String key= getKeyboardShortcut(pCmd);
+ return key;
+ }
+ boolean isInDefaultCategory() {
+ return fPreferenceModel.readInclusionPreference(fCategory);
+ }
+ void setInDefaultCategory(boolean included) {
+ if (included != isInDefaultCategory())
+ fPreferenceModel.writeInclusionPreference(this, included);
+ }
+ String getId() {
+ return fCategory.getId();
+ }
+ int getRank() {
+ int rank= getInternalRank();
+ if (rank > PreferenceModel.LIMIT)
+ return rank - PreferenceModel.LIMIT;
+ return rank;
+ }
+ void moveUp() {
+ fPreferenceModel.moveUp(this);
+ }
+ void moveDown() {
+ fPreferenceModel.moveDown(this);
+ }
+ private int getInternalRank() {
+ return fPreferenceModel.readOrderPreference(fCategory);
+ }
+ boolean isSeparateCommand() {
+ return getInternalRank() < PreferenceModel.LIMIT;
+ }
+
+ void setSeparateCommand(boolean separate) {
+ if (separate != isSeparateCommand())
+ fPreferenceModel.writeOrderPreference(this, separate);
+ }
+
+ void update() {
+ fCategory.setIncluded(isInDefaultCategory());
+ int rank= getInternalRank();
+ fCategory.setSortOrder(rank);
+ fCategory.setSeparateCommand(rank < PreferenceModel.LIMIT);
+ }
+ }
+
+ /** element type: {@link ModelElement}. */
+ private final PreferenceModel fModel;
+ private final Map fImages= new HashMap();
+
+ private CheckboxTableViewer fDefaultViewer;
+ private CheckboxTableViewer fSeparateViewer;
+ private Button fUpButton;
+ private Button fDownButton;
+
+ CodeAssistAdvancedConfigurationBlock(IStatusChangeListener statusListener, IWorkbenchPreferenceContainer container) {
+ super(statusListener, null, getAllKeys(), container);
+ fModel= new PreferenceModel(CompletionProposalComputerRegistry.getDefault());
+ }
+
+ /*
+ * @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#createContents(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createContents(Composite parent) {
+
+ ScrolledPageContent scrolled= new ScrolledPageContent(parent, SWT.H_SCROLL | SWT.V_SCROLL);
+
+ scrolled.setExpandHorizontal(true);
+ scrolled.setExpandVertical(true);
+
+ Composite composite= new Composite(scrolled, SWT.NONE);
+ int columns= 2;
+ GridLayout layout= new GridLayout(columns, false);
+ composite.setLayout(layout);
+
+
+ createDefaultLabel(composite, columns);
+ createDefaultViewer(composite, columns);
+ createKeysLink(composite, columns);
+
+ createFiller(composite, columns);
+
+ createSeparateLabel(composite, columns);
+ createSeparateSection(composite);
+
+ createFiller(composite, columns);
+
+ updateControls();
+ if (fModel.elements.size() > 0) {
+ fDefaultViewer.getTable().select(0);
+ fSeparateViewer.getTable().select(0);
+ handleTableSelection();
+ }
+
+ scrolled.setContent(composite);
+ scrolled.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ return scrolled;
+ }
+
+ private void createDefaultLabel(Composite composite, int h_span) {
+ final ICommandService commandSvc= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class);
+ final Command command= commandSvc.getCommand(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+ ParameterizedCommand pCmd= new ParameterizedCommand(command, null);
+ String key= getKeyboardShortcut(pCmd);
+ if (key == null)
+ key= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_no_shortcut;
+
+ PixelConverter pixelConverter= new PixelConverter(composite);
+ int width= pixelConverter.convertWidthInCharsToPixels(40);
+
+ Label label= new Label(composite, SWT.NONE | SWT.WRAP);
+ label.setText(Messages.format(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_page_description, new Object[] { key }));
+ GridData gd= new GridData(GridData.FILL, GridData.FILL, true, false, h_span, 1);
+ gd.widthHint= width;
+ label.setLayoutData(gd);
+
+ createFiller(composite, h_span);
+
+ label= new Label(composite, SWT.NONE | SWT.WRAP);
+ label.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_default_table_description);
+ gd= new GridData(GridData.FILL, GridData.FILL, true, false, h_span, 1);
+ gd.widthHint= width;
+ label.setLayoutData(gd);
+ }
+
+ private void createDefaultViewer(Composite composite, int h_span) {
+ fDefaultViewer= CheckboxTableViewer.newCheckList(composite, SWT.SINGLE | SWT.BORDER);
+ Table table= fDefaultViewer.getTable();
+ table.setHeaderVisible(true);
+ table.setLinesVisible(false);
+ table.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false, h_span, 1));
+
+ TableColumn nameColumn= new TableColumn(table, SWT.NONE);
+ nameColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_default_table_category_column_title);
+ nameColumn.setResizable(false);
+ TableColumn keyColumn= new TableColumn(table, SWT.NONE);
+ keyColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_default_table_keybinding_column_title);
+ keyColumn.setResizable(false);
+
+ fDefaultViewer.addCheckStateListener(new ICheckStateListener() {
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ boolean checked= event.getChecked();
+ ModelElement element= (ModelElement) event.getElement();
+ element.setInDefaultCategory(checked);
+ }
+ });
+
+ fDefaultViewer.setContentProvider(new ArrayContentProvider());
+
+ DefaultTableLabelProvider labelProvider= new DefaultTableLabelProvider();
+ fDefaultViewer.setLabelProvider(labelProvider);
+ fDefaultViewer.setInput(fModel.elements);
+ fDefaultViewer.setComparator(new ViewerComparator()); // sort alphabetically
+
+ final int ICON_AND_CHECKBOX_WITH= 50;
+ final int HEADER_MARGIN= 20;
+ int minNameWidth= computeWidth(table, nameColumn.getText()) + HEADER_MARGIN;
+ int minKeyWidth= computeWidth(table, keyColumn.getText()) + HEADER_MARGIN;
+ for (int i= 0; i < fModel.elements.size(); i++) {
+ minNameWidth= Math.max(minNameWidth, computeWidth(table, labelProvider.getColumnText(fModel.elements.get(i), 0)) + ICON_AND_CHECKBOX_WITH);
+ minKeyWidth= Math.max(minKeyWidth, computeWidth(table, labelProvider.getColumnText(fModel.elements.get(i), 1)));
+ }
+
+ nameColumn.setWidth(minNameWidth);
+ keyColumn.setWidth(minKeyWidth);
+ }
+
+ private void createKeysLink(Composite composite, int h_span) {
+ Link link= new Link(composite, SWT.NONE | SWT.WRAP);
+ link.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_key_binding_hint);
+ link.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ PreferencesUtil.createPreferenceDialogOn(getShell(), e.text, null, null);
+ }
+ });
+
+ PixelConverter pixelConverter= new PixelConverter(composite);
+ int width= pixelConverter.convertWidthInCharsToPixels(40);
+
+ // limit the size of the Link as it would take all it can get
+ GridData gd= new GridData(GridData.FILL, GridData.FILL, false, false, h_span, 1);
+ gd.widthHint= width;
+ link.setLayoutData(gd);
+ }
+
+ private void createFiller(Composite composite, int h_span) {
+ Label filler= new Label(composite, SWT.NONE);
+ filler.setVisible(false);
+ filler.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, h_span, 1));
+ }
+
+ private void createSeparateLabel(Composite composite, int h_span) {
+ PixelConverter pixelConverter= new PixelConverter(composite);
+ int width= pixelConverter.convertWidthInCharsToPixels(40);
+
+ Label label= new Label(composite, SWT.NONE | SWT.WRAP);
+ label.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_separate_table_description);
+ GridData gd= new GridData(GridData.FILL, GridData.FILL, false, false, h_span, 1);
+ gd.widthHint= width;
+ label.setLayoutData(gd);
+ }
+
+ private void createSeparateSection(Composite composite) {
+ createSeparateViewer(composite);
+ createButtonList(composite);
+ }
+
+ private void createSeparateViewer(Composite composite) {
+ fSeparateViewer= CheckboxTableViewer.newCheckList(composite, SWT.SINGLE | SWT.BORDER);
+ Table table= fSeparateViewer.getTable();
+ table.setHeaderVisible(false);
+ table.setLinesVisible(false);
+ table.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false, 1, 1));
+
+ TableColumn nameColumn= new TableColumn(table, SWT.NONE);
+ nameColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_separate_table_category_column_title);
+ nameColumn.setResizable(false);
+
+ fSeparateViewer.setContentProvider(new ArrayContentProvider());
+
+ ITableLabelProvider labelProvider= new SeparateTableLabelProvider();
+ fSeparateViewer.setLabelProvider(labelProvider);
+ fSeparateViewer.setInput(fModel.elements);
+
+ final int ICON_AND_CHECKBOX_WITH= 50;
+ final int HEADER_MARGIN= 20;
+ int minNameWidth= computeWidth(table, nameColumn.getText()) + HEADER_MARGIN;
+ for (int i= 0; i < fModel.elements.size(); i++) {
+ minNameWidth= Math.max(minNameWidth, computeWidth(table, labelProvider.getColumnText(fModel.elements.get(i), 0)) + ICON_AND_CHECKBOX_WITH);
+ }
+
+ nameColumn.setWidth(minNameWidth);
+
+ fSeparateViewer.addCheckStateListener(new ICheckStateListener() {
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ boolean checked= event.getChecked();
+ ModelElement element= (ModelElement) event.getElement();
+ element.setSeparateCommand(checked);
+ }
+ });
+
+ table.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleTableSelection();
+ }
+ });
+
+ }
+
+ private void createButtonList(Composite parent) {
+ Composite composite= new Composite(parent, SWT.NONE);
+ composite.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
+
+ GridLayout layout= new GridLayout();
+ layout.marginWidth= 0;
+ layout.marginHeight= 0;
+ composite.setLayout(layout);
+
+ fUpButton= new Button(composite, SWT.PUSH | SWT.CENTER);
+ fUpButton.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_Up);
+ fUpButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ int index= getSelectionIndex();
+ if (index != -1) {
+ ((ModelElement) fModel.elements.get(index)).moveUp();
+ fSeparateViewer.refresh();
+ handleTableSelection();
+ }
+ }
+ });
+ fUpButton.setLayoutData(new GridData());
+ SWTUtil.setButtonDimensionHint(fUpButton);
+
+ fDownButton= new Button(composite, SWT.PUSH | SWT.CENTER);
+ fDownButton.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_Down);
+ fDownButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ int index= getSelectionIndex();
+ if (index != -1) {
+ ((ModelElement) fModel.elements.get(index)).moveDown();
+ fSeparateViewer.refresh();
+ handleTableSelection();
+ }
+ }
+ });
+ fDownButton.setLayoutData(new GridData());
+ SWTUtil.setButtonDimensionHint(fDownButton);
+ }
+
+ private void handleTableSelection() {
+ ModelElement item= getSelectedItem();
+ if (item != null) {
+ int index= getSelectionIndex();
+ fUpButton.setEnabled(index > 0);
+ fDownButton.setEnabled(index < fModel.elements.size() - 1);
+ } else {
+ fUpButton.setEnabled(false);
+ fDownButton.setEnabled(false);
+ }
+ }
+
+ private ModelElement getSelectedItem() {
+ return (ModelElement) ((IStructuredSelection) fSeparateViewer.getSelection()).getFirstElement();
+ }
+
+ private int getSelectionIndex() {
+ return fSeparateViewer.getTable().getSelectionIndex();
+ }
+
+ /*
+ * @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#updateControls()
+ */
+ protected void updateControls() {
+ super.updateControls();
+
+ fModel.update();
+ updateCheckedState();
+ fDefaultViewer.refresh();
+ fSeparateViewer.refresh();
+ handleTableSelection();
+ }
+
+ private void updateCheckedState() {
+ final int size= fModel.elements.size();
+ List defaultChecked= new ArrayList(size);
+ List separateChecked= new ArrayList(size);
+
+ for (Iterator it= fModel.elements.iterator(); it.hasNext();) {
+ ModelElement element= (ModelElement) it.next();
+ if (element.isInDefaultCategory())
+ defaultChecked.add(element);
+ if (element.isSeparateCommand())
+ separateChecked.add(element);
+ }
+
+ fDefaultViewer.setCheckedElements(defaultChecked.toArray(new Object[defaultChecked.size()]));
+ fSeparateViewer.setCheckedElements(separateChecked.toArray(new Object[separateChecked.size()]));
+ }
+
+ /*
+ * @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#processChanges(org.eclipse.ui.preferences.IWorkbenchPreferenceContainer)
+ */
+ protected boolean processChanges(IWorkbenchPreferenceContainer container) {
+ for (Iterator it= fModel.elements.iterator(); it.hasNext();) {
+ ModelElement item= (ModelElement) it.next();
+ item.update();
+ }
+
+ return super.processChanges(container);
+ }
+
+ /*
+ * @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock.Key, java.lang.String, java.lang.String)
+ */
+ protected void validateSettings(Key changedKey, String oldValue, String newValue) {
+ }
+
+ /*
+ * @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#getFullBuildDialogStrings(boolean)
+ */
+ protected String[] getFullBuildDialogStrings(boolean workspaceSettings) {
+ // no builds triggered by our settings
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#dispose()
+ */
+ public void dispose() {
+ for (Iterator it= fImages.values().iterator(); it.hasNext();) {
+ Image image= (Image) it.next();
+ image.dispose();
+ }
+
+ super.dispose();
+ }
+
+ private int computeWidth(Control control, String name) {
+ if (name == null)
+ return 0;
+ GC gc= new GC(control);
+ try {
+ gc.setFont(JFaceResources.getDialogFont());
+ return gc.stringExtent(name).x + 10;
+ } finally {
+ gc.dispose();
+ }
+ }
+
+ private static String getKeyboardShortcut(ParameterizedCommand command) {
+ final IBindingService bindingSvc= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
+ final Binding[] bindings= bindingSvc.getBindings();
+ for (int i= 0; i < bindings.length; i++) {
+ Binding binding= bindings[i];
+ if (command.equals(binding.getParameterizedCommand())) {
+ TriggerSequence triggers= binding.getTriggerSequence();
+ return triggers.format();
+ }
+ }
+ return null;
+ }
+
+ private Image getImage(ImageDescriptor imgDesc) {
+ if (imgDesc == null)
+ return null;
+
+ Image img= (Image) fImages.get(imgDesc);
+ if (img == null) {
+ img= imgDesc.createImage(false);
+ fImages.put(imgDesc, img);
+ }
+ return img;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistAdvancedPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistAdvancedPreferencePage.java
new file mode 100644
index 00000000000..ac1e7aadfc3
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistAdvancedPreferencePage.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.preferences;
+
+import org.eclipse.core.resources.IProject;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
+
+import org.eclipse.cdt.internal.ui.ICHelpContextIds;
+
+public final class CodeAssistAdvancedPreferencePage extends PropertyAndPreferencePage {
+
+ private CodeAssistAdvancedConfigurationBlock fConfigurationBlock;
+
+ public void createControl(Composite parent) {
+ IWorkbenchPreferenceContainer container= (IWorkbenchPreferenceContainer) getContainer();
+ fConfigurationBlock= new CodeAssistAdvancedConfigurationBlock(getNewStatusChangedListener(), container);
+
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), ICHelpContextIds.C_EDITOR_PREF_PAGE);
+ }
+
+ protected Control createPreferenceContent(Composite composite) {
+ return fConfigurationBlock.createContents(composite);
+ }
+
+ protected boolean hasProjectSpecificOptions(IProject project) {
+ return false;
+ }
+
+ protected String getPreferencePageID() {
+ return "org.eclipse.cdt.ui.preferences.CodeAssistPreferenceAdvanced"; //$NON-NLS-1$
+ }
+
+ protected String getPropertyPageID() {
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.dialogs.DialogPage#dispose()
+ */
+ public void dispose() {
+ if (fConfigurationBlock != null) {
+ fConfigurationBlock.dispose();
+ }
+ super.dispose();
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ super.performDefaults();
+ if (fConfigurationBlock != null) {
+ fConfigurationBlock.performDefaults();
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+ if (fConfigurationBlock != null && !fConfigurationBlock.performOk()) {
+ return false;
+ }
+ return super.performOk();
+ }
+
+ /*
+ * @see org.eclipse.jface.preference.IPreferencePage#performApply()
+ */
+ public void performApply() {
+ if (fConfigurationBlock != null) {
+ fConfigurationBlock.performApply();
+ }
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistPreferencePage.java
index 88629172e34..e25208bae54 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistPreferencePage.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistPreferencePage.java
@@ -45,13 +45,13 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, ContentAssistPreference.AUTOACTIVATION_DELAY));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.AUTOINSERT));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.PREFIX_COMPLETION));
- overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, ContentAssistPreference.TIMEOUT_DELAY));
+// overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, ContentAssistPreference.TIMEOUT_DELAY));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.AUTOACTIVATION_TRIGGERS_DOT));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.AUTOACTIVATION_TRIGGERS_ARROW));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.AUTOACTIVATION_TRIGGERS_DOUBLECOLON));
- overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.SHOW_DOCUMENTED_PROPOSALS));
- overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.ORDER_PROPOSALS));
- overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.ADD_INCLUDE));
+// overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.SHOW_DOCUMENTED_PROPOSALS));
+// overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.ORDER_PROPOSALS));
+// overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.ADD_INCLUDE));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.CURRENT_FILE_SEARCH_SCOPE));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.PROJECT_SEARCH_SCOPE));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.PROPOSALS_FILTER));
@@ -106,8 +106,8 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
label = PreferencesMessages.CEditorPreferencePage_ContentAssistPage_sortingSection_title;
Group sortingGroup = addGroupBox(contentAssistComposite, label, 2);
- label= PreferencesMessages.CEditorPreferencePage_ContentAssistPage_showProposalsInAlphabeticalOrder;
- addCheckBox(sortingGroup, label, ContentAssistPreference.ORDER_PROPOSALS, 0);
+// label= PreferencesMessages.CEditorPreferencePage_ContentAssistPage_showProposalsInAlphabeticalOrder;
+// addCheckBox(sortingGroup, label, ContentAssistPreference.ORDER_PROPOSALS, 0);
label = PreferencesMessages.CEditorPreferencePage_ContentAssistPage_proposalFilterSelect ;
addComboBox(sortingGroup, label, ContentAssistPreference.PROPOSALS_FILTER, 20, 0);
@@ -147,7 +147,7 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
store.setDefault(ContentAssistPreference.CURRENT_FILE_SEARCH_SCOPE, true);
store.setDefault(ContentAssistPreference.PROJECT_SEARCH_SCOPE, false);
- store.setDefault(ContentAssistPreference.TIMEOUT_DELAY, 3000);
+// store.setDefault(ContentAssistPreference.TIMEOUT_DELAY, 3000);
store.setDefault(ContentAssistPreference.AUTOACTIVATION_TRIGGERS_DOT, true);
store.setDefault(ContentAssistPreference.AUTOACTIVATION_TRIGGERS_ARROW, true);
@@ -156,8 +156,8 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
store.setDefault(ContentAssistPreference.AUTOINSERT, true);
store.setDefault(ContentAssistPreference.PREFIX_COMPLETION, true);
- store.setDefault(ContentAssistPreference.ORDER_PROPOSALS, false);
- store.setDefault(ContentAssistPreference.ADD_INCLUDE, true);
+// store.setDefault(ContentAssistPreference.ORDER_PROPOSALS, false);
+// store.setDefault(ContentAssistPreference.ADD_INCLUDE, true);
store.setDefault(ContentAssistPreference.PROPOSALS_FILTER, ProposalFilterPreferencesUtil.getProposalFilternamesAsString()); // $NON_NLS 1$
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OptionsConfigurationBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OptionsConfigurationBlock.java
index 94ad696cec3..3d319f09738 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OptionsConfigurationBlock.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OptionsConfigurationBlock.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation 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
@@ -7,72 +7,130 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
-import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
-import org.eclipse.core.resources.IncrementalProjectBuilder;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IResourceProxy;
-import org.eclipse.core.resources.IResourceProxyVisitor;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.SubProgressMonitor;
-
-import org.eclipse.osgi.util.NLS;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;
-
-import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.dialogs.ProgressMonitorDialog;
-import org.eclipse.jface.operation.IRunnableWithProgress;
-
-import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.forms.events.ExpansionAdapter;
+import org.eclipse.ui.forms.events.ExpansionEvent;
+import org.eclipse.ui.forms.widgets.ExpandableComposite;
+import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
+import org.eclipse.ui.preferences.IWorkingCopyManager;
+import org.eclipse.ui.preferences.WorkingCopyManager;
+import org.osgi.service.prefs.BackingStoreException;
import org.eclipse.cdt.core.CCorePlugin;
-import org.eclipse.cdt.core.model.CoreModel;
-import org.eclipse.cdt.core.model.CModelException;
-import org.eclipse.cdt.core.model.ICProject;
-import org.eclipse.cdt.core.model.ITranslationUnit;
-
import org.eclipse.cdt.ui.CUIPlugin;
-import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
-import org.eclipse.cdt.internal.ui.util.EditorUtility;
+
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
/**
- */
+ * Abstract options configuration block providing a general implementation for setting up
+ * an options configuration page.
+ */
public abstract class OptionsConfigurationBlock {
+
+ public static final class Key {
+
+ private String fQualifier;
+ private String fKey;
+
+ public Key(String qualifier, String key) {
+ fQualifier= qualifier;
+ fKey= key;
+ }
+
+ public String getName() {
+ return fKey;
+ }
+
+ private IEclipsePreferences getNode(IScopeContext context, IWorkingCopyManager manager) {
+ IEclipsePreferences node= context.getNode(fQualifier);
+ if (manager != null) {
+ return manager.getWorkingCopy(node);
+ }
+ return node;
+ }
+
+ public String getStoredValue(IScopeContext context, IWorkingCopyManager manager) {
+ return getNode(context, manager).get(fKey, null);
+ }
+
+ public String getStoredValue(IScopeContext[] lookupOrder, boolean ignoreTopScope, IWorkingCopyManager manager) {
+ for (int i= ignoreTopScope ? 1 : 0; i < lookupOrder.length; i++) {
+ String value= getStoredValue(lookupOrder[i], manager);
+ if (value != null) {
+ return value;
+ }
+ }
+ return null;
+ }
+
+ public void setStoredValue(IScopeContext context, String value, IWorkingCopyManager manager) {
+ if (value != null) {
+ getNode(context, manager).put(fKey, value);
+ } else {
+ getNode(context, manager).remove(fKey);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return fQualifier + '/' + fKey;
+ }
+
+ public String getQualifier() {
+ return fQualifier;
+ }
+
+ }
+
protected static class ControlData {
- private String fKey;
+ private Key fKey;
private String[] fValues;
- public ControlData(String key, String[] values) {
+ public ControlData(Key key, String[] values) {
fKey= key;
fValues= values;
}
- public String getKey() {
+ public Key getKey() {
return fKey;
}
@@ -86,75 +144,170 @@ public abstract class OptionsConfigurationBlock {
}
public int getSelection(String value) {
- for (int i= 0; i < fValues.length; i++) {
- if (value.equals(fValues[i])) {
- return i;
+ if (value != null) {
+ for (int i= 0; i < fValues.length; i++) {
+ if (value.equals(fValues[i])) {
+ return i;
+ }
}
}
- throw new IllegalArgumentException();
+ return fValues.length -1; // assume the last option is the least severe
}
}
+ private static final String REBUILD_COUNT_KEY= "preferences_build_requested"; //$NON-NLS-1$
- protected Map fWorkingValues;
+ private static final String SETTINGS_EXPANDED= "expanded"; //$NON-NLS-1$
- protected ArrayList fCheckBoxes;
- protected ArrayList fComboBoxes;
- protected ArrayList fTextBoxes;
+ protected final ArrayList fCheckBoxes;
+ protected final ArrayList fComboBoxes;
+ protected final ArrayList fTextBoxes;
+ protected final HashMap fLabels;
+ protected final ArrayList fExpandedComposites;
private SelectionListener fSelectionListener;
private ModifyListener fTextModifyListener;
protected IStatusChangeListener fContext;
- protected ICProject fProject; // project or null
+ protected final IProject fProject; // project or null
+ protected final Key[] fAllKeys;
+
+ private IScopeContext[] fLookupOrder;
private Shell fShell;
- public OptionsConfigurationBlock(IStatusChangeListener context, ICProject project) {
+ private final IWorkingCopyManager fManager;
+ private IWorkbenchPreferenceContainer fContainer;
+
+ private Map fDisabledProjectSettings; // null when project specific settings are turned off
+
+ private int fRebuildCount; /// used to prevent multiple dialogs that ask for a rebuild
+
+ public OptionsConfigurationBlock(IStatusChangeListener context, IProject project, Key[] allKeys, IWorkbenchPreferenceContainer container) {
fContext= context;
fProject= project;
+ fAllKeys= allKeys;
+ fContainer= container;
+ if (container == null) {
+ fManager= new WorkingCopyManager();
+ } else {
+ fManager= container.getWorkingCopyManager();
+ }
- fWorkingValues= getOptions(true);
+ if (fProject != null) {
+ fLookupOrder= new IScopeContext[] {
+ new ProjectScope(fProject),
+ new InstanceScope(),
+ new DefaultScope()
+ };
+ } else {
+ fLookupOrder= new IScopeContext[] {
+ new InstanceScope(),
+ new DefaultScope()
+ };
+ }
+
+ testIfOptionsComplete(allKeys);
+ if (fProject == null || hasProjectSpecificOptions(fProject)) {
+ fDisabledProjectSettings= null;
+ } else {
+ fDisabledProjectSettings= new IdentityHashMap();
+ for (int i= 0; i < allKeys.length; i++) {
+ Key curr= allKeys[i];
+ fDisabledProjectSettings.put(curr, curr.getStoredValue(fLookupOrder, false, fManager));
+ }
+ }
+
+ settingsUpdated();
fCheckBoxes= new ArrayList();
fComboBoxes= new ArrayList();
- fTextBoxes= new ArrayList(2);
- }
-
- protected abstract String[] getAllKeys();
-
- protected Map getOptions(boolean inheritCCoreOptions) {
- if (fProject != null) {
- return fProject.getOptions(inheritCCoreOptions);
- }
- return CCorePlugin.getOptions();
- }
-
- protected Map getDefaultOptions() {
- return CCorePlugin.getDefaultOptions();
+ fTextBoxes= new ArrayList(2);
+ fLabels= new HashMap();
+ fExpandedComposites= new ArrayList();
+
+ fRebuildCount= getRebuildCount();
}
- public final boolean hasProjectSpecificOptions() {
- if (fProject != null) {
- Map settings= fProject.getOptions(false);
- String[] allKeys= getAllKeys();
+ protected final IWorkbenchPreferenceContainer getPreferenceContainer() {
+ return fContainer;
+ }
+
+ protected static Key getKey(String plugin, String key) {
+ return new Key(plugin, key);
+ }
+
+ protected final static Key getCDTCoreKey(String key) {
+ return getKey(CCorePlugin.PLUGIN_ID, key);
+ }
+
+ protected final static Key getCDTUIKey(String key) {
+ return getKey(CUIPlugin.PLUGIN_ID, key);
+ }
+
+
+ private void testIfOptionsComplete(Key[] allKeys) {
+ for (int i= 0; i < allKeys.length; i++) {
+ if (allKeys[i].getStoredValue(fLookupOrder, false, fManager) == null) {
+ CUIPlugin.getDefault().logErrorMessage("preference option missing: " + allKeys[i] + " (" + this.getClass().getName() +')'); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ }
+ }
+
+ private int getRebuildCount() {
+ return fManager.getWorkingCopy(new DefaultScope().getNode(CUIPlugin.PLUGIN_ID)).getInt(REBUILD_COUNT_KEY, 0);
+ }
+
+ private void incrementRebuildCount() {
+ fRebuildCount++;
+ fManager.getWorkingCopy(new DefaultScope().getNode(CUIPlugin.PLUGIN_ID)).putInt(REBUILD_COUNT_KEY, fRebuildCount);
+ }
+
+
+ protected void settingsUpdated() {
+ }
+
+
+ public void selectOption(String key, String qualifier) {
+ for (int i= 0; i < fAllKeys.length; i++) {
+ Key curr= fAllKeys[i];
+ if (curr.getName().equals(key) && curr.getQualifier().equals(qualifier)) {
+ selectOption(curr);
+ }
+ }
+ }
+
+ public void selectOption(Key key) {
+ Control control= findControl(key);
+ if (control != null) {
+ if (!fExpandedComposites.isEmpty()) {
+ ExpandableComposite expandable= getParentExpandableComposite(control);
+ if (expandable != null) {
+ for (int i= 0; i < fExpandedComposites.size(); i++) {
+ ExpandableComposite curr= (ExpandableComposite) fExpandedComposites.get(i);
+ curr.setExpanded(curr == expandable);
+ }
+ expandedStateChanged(expandable);
+ }
+ }
+ control.setFocus();
+ }
+ }
+
+
+ public final boolean hasProjectSpecificOptions(IProject project) {
+ if (project != null) {
+ IScopeContext projectContext= new ProjectScope(project);
+ Key[] allKeys= fAllKeys;
for (int i= 0; i < allKeys.length; i++) {
- if (settings.get(allKeys[i]) != null) {
+ if (allKeys[i].getStoredValue(projectContext, fManager) != null) {
return true;
}
}
}
return false;
}
-
- protected final void setOptions(Map map) {
- if (fProject != null) {
- fProject.setOptions(map);
- } else {
- CCorePlugin.setOptions((HashMap) map);
- }
- }
-
+
protected Shell getShell() {
return fShell;
}
@@ -165,58 +318,150 @@ public abstract class OptionsConfigurationBlock {
protected abstract Control createContents(Composite parent);
- protected void addCheckBox(Composite parent, String label, String key, String[] values, int indent) {
+ protected Button addCheckBox(Composite parent, String label, Key key, String[] values, int indent) {
ControlData data= new ControlData(key, values);
GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
- gd.horizontalSpan= 2;
+ gd.horizontalSpan= 3;
gd.horizontalIndent= indent;
Button checkBox= new Button(parent, SWT.CHECK);
+ checkBox.setFont(JFaceResources.getDialogFont());
checkBox.setText(label);
checkBox.setData(data);
checkBox.setLayoutData(gd);
checkBox.addSelectionListener(getSelectionListener());
- String currValue= (String)fWorkingValues.get(key);
+ makeScrollableCompositeAware(checkBox);
+
+ String currValue= getValue(key);
checkBox.setSelection(data.getSelection(currValue) == 0);
fCheckBoxes.add(checkBox);
+
+ return checkBox;
}
- protected void addComboBox(Composite parent, String label, String key, String[] values, String[] valueLabels, int indent) {
+ protected Button addCheckBoxWithLink(Composite parent, String label, Key key, String[] values, int indent, int widthHint, SelectionListener listener) {
ControlData data= new ControlData(key, values);
- GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ GridData gd= new GridData(GridData.FILL, GridData.FILL, true, false);
+ gd.horizontalSpan= 3;
+ gd.horizontalIndent= indent;
+
+ Composite composite= new Composite(parent, SWT.NONE);
+ GridLayout layout= new GridLayout();
+ layout.marginHeight= 0;
+ layout.marginWidth= 0;
+ layout.numColumns= 2;
+ composite.setLayout(layout);
+ composite.setLayoutData(gd);
+
+ Button checkBox= new Button(composite, SWT.CHECK);
+ checkBox.setFont(JFaceResources.getDialogFont());
+ checkBox.setData(data);
+ checkBox.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
+ checkBox.addSelectionListener(getSelectionListener());
+
+ gd= new GridData(GridData.FILL, GridData.CENTER, true, false);
+ gd.widthHint= widthHint;
+
+ Link link= new Link(composite, SWT.NONE);
+ link.setText(label);
+ link.setLayoutData(gd);
+ if (listener != null) {
+ link.addSelectionListener(listener);
+ }
+
+ makeScrollableCompositeAware(link);
+ makeScrollableCompositeAware(checkBox);
+
+ String currValue= getValue(key);
+ checkBox.setSelection(data.getSelection(currValue) == 0);
+
+ fCheckBoxes.add(checkBox);
+
+ return checkBox;
+ }
+
+ protected Combo addComboBox(Composite parent, String label, Key key, String[] values, String[] valueLabels, int indent) {
+ GridData gd= new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1);
gd.horizontalIndent= indent;
- Label labelControl= new Label(parent, SWT.LEFT | SWT.WRAP);
+ Label labelControl= new Label(parent, SWT.LEFT);
+ labelControl.setFont(JFaceResources.getDialogFont());
labelControl.setText(label);
labelControl.setLayoutData(gd);
+
+ Combo comboBox= newComboControl(parent, key, values, valueLabels);
+ comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ fLabels.put(comboBox, labelControl);
- Combo comboBox= new Combo(parent, SWT.READ_ONLY);
+ return comboBox;
+ }
+
+ protected Combo addInversedComboBox(Composite parent, String label, Key key, String[] values, String[] valueLabels, int indent) {
+ GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.horizontalIndent= indent;
+ gd.horizontalSpan= 3;
+
+ Composite composite= new Composite(parent, SWT.NONE);
+ GridLayout layout= new GridLayout();
+ layout.marginHeight= 0;
+ layout.marginWidth= 0;
+ layout.numColumns= 2;
+ composite.setLayout(layout);
+ composite.setLayoutData(gd);
+
+ Combo comboBox= newComboControl(composite, key, values, valueLabels);
+ comboBox.setFont(JFaceResources.getDialogFont());
+ comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ Label labelControl= new Label(composite, SWT.LEFT | SWT.WRAP);
+ labelControl.setText(label);
+ labelControl.setLayoutData(new GridData());
+
+ fLabels.put(comboBox, labelControl);
+ return comboBox;
+ }
+
+ protected Combo newComboControl(Composite composite, Key key, String[] values, String[] valueLabels) {
+ ControlData data= new ControlData(key, values);
+
+ Combo comboBox= new Combo(composite, SWT.READ_ONLY);
comboBox.setItems(valueLabels);
comboBox.setData(data);
- comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
comboBox.addSelectionListener(getSelectionListener());
+ comboBox.setFont(JFaceResources.getDialogFont());
+
+ makeScrollableCompositeAware(comboBox);
- String currValue= (String)fWorkingValues.get(key);
+ String currValue= getValue(key);
comboBox.select(data.getSelection(currValue));
fComboBoxes.add(comboBox);
+ return comboBox;
}
-
- protected Text addTextField(Composite parent, String label, String key, int indent, int widthHint) {
- Label labelControl= new Label(parent, SWT.NONE);
+
+ protected Text addTextField(Composite parent, String label, Key key, int indent, int widthHint) {
+ Label labelControl= new Label(parent, SWT.WRAP);
labelControl.setText(label);
+ labelControl.setFont(JFaceResources.getDialogFont());
labelControl.setLayoutData(new GridData());
Text textBox= new Text(parent, SWT.BORDER | SWT.SINGLE);
textBox.setData(key);
textBox.setLayoutData(new GridData());
- String currValue= (String) fWorkingValues.get(key);
- textBox.setText(currValue);
+ makeScrollableCompositeAware(textBox);
+
+ fLabels.put(textBox, labelControl);
+
+ String currValue= getValue(key);
+ if (currValue != null) {
+ textBox.setText(currValue);
+ }
textBox.addModifyListener(getTextModifyListener());
GridData data= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
@@ -224,12 +469,83 @@ public abstract class OptionsConfigurationBlock {
data.widthHint= widthHint;
}
data.horizontalIndent= indent;
+ data.horizontalSpan= 2;
textBox.setLayoutData(data);
fTextBoxes.add(textBox);
return textBox;
- }
-
+ }
+
+ protected ScrolledPageContent getParentScrolledComposite(Control control) {
+ Control parent= control.getParent();
+ while (!(parent instanceof ScrolledPageContent) && parent != null) {
+ parent= parent.getParent();
+ }
+ if (parent instanceof ScrolledPageContent) {
+ return (ScrolledPageContent) parent;
+ }
+ return null;
+ }
+
+ protected ExpandableComposite getParentExpandableComposite(Control control) {
+ Control parent= control.getParent();
+ while (!(parent instanceof ExpandableComposite) && parent != null) {
+ parent= parent.getParent();
+ }
+ if (parent instanceof ExpandableComposite) {
+ return (ExpandableComposite) parent;
+ }
+ return null;
+ }
+
+ private void makeScrollableCompositeAware(Control control) {
+ ScrolledPageContent parentScrolledComposite= getParentScrolledComposite(control);
+ if (parentScrolledComposite != null) {
+ parentScrolledComposite.adaptChild(control);
+ }
+ }
+
+ protected ExpandableComposite createStyleSection(Composite parent, String label, int nColumns) {
+ ExpandableComposite excomposite= new ExpandableComposite(parent, SWT.NONE, ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT);
+ excomposite.setText(label);
+ excomposite.setExpanded(false);
+ excomposite.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT));
+ excomposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, nColumns, 1));
+ excomposite.addExpansionListener(new ExpansionAdapter() {
+ public void expansionStateChanged(ExpansionEvent e) {
+ expandedStateChanged((ExpandableComposite) e.getSource());
+ }
+ });
+ fExpandedComposites.add(excomposite);
+ makeScrollableCompositeAware(excomposite);
+ return excomposite;
+ }
+
+ protected final void expandedStateChanged(ExpandableComposite expandable) {
+ ScrolledPageContent parentScrolledComposite= getParentScrolledComposite(expandable);
+ if (parentScrolledComposite != null) {
+ parentScrolledComposite.reflow(true);
+ }
+ }
+
+ protected void restoreSectionExpansionStates(IDialogSettings settings) {
+ for (int i= 0; i < fExpandedComposites.size(); i++) {
+ ExpandableComposite excomposite= (ExpandableComposite) fExpandedComposites.get(i);
+ if (settings == null) {
+ excomposite.setExpanded(i == 0); // only expand the first node by default
+ } else {
+ excomposite.setExpanded(settings.getBoolean(SETTINGS_EXPANDED + String.valueOf(i)));
+ }
+ }
+ }
+
+ protected void storeSectionExpansionStates(IDialogSettings settings) {
+ for (int i= 0; i < fExpandedComposites.size(); i++) {
+ ExpandableComposite curr= (ExpandableComposite) fExpandedComposites.get(i);
+ settings.put(SETTINGS_EXPANDED + String.valueOf(i), curr.isExpanded());
+ }
+ }
+
protected SelectionListener getSelectionListener() {
if (fSelectionListener == null) {
fSelectionListener= new SelectionListener() {
@@ -264,27 +580,60 @@ public abstract class OptionsConfigurationBlock {
} else {
return;
}
- fWorkingValues.put(data.getKey(), newValue);
-
- validateSettings(data.getKey(), newValue);
+ String oldValue= setValue(data.getKey(), newValue);
+ validateSettings(data.getKey(), oldValue, newValue);
}
protected void textChanged(Text textControl) {
- String key= (String) textControl.getData();
+ Key key= (Key) textControl.getData();
String number= textControl.getText();
- fWorkingValues.put(key, number);
- validateSettings(key, number);
+ String oldValue= setValue(key, number);
+ validateSettings(key, oldValue, number);
}
- protected boolean checkValue(String key, String value) {
- return value.equals(fWorkingValues.get(key));
+ protected boolean checkValue(Key key, String value) {
+ return value.equals(getValue(key));
}
- /* (non-javadoc)
+ protected String getValue(Key key) {
+ if (fDisabledProjectSettings != null) {
+ return (String) fDisabledProjectSettings.get(key);
+ }
+ return key.getStoredValue(fLookupOrder, false, fManager);
+ }
+
+
+ protected boolean getBooleanValue(Key key) {
+ return Boolean.valueOf(getValue(key)).booleanValue();
+ }
+
+ protected String setValue(Key key, String value) {
+ if (fDisabledProjectSettings != null) {
+ return (String) fDisabledProjectSettings.put(key, value);
+ }
+ String oldValue= getValue(key);
+ key.setStoredValue(fLookupOrder[0], value, fManager);
+ return oldValue;
+ }
+
+ protected String setValue(Key key, boolean value) {
+ return setValue(key, String.valueOf(value));
+ }
+
+ /**
+ * Returns the value as actually stored in the preference store.
+ * @param key
+ * @return the value as actually stored in the preference store.
+ */
+ protected String getStoredValue(Key key) {
+ return key.getStoredValue(fLookupOrder, false, fManager);
+ }
+
+ /**
* Update fields and validate.
* @param changedKey Key that changed, or null, if all changed.
*/
- protected abstract void validateSettings(String changedKey, String newValue);
+ protected abstract void validateSettings(Key changedKey, String oldValue, String newValue);
protected String[] getTokens(String text, String separator) {
@@ -295,183 +644,242 @@ public abstract class OptionsConfigurationBlock {
res[i]= tok.nextToken().trim();
}
return res;
- }
+ }
-
- public boolean performOk(boolean enabled) {
- String[] allKeys= getAllKeys();
- Map actualOptions= getOptions(false);
-
- // preserve other options
- boolean hasChanges= false;
- for (int i= 0; i < allKeys.length; i++) {
- String key= allKeys[i];
- String oldVal= (String) actualOptions.get(key);
- String val= null;
- if (enabled) {
- val= (String) fWorkingValues.get(key);
- if (!val.equals(oldVal)) {
- hasChanges= true;
- actualOptions.put(key, val);
- }
- } else {
+ private boolean getChanges(IScopeContext currContext, List changedSettings) {
+ boolean needsBuild= false;
+ for (int i= 0; i < fAllKeys.length; i++) {
+ Key key= fAllKeys[i];
+ String oldVal= key.getStoredValue(currContext, null);
+ String val= key.getStoredValue(currContext, fManager);
+ if (val == null) {
if (oldVal != null) {
- actualOptions.remove(key);
- hasChanges= true;
+ changedSettings.add(key);
+ needsBuild |= !oldVal.equals(key.getStoredValue(fLookupOrder, true, fManager));
+ }
+ } else if (!val.equals(oldVal)) {
+ changedSettings.add(key);
+ needsBuild |= oldVal != null || !val.equals(key.getStoredValue(fLookupOrder, true, fManager));
+ }
+ }
+ return needsBuild;
+ }
+
+ public void useProjectSpecificSettings(boolean enable) {
+ boolean hasProjectSpecificOption= fDisabledProjectSettings == null;
+ if (enable != hasProjectSpecificOption && fProject != null) {
+ if (enable) {
+ for (int i= 0; i < fAllKeys.length; i++) {
+ Key curr= fAllKeys[i];
+ String val= (String) fDisabledProjectSettings.get(curr);
+ curr.setStoredValue(fLookupOrder[0], val, fManager);
+ }
+ fDisabledProjectSettings= null;
+ updateControls();
+ validateSettings(null, null, null);
+ } else {
+ fDisabledProjectSettings= new IdentityHashMap();
+ for (int i= 0; i < fAllKeys.length; i++) {
+ Key curr= fAllKeys[i];
+ String oldSetting= curr.getStoredValue(fLookupOrder, false, fManager);
+ fDisabledProjectSettings.put(curr, oldSetting);
+ curr.setStoredValue(fLookupOrder[0], null, fManager); // clear project settings
}
}
}
+ }
+
+ public boolean areSettingsEnabled() {
+ return fDisabledProjectSettings == null || fProject == null;
+ }
+
+
+ public boolean performOk() {
+ return processChanges(fContainer);
+ }
+
+ public boolean performApply() {
+ return processChanges(null); // apply directly
+ }
+
+ protected boolean processChanges(IWorkbenchPreferenceContainer container) {
+ IScopeContext currContext= fLookupOrder[0];
-
- if (hasChanges) {
- boolean doReParse = false;
- String[] strings = getFullReParseDialogStrings(fProject == null);
+ List /* scanXXX
methods will decide whether
@@ -401,6 +403,10 @@ public final class CHeuristicScanner implements Symbols {
return TokenLESSTHAN;
case RANGLE:
return TokenGREATERTHAN;
+ case DOT:
+ return TokenDOT;
+ case MINUS:
+ return TokenMINUS;
}
// else
@@ -551,13 +557,31 @@ public final class CHeuristicScanner implements Symbols {
* @return the matching peer character position, or NOT_FOUND
*/
public int findOpeningPeer(int start, char openingPeer, char closingPeer) {
+ return findOpeningPeer(start, CHeuristicScanner.UNBOUND, openingPeer, closingPeer);
+ }
+
+ /**
+ * Returns the position of the opening peer character (backward search). Any scopes introduced by closing peers
+ * are skipped. All peers accounted for must reside in the default partition.
+ *
+ * start
must not point to the closing peer, but to the first
+ * character being searched.NOT_FOUND
+ */
+ public int findOpeningPeer(int start, int bound, char openingPeer, char closingPeer) {
Assert.isLegal(start < fDocument.getLength());
try {
+ final CharacterMatch match= new CharacterMatch(new char[] {openingPeer, closingPeer});
int depth= 1;
start += 1;
while (true) {
- start= scanBackward(start - 1, UNBOUND, new CharacterMatch(new char[] {openingPeer, closingPeer}));
+ start= scanBackward(start - 1, bound, match);
if (start == NOT_FOUND)
return NOT_FOUND;
@@ -587,7 +611,7 @@ public final class CHeuristicScanner implements Symbols {
if (offset < 1 || offset >= fDocument.getLength())
return null;
- int begin= findOpeningPeer(offset - 1, LBRACE, RBRACE);
+ int begin= findOpeningPeer(offset - 1, CHeuristicScanner.UNBOUND, LBRACE, RBRACE);
int end= findClosingPeer(offset, LBRACE, RBRACE);
if (begin == NOT_FOUND || end == NOT_FOUND)
return null;
@@ -821,7 +845,7 @@ public final class CHeuristicScanner implements Symbols {
case TokenELSE:
return true;
case TokenRPAREN:
- position= findOpeningPeer(fPos, LPAREN, RPAREN);
+ position= findOpeningPeer(fPos, CHeuristicScanner.UNBOUND, LPAREN, RPAREN);
if (position > 0) {
switch (previousToken(position - 1, bound)) {
case TokenIF:
@@ -880,4 +904,31 @@ public final class CHeuristicScanner implements Symbols {
}
return false;
}
+
+ /**
+ * Returns true
if the document, when scanned backwards from start
+ * appears to contain a field reference, i.e. a (optional) name preceded by a .
or ->
+ * The start
must be before the operator.
+ *
+ * @param start the position after the field reference operator.
+ * @param bound the first position in fDocument
to not consider any more, with
+ * bound
< start
, or UNBOUND
+ * @return true
if the current position looks like a field reference
+ */
+ public boolean looksLikeFieldReferenceBackward(int start, int bound) {
+ int token= previousToken(start - 1, bound);
+ if (token == Symbols.TokenIDENT) { // field name
+ token= previousToken(getPosition(), bound);
+ }
+ if (token == Symbols.TokenDOT) {
+ return true;
+ }
+ if (token == Symbols.TokenGREATERTHAN) {
+ token= previousToken(getPosition(), bound);
+ if (token == Symbols.TokenMINUS) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java
index 7f57b91b7d2..9017b18fb24 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java
@@ -81,9 +81,8 @@ import org.eclipse.cdt.internal.ui.editor.CDocumentProvider;
import org.eclipse.cdt.internal.ui.editor.CElementHyperlinkDetector;
import org.eclipse.cdt.internal.ui.text.c.hover.CEditorTextHoverDescriptor;
import org.eclipse.cdt.internal.ui.text.c.hover.CEditorTextHoverProxy;
-import org.eclipse.cdt.internal.ui.text.contentassist.CCompletionProcessor2;
+import org.eclipse.cdt.internal.ui.text.contentassist.CContentAssistProcessor;
import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference;
-import org.eclipse.cdt.internal.ui.text.template.CTemplateCompletionProcessor;
import org.eclipse.cdt.internal.ui.util.ExternalEditorInput;
@@ -346,10 +345,21 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
assistant.setRestoreCompletionProposalSize(getSettings("completion_proposal_size")); //$NON-NLS-1$
- IContentAssistProcessor processor = new CCompletionProcessor2(getEditor());
+ IContentAssistProcessor processor = new CContentAssistProcessor(getEditor(), assistant, IDocument.DEFAULT_CONTENT_TYPE);
assistant.setContentAssistProcessor(processor, IDocument.DEFAULT_CONTENT_TYPE);
- assistant.setContentAssistProcessor(new CTemplateCompletionProcessor(getEditor()), ICPartitions.C_MULTI_LINE_COMMENT);
+ processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_MULTI_LINE_COMMENT);
+ assistant.setContentAssistProcessor(processor, ICPartitions.C_MULTI_LINE_COMMENT);
+
+ processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_SINGLE_LINE_COMMENT);
+ assistant.setContentAssistProcessor(processor, ICPartitions.C_SINGLE_LINE_COMMENT);
+
+ processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_STRING);
+ assistant.setContentAssistProcessor(processor, ICPartitions.C_STRING);
+
+ processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_PREPROCESSOR);
+ assistant.setContentAssistProcessor(processor, ICPartitions.C_PREPROCESSOR);
+
ContentAssistPreference.configure(assistant, fPreferenceStore);
assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY);
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/Symbols.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/Symbols.java
index 1d0f899aee0..6dc62e2a1ea 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/Symbols.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/Symbols.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation 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
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Sergey Prigogin, Google
+ * Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text;
@@ -30,6 +31,8 @@ public interface Symbols {
int TokenEQUAL= 12;
int TokenLESSTHAN= 13;
int TokenGREATERTHAN= 14;
+ int TokenDOT= 15;
+ int TokenMINUS= 16;
int TokenIF= 109;
int TokenDO= 1010;
int TokenFOR= 1011;
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistInvocationContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistInvocationContext.java
new file mode 100644
index 00000000000..9f5de95c1d7
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistInvocationContext.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.text.contentassist;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.ui.IEditorPart;
+
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
+
+
+/**
+ * Describes the context of a content assist invocation in a C/C++ editor.
+ * document
+ */
+ public CContentAssistInvocationContext(ITranslationUnit unit) {
+ super();
+ fTU= unit;
+ fTUComputed= true;
+ fEditor= null;
+ }
+
+ /**
+ * Returns the translation unit that content assist is invoked in, null
if there
+ * is none.
+ *
+ * @return the translation unit that content assist is invoked in, possibly null
+ */
+ public ITranslationUnit getTranslationUnit() {
+ if (!fTUComputed) {
+ fTUComputed= true;
+ fTU= CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput());
+ }
+ return fTU;
+ }
+
+ /**
+ * Returns the project of the translation unit that content assist is invoked in,
+ * null
if none.
+ *
+ * @return the current C project, possibly null
+ */
+ public ICProject getProject() {
+ ITranslationUnit unit= getTranslationUnit();
+ return unit == null ? null : unit.getCProject();
+ }
+
+ /**
+ * Get the editor content assist is invoked in.
+ *
+ * @return the editor, may be null
+ */
+ public IEditorPart getEditor() {
+ return fEditor;
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistProcessor.java
new file mode 100644
index 00000000000..ed32238f6d4
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistProcessor.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.text.contentassist;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.ui.IEditorPart;
+
+import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
+
+import org.eclipse.cdt.internal.ui.text.CParameterListValidator;
+
+/**
+ * C/C++ content assist processor.
+ */
+public class CContentAssistProcessor extends ContentAssistProcessor {
+
+ private IContextInformationValidator fValidator;
+ private final IEditorPart fEditor;
+
+ public CContentAssistProcessor(IEditorPart editor, ContentAssistant assistant, String partition) {
+ super(assistant, partition);
+ fEditor= editor;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
+ */
+ public IContextInformationValidator getContextInformationValidator() {
+ if (fValidator == null) {
+ fValidator= new CParameterListValidator();
+ }
+ return fValidator;
+ }
+
+ /*
+ * @see org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistProcessor#filterAndSort(java.util.List, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected List filterAndSortProposals(List proposals, IProgressMonitor monitor, ContentAssistInvocationContext context) {
+ return proposals;
+ }
+
+ /*
+ * @see org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistProcessor#createContext(org.eclipse.jface.text.ITextViewer, int)
+ */
+ protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset) {
+ return new CContentAssistInvocationContext(viewer, offset, fEditor);
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CompletionProposalCategory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CompletionProposalCategory.java
new file mode 100644
index 00000000000..fdf661e2389
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CompletionProposalCategory.java
@@ -0,0 +1,331 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.text.contentassist;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.InvalidRegistryObjectException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.action.LegacyActionTools;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.osgi.framework.Bundle;
+
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
+import org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer;
+
+import org.eclipse.cdt.internal.ui.util.Messages;
+
+/**
+ * Describes a category extension to the "completionProposalComputer" extension point.
+ *
+ * @since 4.0
+ */
+public final class CompletionProposalCategory {
+ /** The extension schema name of the icon attribute. */
+ private static final String ICON= "icon"; //$NON-NLS-1$
+
+ private final String fId;
+ private final String fName;
+ private final IConfigurationElement fElement;
+ /** The image descriptor for this category, or null
if none specified. */
+ private final ImageDescriptor fImage;
+
+ private boolean fIsSeparateCommand= true;
+ private boolean fIsEnabled= true;
+ private boolean fIsIncluded= true;
+ private final CompletionProposalComputerRegistry fRegistry;
+
+ private int fSortOrder= 0x10000;
+ private String fLastError= null;
+
+ CompletionProposalCategory(IConfigurationElement element, CompletionProposalComputerRegistry registry) {
+ fElement= element;
+ fRegistry= registry;
+ IExtension parent= (IExtension) element.getParent();
+ fId= parent.getUniqueIdentifier();
+ checkNotNull(fId, "id"); //$NON-NLS-1$
+ String name= parent.getLabel();
+ if (name == null)
+ fName= fId;
+ else
+ fName= name;
+
+ String icon= element.getAttribute(ICON);
+ ImageDescriptor img= null;
+ if (icon != null) {
+ Bundle bundle= getBundle();
+ if (bundle != null) {
+ Path path= new Path(icon);
+ URL url= FileLocator.find(bundle, path, null);
+ img= ImageDescriptor.createFromURL(url);
+ }
+ }
+ fImage= img;
+
+ }
+
+ CompletionProposalCategory(String id, String name, CompletionProposalComputerRegistry registry) {
+ fRegistry= registry;
+ fId= id;
+ fName= name;
+ fElement= null;
+ fImage= null;
+ }
+
+ private Bundle getBundle() {
+ String namespace= fElement.getDeclaringExtension().getContributor().getName();
+ Bundle bundle= Platform.getBundle(namespace);
+ return bundle;
+ }
+
+ /**
+ * Checks an element that must be defined according to the extension
+ * point schema. Throws an
+ * InvalidRegistryObjectException
if obj
+ * is null
.
+ */
+ private void checkNotNull(Object obj, String attribute) throws InvalidRegistryObjectException {
+ if (obj == null) {
+ Object[] args= { getId(), fElement.getContributor().getName(), attribute };
+ String message= Messages.format(ContentAssistMessages.CompletionProposalComputerDescriptor_illegal_attribute_message, args);
+ IStatus status= new Status(IStatus.WARNING, CUIPlugin.getPluginId(), IStatus.OK, message, null);
+ CUIPlugin.getDefault().log(status);
+ throw new InvalidRegistryObjectException();
+ }
+ }
+
+ /**
+ * Returns the identifier of the described extension.
+ *
+ * @return Returns the id
+ */
+ public String getId() {
+ return fId;
+ }
+
+ /**
+ * Returns the name of the described extension.
+ *
+ * @return Returns the name
+ */
+ public String getName() {
+ return fName;
+ }
+
+ /**
+ * Returns the name of the described extension
+ * without mnemonic hint in order to be displayed
+ * in a message.
+ *
+ * @return Returns the name
+ */
+ public String getDisplayName() {
+ return LegacyActionTools.removeMnemonics(fName);
+ }
+
+ /**
+ * Returns the image descriptor of the described category.
+ *
+ * @return the image descriptor of the described category
+ */
+ public ImageDescriptor getImageDescriptor() {
+ return fImage;
+ }
+
+ /**
+ * Sets the separate command state of the category.
+ *
+ * @param enabled the new enabled state.
+ */
+ public void setSeparateCommand(boolean enabled) {
+ fIsSeparateCommand= enabled;
+ }
+
+ /**
+ * Returns the enablement state of the category.
+ *
+ * @return the enablement state of the category
+ */
+ public boolean isSeparateCommand() {
+ return fIsSeparateCommand;
+ }
+
+ /**
+ * @param included the included
+ */
+ public void setIncluded(boolean included) {
+ fIsIncluded= included;
+ }
+
+ /**
+ * @return included
+ */
+ public boolean isIncluded() {
+ return fIsIncluded;
+ }
+
+ public boolean isEnabled() {
+ return fIsEnabled;
+ }
+
+ public void setEnabled(boolean isEnabled) {
+ fIsEnabled= isEnabled;
+ }
+
+ /**
+ * Returns true
if the category contains any computers, false
+ * otherwise.
+ *
+ * @return true
if the category contains any computers, false
+ * otherwise
+ */
+ public boolean hasComputers() {
+ List descriptors= fRegistry.getProposalComputerDescriptors();
+ for (Iterator it= descriptors.iterator(); it.hasNext();) {
+ CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
+ if (desc.getCategory() == this)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true
if the category contains any computers in the given partition, false
+ * otherwise.
+ *
+ * @param partition the partition
+ * @return true
if the category contains any computers, false
+ * otherwise
+ */
+ public boolean hasComputers(String partition) {
+ List descriptors= fRegistry.getProposalComputerDescriptors(partition);
+ for (Iterator it= descriptors.iterator(); it.hasNext();) {
+ CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
+ if (desc.getCategory() == this)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @return sortOrder
+ */
+ public int getSortOrder() {
+ return fSortOrder;
+ }
+
+ /**
+ * @param sortOrder the sortOrder
+ */
+ public void setSortOrder(int sortOrder) {
+ fSortOrder= sortOrder;
+ }
+
+ /**
+ * Safely computes completion proposals of all computers of this category through their
+ * extension. If an extension is disabled, throws an exception or otherwise does not adhere to
+ * the contract described in {@link ICompletionProposalComputer}, it is disabled.
+ *
+ * @param context the invocation context passed on to the extension
+ * @param partition the partition type where to invocation occurred
+ * @param monitor the progress monitor passed on to the extension
+ * @return the list of computed completion proposals (element type:
+ * {@link org.eclipse.jface.text.contentassist.ICompletionProposal})
+ */
+ public List computeCompletionProposals(ContentAssistInvocationContext context, String partition, SubProgressMonitor monitor) {
+ fLastError= null;
+ List result= new ArrayList();
+ List descriptors= new ArrayList(fRegistry.getProposalComputerDescriptors(partition));
+ for (Iterator it= descriptors.iterator(); it.hasNext();) {
+ CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
+ if (desc.getCategory() == this)
+ result.addAll(desc.computeCompletionProposals(context, monitor));
+ if (fLastError == null)
+ fLastError= desc.getErrorMessage();
+ }
+ return result;
+ }
+
+ /**
+ * Safely computes context information objects of all computers of this category through their
+ * extension. If an extension is disabled, throws an exception or otherwise does not adhere to
+ * the contract described in {@link ICompletionProposalComputer}, it is disabled.
+ *
+ * @param context the invocation context passed on to the extension
+ * @param partition the partition type where to invocation occurred
+ * @param monitor the progress monitor passed on to the extension
+ * @return the list of computed context information objects (element type:
+ * {@link org.eclipse.jface.text.contentassist.IContextInformation})
+ */
+ public List computeContextInformation(ContentAssistInvocationContext context, String partition, SubProgressMonitor monitor) {
+ fLastError= null;
+ List result= new ArrayList();
+ List descriptors= new ArrayList(fRegistry.getProposalComputerDescriptors(partition));
+ for (Iterator it= descriptors.iterator(); it.hasNext();) {
+ CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
+ if (desc.getCategory() == this)
+ result.addAll(desc.computeContextInformation(context, monitor));
+ if (fLastError == null)
+ fLastError= desc.getErrorMessage();
+ }
+ return result;
+ }
+
+ /**
+ * Returns the error message from the computers in this category.
+ *
+ * @return the error message from the computers in this category
+ */
+ public String getErrorMessage() {
+ return fLastError;
+ }
+
+ /**
+ * Notifies the computers in this category of a proposal computation session start.
+ */
+ public void sessionStarted() {
+ List descriptors= new ArrayList(fRegistry.getProposalComputerDescriptors());
+ for (Iterator it= descriptors.iterator(); it.hasNext();) {
+ CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
+ if (desc.getCategory() == this)
+ desc.sessionStarted();
+ if (fLastError == null)
+ fLastError= desc.getErrorMessage();
+ }
+ }
+
+ /**
+ * Notifies the computers in this category of a proposal computation session end.
+ */
+ public void sessionEnded() {
+ List descriptors= new ArrayList(fRegistry.getProposalComputerDescriptors());
+ for (Iterator it= descriptors.iterator(); it.hasNext();) {
+ CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
+ if (desc.getCategory() == this)
+ desc.sessionEnded();
+ if (fLastError == null)
+ fLastError= desc.getErrorMessage();
+ }
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CompletionProposalComputerDescriptor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CompletionProposalComputerDescriptor.java
new file mode 100644
index 00000000000..d0e66d604ae
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CompletionProposalComputerDescriptor.java
@@ -0,0 +1,550 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.text.contentassist;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IContributor;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.InvalidRegistryObjectException;
+import org.eclipse.core.runtime.PerformanceStats;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+
+import org.eclipse.jface.text.IDocument;
+
+import org.osgi.framework.Bundle;
+
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.ui.text.ICPartitions;
+import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
+import org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer;
+
+import org.eclipse.cdt.internal.ui.util.Messages;
+
+/**
+ * The description of an extension to the
+ * org.eclipse.cdt.ui.completionProposalComputer
extension point. Instances are
+ * immutable. Instances can be obtained from a {@link CompletionProposalComputerRegistry}.
+ *
+ * @see CompletionProposalComputerRegistry
+ * @since 4.0
+ */
+final class CompletionProposalComputerDescriptor {
+ /** The default category id. */
+ private static final String DEFAULT_CATEGORY_ID= "org.eclipse.cdt.ui.defaultProposalCategory"; //$NON-NLS-1$
+ /** The extension schema name of the category id attribute. */
+ private static final String CATEGORY_ID= "categoryId"; //$NON-NLS-1$
+ /** The extension schema name of the partition type attribute. */
+ private static final String TYPE= "type"; //$NON-NLS-1$
+ /** The extension schema name of the class attribute. */
+ private static final String CLASS= "class"; //$NON-NLS-1$
+ /** The extension schema name of the activate attribute. */
+ private static final String ACTIVATE= "activate"; //$NON-NLS-1$
+ /** The extension schema name of the partition child elements. */
+ private static final String PARTITION= "partition"; //$NON-NLS-1$
+ /** Set of Java partition types. */
+ private static final Set PARTITION_SET;
+ /** The name of the performance event used to trace extensions. */
+ private static final String PERFORMANCE_EVENT= CUIPlugin.getPluginId() + "/perf/content_assist/extensions"; //$NON-NLS-1$
+ /**
+ * If true
, execution time of extensions is measured and the data forwarded to
+ * core's {@link PerformanceStats} service.
+ */
+ private static final boolean MEASURE_PERFORMANCE= PerformanceStats.isEnabled(PERFORMANCE_EVENT);
+ /**
+ * Independently of the {@link PerformanceStats} service, any operation that takes longer than
+ * {@value} milliseconds will be flagged as an violation. This timeout does not apply to the
+ * first invocation, as it may take longer due to plug-in initialization etc. See also
+ * {@link #fIsReportingDelay}.
+ */
+ private static final long MAX_DELAY= 5000;
+
+ /* log constants */
+ private static final String COMPUTE_COMPLETION_PROPOSALS= "computeCompletionProposals()"; //$NON-NLS-1$
+ private static final String COMPUTE_CONTEXT_INFORMATION= "computeContextInformation()"; //$NON-NLS-1$
+ private static final String SESSION_STARTED= "sessionStarted()"; //$NON-NLS-1$
+ private static final String SESSION_ENDED= "sessionEnded()"; //$NON-NLS-1$
+
+ static {
+ Set partitions= new HashSet();
+ partitions.add(IDocument.DEFAULT_CONTENT_TYPE);
+ partitions.add(ICPartitions.C_PREPROCESSOR);
+ partitions.add(ICPartitions.C_MULTI_LINE_COMMENT);
+ partitions.add(ICPartitions.C_SINGLE_LINE_COMMENT);
+ partitions.add(ICPartitions.C_STRING);
+ partitions.add(ICPartitions.C_CHARACTER);
+
+ PARTITION_SET= Collections.unmodifiableSet(partitions);
+ }
+
+ /** The identifier of the extension. */
+ private final String fId;
+ /** The name of the extension. */
+ private final String fName;
+ /** The class name of the provided IJavaCompletionProposalComputer
. */
+ private final String fClass;
+ /** The activate attribute value. */
+ private final boolean fActivate;
+ /** The partition of the extension (element type: {@link String}). */
+ private final Set fPartitions;
+ /** The configuration element of this extension. */
+ private final IConfigurationElement fElement;
+ /** The registry we are registered with. */
+ private final CompletionProposalComputerRegistry fRegistry;
+ /** The computer, if instantiated, null
otherwise. */
+ private ICompletionProposalComputer fComputer;
+ /** The ui category. */
+ private final CompletionProposalCategory fCategory;
+ /** The first error message in the most recent operation, or null
. */
+ private String fLastError;
+ /**
+ * Tells whether to inform the user when MAX_DELAY
has been exceeded.
+ * We start timing execution after the first session because the first may take
+ * longer due to plug-in activation and initialization.
+ */
+ private boolean fIsReportingDelay= false;
+ /** The start of the last operation. */
+ private long fStart;
+
+ /**
+ * Creates a new descriptor.
+ *
+ * @param element the configuration element to read
+ * @param registry the computer registry creating this descriptor
+ */
+ CompletionProposalComputerDescriptor(IConfigurationElement element, CompletionProposalComputerRegistry registry, List categories) throws InvalidRegistryObjectException {
+ Assert.isLegal(registry != null);
+ Assert.isLegal(element != null);
+
+ fRegistry= registry;
+ fElement= element;
+ IExtension extension= element.getDeclaringExtension();
+ fId= extension.getUniqueIdentifier();
+ checkNotNull(fId, "id"); //$NON-NLS-1$
+
+ String name= extension.getLabel();
+ if (name.length() == 0)
+ fName= fId;
+ else
+ fName= name;
+
+ Set partitions= new HashSet();
+ IConfigurationElement[] children= element.getChildren(PARTITION);
+ if (children.length == 0) {
+ fPartitions= PARTITION_SET; // add to all partition types if no partition is configured
+ } else {
+ for (int i= 0; i < children.length; i++) {
+ String type= children[i].getAttribute(TYPE);
+ checkNotNull(type, TYPE);
+ partitions.add(type);
+ }
+ fPartitions= Collections.unmodifiableSet(partitions);
+ }
+
+ String activateAttribute= element.getAttribute(ACTIVATE);
+ fActivate= Boolean.valueOf(activateAttribute).booleanValue();
+
+ fClass= element.getAttribute(CLASS);
+ checkNotNull(fClass, CLASS);
+
+ String categoryId= element.getAttribute(CATEGORY_ID);
+ if (categoryId == null)
+ categoryId= DEFAULT_CATEGORY_ID;
+ CompletionProposalCategory category= null;
+ for (Iterator it= categories.iterator(); it.hasNext();) {
+ CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
+ if (cat.getId().equals(categoryId)) {
+ category= cat;
+ break;
+ }
+ }
+ if (category == null) {
+ // create a category if it does not exist
+ fCategory= new CompletionProposalCategory(categoryId, fName, registry);
+ categories.add(fCategory);
+ } else {
+ fCategory= category;
+ }
+ }
+
+ /**
+ * Checks an element that must be defined according to the extension
+ * point schema. Throws an
+ * InvalidRegistryObjectException
if obj
+ * is null
.
+ */
+ private void checkNotNull(Object obj, String attribute) throws InvalidRegistryObjectException {
+ if (obj == null) {
+ Object[] args= { getId(), fElement.getContributor().getName(), attribute };
+ String message= Messages.format(ContentAssistMessages.CompletionProposalComputerDescriptor_illegal_attribute_message, args);
+ IStatus status= new Status(IStatus.WARNING, CUIPlugin.getPluginId(), IStatus.OK, message, null);
+ CUIPlugin.getDefault().log(status);
+ throw new InvalidRegistryObjectException();
+ }
+ }
+
+ /**
+ * Returns the identifier of the described extension.
+ *
+ * @return Returns the id
+ */
+ public String getId() {
+ return fId;
+ }
+
+ /**
+ * Returns the name of the described extension.
+ *
+ * @return Returns the name
+ */
+ public String getName() {
+ return fName;
+ }
+
+ /**
+ * Returns the partition types of the described extension.
+ *
+ * @return the set of partition types (element type: {@link String})
+ */
+ public Set getPartitions() {
+ return fPartitions;
+ }
+
+ /**
+ * Returns a cached instance of the computer as described in the
+ * extension's xml. The computer is
+ * {@link #createComputer() created} the first time that this method
+ * is called and then cached.
+ *
+ * @return a new instance of the completion proposal computer as
+ * described by this descriptor
+ * @throws CoreException if the creation fails
+ * @throws InvalidRegistryObjectException if the extension is not
+ * valid any longer (e.g. due to plug-in unloading)
+ */
+ private synchronized ICompletionProposalComputer getComputer() throws CoreException, InvalidRegistryObjectException {
+ if (fComputer == null && (fActivate || isPluginLoaded()))
+ fComputer= createComputer();
+ return fComputer;
+ }
+
+ private boolean isPluginLoaded() {
+ Bundle bundle= getBundle();
+ return bundle != null && bundle.getState() == Bundle.ACTIVE;
+ }
+
+ private Bundle getBundle() {
+ String namespace= fElement.getDeclaringExtension().getContributor().getName();
+ Bundle bundle= Platform.getBundle(namespace);
+ return bundle;
+ }
+
+ /**
+ * Returns a new instance of the computer as described in the
+ * extension's xml. Note that the safest way to access the computer
+ * is by using the {@linkplain #computeCompletionProposals}
+ * and {@linkplain #computeContextInformation}
+ * methods. These delegate the functionality to the contributed
+ * computer, but handle instance creation and any exceptions thrown.
+ *
+ * @return a new instance of the completion proposal computer as
+ * described by this descriptor
+ * @throws CoreException if the creation fails
+ * @throws InvalidRegistryObjectException if the extension is not
+ * valid any longer (e.g. due to plug-in unloading)
+ */
+ public ICompletionProposalComputer createComputer() throws CoreException, InvalidRegistryObjectException {
+ return (ICompletionProposalComputer) fElement.createExecutableExtension(CLASS);
+ }
+
+ /**
+ * Safely computes completion proposals through the described extension. If the extension
+ * is disabled, throws an exception or otherwise does not adhere to the contract described in
+ * {@link ICompletionProposalComputer}, an empty list is returned.
+ *
+ * @param context the invocation context passed on to the extension
+ * @param monitor the progress monitor passed on to the extension
+ * @return the list of computed completion proposals (element type:
+ * {@link org.eclipse.jface.text.contentassist.ICompletionProposal})
+ */
+ public List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) {
+ if (!isEnabled())
+ return Collections.EMPTY_LIST;
+
+ IStatus status;
+ try {
+ ICompletionProposalComputer computer= getComputer();
+ if (computer == null) // not active yet
+ return Collections.EMPTY_LIST;
+
+ try {
+ PerformanceStats stats= startMeter(context, computer);
+ List proposals= computer.computeCompletionProposals(context, monitor);
+ stopMeter(stats, COMPUTE_COMPLETION_PROPOSALS);
+
+ if (proposals != null) {
+ fLastError= computer.getErrorMessage();
+ return proposals;
+ }
+ } finally {
+ fIsReportingDelay= true;
+ }
+ status= createAPIViolationStatus(COMPUTE_COMPLETION_PROPOSALS);
+ } catch (InvalidRegistryObjectException x) {
+ status= createExceptionStatus(x);
+ } catch (CoreException x) {
+ status= createExceptionStatus(x);
+ } catch (RuntimeException x) {
+ status= createExceptionStatus(x);
+ } finally {
+ monitor.done();
+ }
+
+ fRegistry.informUser(this, status);
+
+ return Collections.EMPTY_LIST;
+ }
+
+ /**
+ * Safely computes context information objects through the described extension. If the extension
+ * is disabled, throws an exception or otherwise does not adhere to the contract described in
+ * {@link ICompletionProposalComputer}, an empty list is returned.
+ *
+ * @param context the invocation context passed on to the extension
+ * @param monitor the progress monitor passed on to the extension
+ * @return the list of computed context information objects (element type:
+ * {@link org.eclipse.jface.text.contentassist.IContextInformation})
+ */
+ public List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) {
+ if (!isEnabled())
+ return Collections.EMPTY_LIST;
+
+ IStatus status;
+ try {
+ ICompletionProposalComputer computer= getComputer();
+ if (computer == null) // not active yet
+ return Collections.EMPTY_LIST;
+
+ PerformanceStats stats= startMeter(context, computer);
+ List proposals= computer.computeContextInformation(context, monitor);
+ stopMeter(stats, COMPUTE_CONTEXT_INFORMATION);
+
+ if (proposals != null) {
+ fLastError= computer.getErrorMessage();
+ return proposals;
+ }
+
+ status= createAPIViolationStatus(COMPUTE_CONTEXT_INFORMATION);
+ } catch (InvalidRegistryObjectException x) {
+ status= createExceptionStatus(x);
+ } catch (CoreException x) {
+ status= createExceptionStatus(x);
+ } catch (RuntimeException x) {
+ status= createExceptionStatus(x);
+ } finally {
+ monitor.done();
+ }
+
+ fRegistry.informUser(this, status);
+
+ return Collections.EMPTY_LIST;
+ }
+
+
+ /**
+ * Notifies the described extension of a proposal computation session start.
+ * org.eclipse.cdt.ui.completionProposalComputer
+ * extension point.
+ *
+ * @since 4.0
+ */
+public final class CompletionProposalComputerRegistry {
+
+ private static final String EXTENSION_POINT= "completionProposalComputer"; //$NON-NLS-1$
+
+ /** The singleton instance. */
+ private static CompletionProposalComputerRegistry fgSingleton= null;
+
+ /**
+ * Returns the default computer registry.
+ * fDescriptorsByPartition
(key type: {@link String},
+ * value type:
+ * {@linkplain List List<CompletionProposalComputerDescriptor>}).
+ */
+ private final Map fPublicDescriptorsByPartition= new HashMap();
+ /**
+ * All descriptors (element type:
+ * {@link CompletionProposalComputerDescriptor}).
+ */
+ private final List fDescriptors= new ArrayList();
+ /**
+ * Unmodifiable view of fDescriptors
+ */
+ private final List fPublicDescriptors= Collections.unmodifiableList(fDescriptors);
+
+ private final List fCategories= new ArrayList();
+ private final List fPublicCategories= Collections.unmodifiableList(fCategories);
+ /**
+ * true
if this registry has been loaded.
+ */
+ private boolean fLoaded= false;
+
+ /**
+ * Creates a new instance.
+ */
+ public CompletionProposalComputerRegistry() {
+ }
+
+ /**
+ * Returns the list of {@link CompletionProposalComputerDescriptor}s describing all extensions
+ * to the javaCompletionProposalComputer
extension point for the given partition
+ * type.
+ * javaCompletionProposalComputer
extension
+ * point (element type: {@link CompletionProposalComputerDescriptor})
+ */
+ List getProposalComputerDescriptors(String partition) {
+ ensureExtensionPointRead();
+ List result= (List) fPublicDescriptorsByPartition.get(partition);
+ return result != null ? result : Collections.EMPTY_LIST;
+ }
+
+ /**
+ * Returns the list of {@link CompletionProposalComputerDescriptor}s describing all extensions
+ * to the javaCompletionProposalComputer
extension point.
+ * javaCompletionProposalComputer
extension
+ * point (element type: {@link CompletionProposalComputerDescriptor})
+ */
+ List getProposalComputerDescriptors() {
+ ensureExtensionPointRead();
+ return fPublicDescriptors;
+ }
+
+ /**
+ * Returns the list of proposal categories contributed to the
+ * javaCompletionProposalComputer
extension point.
+ * javaCompletionProposalComputer
extension point (element type:
+ * {@link CompletionProposalCategory})
+ */
+ public List getProposalCategories() {
+ ensureExtensionPointRead();
+ return fPublicCategories;
+ }
+
+ /**
+ * Ensures that the extensions are read and stored in
+ * fDescriptorsByPartition
.
+ */
+ private void ensureExtensionPointRead() {
+ boolean reload;
+ synchronized (this) {
+ reload= !fLoaded;
+ fLoaded= true;
+ }
+ if (reload)
+ reload();
+ }
+
+ /**
+ * Reloads the extensions to the extension point.
+ * culprit
that contribute to category
(element type: {@link String})
+ */
+ private Set getAffectedContributors(CompletionProposalCategory category, IContributor culprit) {
+ Set affectedPlugins= new HashSet();
+ for (Iterator it= getProposalComputerDescriptors().iterator(); it.hasNext();) {
+ CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
+ CompletionProposalCategory cat= desc.getCategory();
+ if (cat.equals(category)) {
+ IContributor contributor= desc.getContributor();
+ if (contributor != null && !culprit.equals(contributor))
+ affectedPlugins.add(contributor.getName());
+ }
+ }
+ return affectedPlugins;
+ }
+
+ private Object toString(Collection collection) {
+ // strip brackets off AbstractCollection.toString()
+ String string= collection.toString();
+ return string.substring(1, string.length() - 1);
+ }
+
+ private void informUser(IStatus status) {
+ CUIPlugin.getDefault().log(status);
+ String title= ContentAssistMessages.CompletionProposalComputerRegistry_error_dialog_title;
+ String message= status.getMessage();
+ MessageDialog.openError(CUIPlugin.getActiveWorkbenchShell(), title, message);
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistComputerParameter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistComputerParameter.java
new file mode 100644
index 00000000000..5a016ab9c22
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistComputerParameter.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.text.contentassist;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.commands.IParameterValues;
+
+/**
+ * Map of parameters for the specific content assist command.
+ *
+ * @since 4.0
+ */
+public final class ContentAssistComputerParameter implements IParameterValues {
+ /*
+ * @see org.eclipse.core.commands.IParameterValues#getParameterValues()
+ */
+ public Map getParameterValues() {
+ Collection descriptors= CompletionProposalComputerRegistry.getDefault().getProposalCategories();
+ Map map= new HashMap(descriptors.size());
+ for (Iterator it= descriptors.iterator(); it.hasNext();) {
+ CompletionProposalCategory category= (CompletionProposalCategory) it.next();
+ map.put(category.getDisplayName(), category.getId());
+ }
+ return map;
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistHandler.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistHandler.java
new file mode 100644
index 00000000000..7f0811e9daa
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistHandler.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.text.contentassist;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+import org.eclipse.cdt.internal.ui.editor.SpecificContentAssistExecutor;
+
+/**
+ * A command handler to invoke a content assist for a specific proposal category.
+ *
+ * @since 4.0
+ */
+public final class ContentAssistHandler extends AbstractHandler {
+ private final SpecificContentAssistExecutor fExecutor= new SpecificContentAssistExecutor(CompletionProposalComputerRegistry.getDefault());
+
+ public ContentAssistHandler() {
+ }
+
+ /*
+ * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
+ */
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ITextEditor editor= getActiveEditor();
+ if (editor == null)
+ return null;
+
+ String categoryId= event.getParameter("org.eclipse.cdt.ui.specific_content_assist.category_id"); //$NON-NLS-1$
+ if (categoryId == null)
+ return null;
+
+ fExecutor.invokeContentAssist(editor, categoryId);
+
+ return null;
+ }
+
+ private ITextEditor getActiveEditor() {
+ IWorkbenchWindow window= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window != null) {
+ IWorkbenchPage page= window.getActivePage();
+ if (page != null) {
+ IEditorPart editor= page.getActiveEditor();
+ if (editor instanceof ITextEditor)
+ return (ITextEditor) editor;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistMessages.java
new file mode 100644
index 00000000000..f350e41cafb
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistMessages.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.text.contentassist;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Helper class to get NLSed messages.
+ */
+final class ContentAssistMessages extends NLS {
+
+ private static final String BUNDLE_NAME= ContentAssistMessages.class.getName();
+
+ private ContentAssistMessages() {
+ // Do not instantiate
+ }
+
+ public static String CompletionProposalComputerRegistry_messageAvoidanceHint;
+ public static String CompletionProposalComputerRegistry_messageAvoidanceHintWithWarning;
+ public static String ContentAssistProcessor_all_disabled_message;
+ public static String ContentAssistProcessor_all_disabled_preference_link;
+ public static String ContentAssistProcessor_all_disabled_title;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, ContentAssistMessages.class);
+ }
+
+ public static String ContentAssistProcessor_computing_proposals;
+ public static String ContentAssistProcessor_collecting_proposals;
+ public static String ContentAssistProcessor_sorting_proposals;
+ public static String ContentAssistProcessor_computing_contexts;
+ public static String ContentAssistProcessor_collecting_contexts;
+ public static String ContentAssistProcessor_sorting_contexts;
+ public static String CompletionProposalComputerDescriptor_illegal_attribute_message;
+ public static String CompletionProposalComputerDescriptor_reason_invalid;
+ public static String CompletionProposalComputerDescriptor_reason_instantiation;
+ public static String CompletionProposalComputerDescriptor_reason_runtime_ex;
+ public static String CompletionProposalComputerDescriptor_reason_API;
+ public static String CompletionProposalComputerDescriptor_reason_performance;
+ public static String CompletionProposalComputerDescriptor_blame_message;
+ public static String CompletionProposalComputerRegistry_invalid_message;
+ public static String CompletionProposalComputerRegistry_error_dialog_title;
+ public static String ContentAssistProcessor_defaultProposalCategory;
+ public static String ContentAssistProcessor_toggle_affordance_press_gesture;
+ public static String ContentAssistProcessor_toggle_affordance_click_gesture;
+ public static String ContentAssistProcessor_toggle_affordance_update_message;
+ public static String ContentAssistProcessor_empty_message;
+ public static String ContentAssistHistory_serialize_error;
+ public static String ContentAssistHistory_deserialize_error;
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistMessages.properties
new file mode 100644
index 00000000000..c9b7a6c2081
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistMessages.properties
@@ -0,0 +1,53 @@
+###############################################################################
+# Copyright (c) 2000, 2007 IBM Corporation 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:
+# IBM Corporation - initial API and implementation
+# Anton Leherbauer (Wind River Systems)
+###############################################################################
+
+CompletionProposalComputerRegistry_error_dialog_title=Problems During Content Assist
+# {0} is the plug-in id of the contributing plug-in, {1} the display name of the proposal category
+CompletionProposalComputerRegistry_messageAvoidanceHint=To avoid this message, disable the ''{0}'' plug-in or disable the ''{1}'' category on the content assist preference page.
+# {0} is the plug-in id of the contributing plug-in, {1} the display name of the proposal category, {2} the comma-separated list of plug-ins other than {0} the contribute to the category
+CompletionProposalComputerRegistry_messageAvoidanceHintWithWarning=To avoid this message, disable the ''{0}'' plug-in or disable the ''{1}'' category on the content assist preference page. Note that disabling the category will also affect completion proposals from the following plug-ins: {2}.
+# {0} is the extension id
+CompletionProposalComputerRegistry_invalid_message=The extension ''{0}'' has become invalid.
+
+CompletionProposalComputerDescriptor_reason_invalid=The extension has become invalid.
+CompletionProposalComputerDescriptor_reason_instantiation=Unable to instantiate the extension.
+CompletionProposalComputerDescriptor_reason_runtime_ex=The extension has thrown a runtime exception.
+# {0} specifies an operation name, e.g. "computeProposals"
+CompletionProposalComputerDescriptor_reason_API=The extension violated the API contract of the ''{0}'' operation.
+CompletionProposalComputerDescriptor_reason_performance=The extension took too long to return from the ''{0}'' operation.
+# {0} is the name of an extension, {1} the contributing plug-in name
+CompletionProposalComputerDescriptor_blame_message= The ''{0}'' proposal computer from the ''{1}'' plug-in did not complete normally.
+# {0} is the identifier of an extension, {1} the contributing plug-in, {2} a required but missing xml attribute
+CompletionProposalComputerDescriptor_illegal_attribute_message= The extension "{0}" from plug-in "{1}" did not specify a value for the required "{2}" attribute. Disabling the extension.
+
+ContentAssistProcessor_computing_proposals=Computing completion proposals
+ContentAssistProcessor_collecting_proposals=Collecting proposals
+ContentAssistProcessor_sorting_proposals=Sorting
+ContentAssistProcessor_computing_contexts=Computing context information
+ContentAssistProcessor_all_disabled_title=No Default Proposal Kinds
+ContentAssistProcessor_all_disabled_message=No proposal kinds are enabled for the 'default' content assist list.
+# {0} will be replaced by the label of the 'restore defaults' button
+# The preference page should match the title of the 'C/C++ > Editor > Content Assist > Advanced' preference page
+ContentAssistProcessor_all_disabled_preference_link=Change the settings on the Advanced Content Assist preference page or click ''{0}'' to restore the default behavior.
+ContentAssistProcessor_collecting_contexts=Collecting context information
+ContentAssistProcessor_sorting_contexts=Sorting
+ContentAssistProcessor_defaultProposalCategory=Default Proposals
+# {0} will be replaced by a keyboard shortcut (accelerator)
+ContentAssistProcessor_toggle_affordance_press_gesture=Press ''{0}''
+ContentAssistProcessor_toggle_affordance_click_gesture=Click
+# {0} will be replaced by a title describing the displayed proposal category, {1} by either the press_gesture or click_gesture message above, {2} by the name of the next proposal category
+ContentAssistProcessor_toggle_affordance_update_message={1} to show {2}
+# {0} will be replaced by a title describing the displayed proposal category
+ContentAssistProcessor_empty_message= No {0}
+
+ContentAssistHistory_serialize_error=Problems writing content assist history to XML
+ContentAssistHistory_deserialize_error=Problems reading content assist history from XML
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistPreference.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistPreference.java
index 44657226ead..ed680ef92d0 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistPreference.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistPreference.java
@@ -28,8 +28,8 @@ import org.eclipse.jface.util.PropertyChangeEvent;
public class ContentAssistPreference {
- /** Preference key for content assist auto activation */
- //public final static String AUTOACTIVATION= "content_assist_autoactivation";
+// /** Preference key for content assist auto activation (unused) */
+// public final static String AUTOACTIVATION= "content_assist_autoactivation";
/** Preference key for content assist auto activation delay */
public final static String AUTOACTIVATION_DELAY= "content_assist_autoactivation_delay"; //$NON-NLS-1$
/** Preference key for content assist timeout delay (unused) */
@@ -52,14 +52,14 @@ public class ContentAssistPreference {
public final static String AUTOACTIVATION_TRIGGERS_ARROW= "content_assist_autoactivation_trigger_arrow"; //$NON-NLS-1$
public final static String AUTOACTIVATION_TRIGGERS_DOUBLECOLON= "content_assist_autoactivation_trigger_doublecolon"; //$NON-NLS-1$
- /** Preference key for visibility of proposals (unused) */
- public final static String SHOW_DOCUMENTED_PROPOSALS= "content_assist_show_visible_proposals"; //$NON-NLS-1$
- /** Preference key for alphabetic ordering of proposals */
- public final static String ORDER_PROPOSALS= "content_assist_order_proposals"; //$NON-NLS-1$
- /** Preference key for case sensitivity of propsals */
- //public final static String CASE_SENSITIVITY= "content_assist_case_sensitivity";
- /** Preference key for adding includes on code assist (unused) */
- public final static String ADD_INCLUDE= "content_assist_add_import"; //$NON-NLS-1$
+// /** Preference key for visibility of proposals (unused) */
+// public final static String SHOW_DOCUMENTED_PROPOSALS= "content_assist_show_visible_proposals"; //$NON-NLS-1$
+// /** Preference key for alphabetic ordering of proposals (unused) */
+// public final static String ORDER_PROPOSALS= "content_assist_order_proposals"; //$NON-NLS-1$
+// /** Preference key for case sensitivity of propsals */
+// public final static String CASE_SENSITIVITY= "content_assist_case_sensitivity";
+// /** Preference key for adding includes on code assist (unused) */
+// public final static String ADD_INCLUDE= "content_assist_add_import"; //$NON-NLS-1$
/** Preference key for completion search scope (unused) */
public final static String CURRENT_FILE_SEARCH_SCOPE= "content_assist_current_file_search_scope"; //$NON-NLS-1$
/** Preference key for completion search scope (unused) */
@@ -77,16 +77,16 @@ public class ContentAssistPreference {
return getColor(store, key, textTools.getColorManager());
}
- private static CCompletionProcessor2 getCProcessor(ContentAssistant assistant) {
+ private static CContentAssistProcessor getCProcessor(ContentAssistant assistant) {
IContentAssistProcessor p= assistant.getContentAssistProcessor(IDocument.DEFAULT_CONTENT_TYPE);
- if (p instanceof CCompletionProcessor2)
- return (CCompletionProcessor2) p;
+ if (p instanceof CContentAssistProcessor)
+ return (CContentAssistProcessor) p;
return null;
}
private static void configureCProcessor(ContentAssistant assistant, IPreferenceStore store) {
- CCompletionProcessor2 jcp= getCProcessor(assistant);
- if (jcp == null)
+ CContentAssistProcessor ccp= getCProcessor(assistant);
+ if (ccp == null)
return;
String triggers = ""; //$NON-NLS-1$
@@ -99,19 +99,20 @@ public class ContentAssistPreference {
boolean useDoubleColonAsTrigger = store.getBoolean(AUTOACTIVATION_TRIGGERS_DOUBLECOLON);
if(useDoubleColonAsTrigger)
triggers += ":"; //$NON-NLS-1$
- jcp.setCompletionProposalAutoActivationCharacters(triggers.toCharArray());
+ ccp.setCompletionProposalAutoActivationCharacters(triggers.toCharArray());
- boolean enabled= store.getBoolean(SHOW_DOCUMENTED_PROPOSALS);
- //jcp.restrictProposalsToVisibility(enabled);
+// boolean enabled;
+// enabled= store.getBoolean(SHOW_DOCUMENTED_PROPOSALS);
+// ccp.restrictProposalsToVisibility(enabled);
+//
+// enabled= store.getBoolean(CASE_SENSITIVITY);
+// ccp.restrictProposalsToMatchingCases(enabled);
- //enabled= store.getBoolean(CASE_SENSITIVITY);
- //jcp.restrictProposalsToMatchingCases(enabled);
+// enabled= store.getBoolean(ORDER_PROPOSALS);
+// ccp.orderProposalsAlphabetically(enabled);
- enabled= store.getBoolean(ORDER_PROPOSALS);
- jcp.orderProposalsAlphabetically(enabled);
-
- enabled= store.getBoolean(ADD_INCLUDE);
- jcp.allowAddingIncludes(enabled);
+// enabled= store.getBoolean(ADD_INCLUDE);
+// ccp.allowAddingIncludes(enabled);
}
@@ -157,8 +158,8 @@ public class ContentAssistPreference {
private static void changeCProcessor(ContentAssistant assistant, IPreferenceStore store, String key) {
- CCompletionProcessor2 jcp= getCProcessor(assistant);
- if (jcp == null)
+ CContentAssistProcessor ccp= getCProcessor(assistant);
+ if (ccp == null)
return;
if ( (AUTOACTIVATION_TRIGGERS_DOT.equals(key))
@@ -177,22 +178,23 @@ public class ContentAssistPreference {
if (useDoubleColonAsTrigger){
triggers += ":"; //$NON-NLS-1$
}
- jcp.setCompletionProposalAutoActivationCharacters(triggers.toCharArray());
- } else if (SHOW_DOCUMENTED_PROPOSALS.equals(key)) {
- //boolean enabled= store.getBoolean(SHOW_DOCUMENTED_PROPOSALS);
- //jcp.restrictProposalsToVisibility(enabled);
- }
- //else if (CASE_SENSITIVITY.equals(key)) {
- // boolean enabled= store.getBoolean(CASE_SENSITIVITY);
- // jcp.restrictProposalsToMatchingCases(enabled);
- // }
- else if (ORDER_PROPOSALS.equals(key)) {
- boolean enable= store.getBoolean(ORDER_PROPOSALS);
- jcp.orderProposalsAlphabetically(enable);
- } else if (ADD_INCLUDE.equals(key)) {
- boolean enabled= store.getBoolean(ADD_INCLUDE);
- jcp.allowAddingIncludes(enabled);
+ ccp.setCompletionProposalAutoActivationCharacters(triggers.toCharArray());
}
+// else if (SHOW_DOCUMENTED_PROPOSALS.equals(key)) {
+// boolean enabled= store.getBoolean(SHOW_DOCUMENTED_PROPOSALS);
+// ccp.restrictProposalsToVisibility(enabled);
+// }
+// else if (CASE_SENSITIVITY.equals(key)) {
+// boolean enabled= store.getBoolean(CASE_SENSITIVITY);
+// ccp.restrictProposalsToMatchingCases(enabled);
+// }
+// else if (ORDER_PROPOSALS.equals(key)) {
+// boolean enable= store.getBoolean(ORDER_PROPOSALS);
+// ccp.orderProposalsAlphabetically(enable);
+// } else if (ADD_INCLUDE.equals(key)) {
+// boolean enabled= store.getBoolean(ADD_INCLUDE);
+// ccp.allowAddingIncludes(enabled);
+// }
}
/**
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistProcessor.java
new file mode 100644
index 00000000000..c3ab20d9597
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistProcessor.java
@@ -0,0 +1,557 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.text.contentassist;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.action.LegacyActionTools;
+import org.eclipse.jface.bindings.TriggerSequence;
+import org.eclipse.jface.bindings.keys.KeySequence;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ContentAssistEvent;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.ICompletionListener;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContentAssistantExtension2;
+import org.eclipse.jface.text.contentassist.IContentAssistantExtension3;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.swt.SWT;
+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.Control;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.ui.keys.IBindingService;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.ui.PreferenceConstants;
+import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
+
+import org.eclipse.cdt.internal.ui.CUIMessages;
+import org.eclipse.cdt.internal.ui.dialogs.OptionalMessageDialog;
+import org.eclipse.cdt.internal.ui.util.Messages;
+
+/**
+ * A content assist processor that aggregates the proposals of the
+ * {@link org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer}s contributed via the
+ * org.eclipse.cdt.ui.completionProposalComputer
extension point.
+ *
+ *
+ * createContext
to provide the context object passed to the computerscreateProgressMonitor
to change the way progress is reportedfilterAndSort
to add sorting and filteringgetContextInformationValidator
to add context validation (needed if any
+ * contexts are provided)getErrorMessage
to change error reporting
+ * The default implementation creates a
+ * NullProgressMonitor
.
+ *
false
if the given invocation context looks like a field reference
+ */
+ private boolean isValidContext(ContentAssistInvocationContext context) {
+ CHeuristicScanner scanner= new CHeuristicScanner(context.getDocument());
+ int start= context.getInvocationOffset();
+ return !scanner.looksLikeFieldReferenceBackward(start, Math.max(0, start-100));
+ }
+
+ /*
+ * @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#computeContextInformation(org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) {
+ return Collections.EMPTY_LIST;
+ }
+
+ /*
+ * @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#getErrorMessage()
+ */
+ public String getErrorMessage() {
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#sessionStarted()
+ */
+ public void sessionStarted() {
+ }
+
+ /*
+ * @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#sessionEnded()
+ */
+ public void sessionEnded() {
+ if (fCommentTemplateEngine != null) {
+ fCommentTemplateEngine.reset();
+ }
+ if (fCTemplateEngine != null) {
+ fCTemplateEngine.reset();
+ }
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/CTemplateCompletionProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/CTemplateCompletionProcessor.java
deleted file mode 100644
index 134b0d87546..00000000000
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/CTemplateCompletionProcessor.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Wind River Systems, Inc. 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:
- * Anton Leherbauer (Wind River Systems) - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.cdt.internal.ui.text.template;
-
-import java.util.List;
-
-import org.eclipse.core.runtime.Assert;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.ITextViewer;
-import org.eclipse.jface.text.TextUtilities;
-import org.eclipse.jface.text.contentassist.ICompletionProposal;
-import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
-import org.eclipse.jface.text.contentassist.IContextInformation;
-import org.eclipse.jface.text.contentassist.IContextInformationValidator;
-import org.eclipse.jface.text.templates.TemplateContextType;
-import org.eclipse.ui.IEditorPart;
-
-import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
-import org.eclipse.cdt.core.model.IWorkingCopy;
-import org.eclipse.cdt.ui.CUIPlugin;
-import org.eclipse.cdt.ui.text.ICPartitions;
-import org.eclipse.cdt.ui.text.contentassist.ICompletionContributor;
-
-import org.eclipse.cdt.internal.corext.template.c.CContextType;
-import org.eclipse.cdt.internal.corext.template.c.CommentContextType;
-
-/**
- * A completion processor for templates.
- * Can be used directly as implementation of {@link IContentAssistProcessor} or
- * as implementation of the extension point interface {@link ICompletionContributor}.
- *
- * @since 4.0
- */
-public class CTemplateCompletionProcessor implements IContentAssistProcessor, ICompletionContributor {
-
- private static final ICompletionProposal[] NO_PROPOSALS= new ICompletionProposal[0];
- private static final IContextInformation[] NO_CONTEXTS= new IContextInformation[0];
-
- private IEditorPart fEditor;
-
- private final TemplateEngine fCTemplateEngine;
- private final TemplateEngine fCommentTemplateEngine;
-
- /**
- * Create a new template completion processor to be used as IContentAssistProcessor
.
- *
- * @param editor the editor, may not be null
- */
- public CTemplateCompletionProcessor(IEditorPart editor) {
- this();
- Assert.isNotNull(editor);
- fEditor= editor;
- }
-
- /**
- * Default constructor is required (executable extension).
- */
- public CTemplateCompletionProcessor() {
- TemplateContextType contextType= CUIPlugin.getDefault().getTemplateContextRegistry().getContextType(CContextType.ID);
- if (contextType == null) {
- contextType= new CContextType();
- CUIPlugin.getDefault().getTemplateContextRegistry().addContextType(contextType);
- }
- if (contextType != null)
- fCTemplateEngine= new TemplateEngine(contextType);
- else
- fCTemplateEngine= null;
- contextType= CUIPlugin.getDefault().getTemplateContextRegistry().getContextType(CommentContextType.ID);
- if (contextType == null) {
- contextType= new CommentContextType();
- CUIPlugin.getDefault().getTemplateContextRegistry().addContextType(contextType);
- }
- if (contextType != null)
- fCommentTemplateEngine= new TemplateEngine(contextType);
- else
- fCommentTemplateEngine= null;
- }
-
- /*
- * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer, int)
- */
- public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
- Assert.isNotNull(fEditor);
- TemplateEngine engine;
- try {
- String partition= TextUtilities.getContentType(viewer.getDocument(), ICPartitions.C_PARTITIONING, offset, true);
- if (partition.equals(ICPartitions.C_MULTI_LINE_COMMENT))
- engine= fCommentTemplateEngine;
- else
- engine= fCTemplateEngine;
- } catch (BadLocationException x) {
- return NO_PROPOSALS;
- }
-
- if (engine != null) {
- IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput());
- if (workingCopy == null)
- return NO_PROPOSALS;
-
- engine.reset();
- engine.complete(viewer, offset, workingCopy);
-
- List result= engine.getResults();
-
- return (ICompletionProposal[]) result.toArray(new ICompletionProposal[result.size()]);
- }
- return NO_PROPOSALS;
- }
-
- /*
- * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer, int)
- */
- public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
- return NO_CONTEXTS;
- }
-
- /*
- * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
- */
- public char[] getCompletionProposalAutoActivationCharacters() {
- return null;
- }
-
- /*
- * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters()
- */
- public char[] getContextInformationAutoActivationCharacters() {
- return null;
- }
-
- /*
- * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
- */
- public IContextInformationValidator getContextInformationValidator() {
- return null;
- }
-
- /*
- * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage()
- */
- public String getErrorMessage() {
- return null;
- }
-
- /*
- * @see org.eclipse.cdt.ui.text.contentassist.ICompletionContributor#contributeCompletionProposals(org.eclipse.jface.text.ITextViewer, int, org.eclipse.cdt.core.model.IWorkingCopy, org.eclipse.cdt.core.dom.ast.ASTCompletionNode, java.lang.String, java.util.List)
- */
- public void contributeCompletionProposals(ITextViewer viewer, int offset,
- IWorkingCopy workingCopy, ASTCompletionNode completionNode,
- String prefix, List proposals) {
- // TODO We should use the completion node to determine the proper context for the templates
- // For now we just keep the current behavior
- TemplateEngine engine;
- try {
- String partition= TextUtilities.getContentType(viewer.getDocument(), ICPartitions.C_PARTITIONING, offset, true);
- if (partition.equals(ICPartitions.C_MULTI_LINE_COMMENT))
- engine= fCommentTemplateEngine;
- else
- engine= fCTemplateEngine;
- } catch (BadLocationException x) {
- return;
- }
-
- if (engine != null) {
- engine.reset();
- engine.complete(viewer, offset, workingCopy);
-
- List result= engine.getResults();
- proposals.addAll(result);
- }
- }
-
-}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java
index 67e5c87c63c..14ea99b153d 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * Copyright (c) 2005, 2007 IBM Corporation 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
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* QNX Software System
+ * Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.ui;
@@ -25,8 +26,7 @@ import org.eclipse.cdt.internal.ui.text.ICColorConstants;
* preference store programmatically.
*
* @since 2.0
- */
-
+ */
public class PreferenceConstants {
private PreferenceConstants() {
@@ -671,6 +671,27 @@ public class PreferenceConstants {
*/
public static final String CVIEW_GROUP_INCLUDES= "org.eclipse.cdt.ui.cview.groupincludes"; //$NON-NLS-1$
+ /**
+ * A named preference that controls which completion proposal categories
+ * have been excluded from the default proposal list.
+ *
+ * Value is of type String
, a "\0"-separated list of identifiers.
+ *
+ * Value is of type String
, a "\0"-separated list of identifiers.
+ *
@@ -985,5 +1006,9 @@ public class PreferenceConstants { store.setDefault(PreferenceConstants.EDITOR_ESCAPE_STRINGS, false); store.setDefault(PreferenceConstants.ENSURE_NEWLINE_AT_EOF, false); + + // content assist + store.setDefault(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES, "org.eclipse.cdt.ui.textProposalCategory\0"); //$NON-NLS-1$ + store.setDefault(PreferenceConstants.CODEASSIST_CATEGORY_ORDER, "org.eclipse.cdt.ui.parserProposalCategory:65539\0org.eclipse.cdt.ui.textProposalCategory:65541\0org.eclipse.cdt.ui.templateProposalCategory:2\0"); //$NON-NLS-1$ } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/contentassist/ContentAssistInvocationContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/contentassist/ContentAssistInvocationContext.java new file mode 100644 index 00000000000..a12dd887f96 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/contentassist/ContentAssistInvocationContext.java @@ -0,0 +1,195 @@ +/******************************************************************************* + * Copyright (c) 2005, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.ui.text.contentassist; + +import org.eclipse.core.runtime.Assert; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; + +/** + * Describes the context of an invocation of content assist in a text viewer. The context knows the + * document, the invocation offset and can lazily compute the identifier prefix preceding the + * invocation offset. It may know the viewer. + *
+ * Subclasses may add information to their environment. For example, source code editors may provide + * specific context information such as an AST. + *
+ *+ * Clients may instantiate and subclass. + *
+ * + * @since 4.0 + */ +public class ContentAssistInvocationContext { + + /* state */ + private final ITextViewer fViewer; + private final IDocument fDocument; + private final int fOffset; + + /* cached additional info */ + private CharSequence fPrefix; + + /** + * Equivalent to + * {@linkplain #ContentAssistInvocationContext(ITextViewer, int) ContentAssistInvocationContext(viewer, viewer.getSelectedRange().x)}. + * + * @param viewer the text viewer that content assist is invoked in + */ + public ContentAssistInvocationContext(ITextViewer viewer) { + this(viewer, viewer.getSelectedRange().x); + } + + /** + * Creates a new context for the given viewer and offset. + * + * @param viewer the text viewer that content assist is invoked in + * @param offset the offset into the viewer's document where content assist is invoked at + */ + public ContentAssistInvocationContext(ITextViewer viewer, int offset) { + Assert.isNotNull(viewer); + fViewer= viewer; + fDocument= null; + fOffset= offset; + } + + /** + * Creates a new context with no viewer or invocation offset set. + */ + protected ContentAssistInvocationContext() { + fDocument= null; + fViewer= null; + fOffset= -1; + } + + /** + * Creates a new context for the given document and offset. + * + * @param document the document that content assist is invoked in + * @param offset the offset into the document where content assist is invoked at + */ + public ContentAssistInvocationContext(IDocument document, int offset) { + Assert.isNotNull(document); + Assert.isTrue(offset >= 0); + fViewer= null; + fDocument= document; + fOffset= offset; + } + + /** + * Returns the invocation offset. + * + * @return the invocation offset + */ + public final int getInvocationOffset() { + return fOffset; + } + + /** + * Returns the viewer,null
if not available.
+ *
+ * @return the viewer, possibly null
+ */
+ public final ITextViewer getViewer() {
+ return fViewer;
+ }
+
+ /**
+ * Returns the document that content assist is invoked on, or null
if not known.
+ *
+ * @return the document or null
+ */
+ public IDocument getDocument() {
+ if (fDocument == null) {
+ if (fViewer == null)
+ return null;
+ return fViewer.getDocument();
+ }
+ return fDocument;
+ }
+
+ /**
+ * Computes the identifier (as specified by {@link Character#isJavaIdentifierPart(char)}) that
+ * immediately precedes the invocation offset.
+ *
+ * @return the prefix preceding the content assist invocation offset, null
if
+ * there is no document
+ * @throws BadLocationException if accessing the document fails
+ */
+ public CharSequence computeIdentifierPrefix() throws BadLocationException {
+ if (fPrefix == null) {
+ IDocument document= getDocument();
+ if (document == null)
+ return null;
+ int end= getInvocationOffset();
+ int start= end;
+ while (--start >= 0) {
+ if (!Character.isJavaIdentifierPart(document.getChar(start)))
+ break;
+ }
+ start++;
+ fPrefix= document.get(start, end - start);
+ }
+
+ return fPrefix;
+ }
+
+ /**
+ * Invocation contexts are equal if they describe the same context and are of the same type.
+ * This implementation checks for null
values and class equality. Subclasses
+ * should extend this method by adding checks for their context relevant fields (but not
+ * necessarily cached values).
+ * + * Example: + * + *
+ * class MyContext extends ContentAssistInvocationContext { + * private final Object fState; + * private Object fCachedInfo; + * + * ... + * + * public boolean equals(Object obj) { + * if (!super.equals(obj)) + * return false; + * MyContext other= (MyContext) obj; + * return fState.equals(other.fState); + * } + * } + *+ * + * + *
+ * Subclasses should also extend {@link Object#hashCode()}. + *
+ * + * @param obj {@inheritDoc} + * @return {@inheritDoc} + */ + public boolean equals(Object obj) { + if (obj == null) + return false; + if (!getClass().equals(obj.getClass())) + return false; + ContentAssistInvocationContext other= (ContentAssistInvocationContext) obj; + return (fViewer == null && other.fViewer == null || fViewer != null && fViewer.equals(other.fViewer)) && fOffset == other.fOffset && (fDocument == null && other.fDocument == null || fDocument != null && fDocument.equals(other.fDocument)); + } + + /* + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return 23459213 << 5 | (fViewer == null ? 0 : fViewer.hashCode() << 3) | fOffset; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/contentassist/ICompletionProposalComputer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/contentassist/ICompletionProposalComputer.java new file mode 100644 index 00000000000..a54ca6ef9ed --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/contentassist/ICompletionProposalComputer.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.ui.text.contentassist; + +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContextInformation; + +/** + * Computes completions and context information displayed by the C/C++ editor content assistant. + * Contributions to the org.eclipse.cdt.ui.completionProposalComputer extension point + * must implement this interface. + * + * @since 4.0 + */ +public interface ICompletionProposalComputer { + /** + * Informs the computer that a content assist session has started. This call will always be + * followed by a {@link #sessionEnded()} call, but not necessarily by calls to + * {@linkplain #computeCompletionProposals(ContentAssistInvocationContext, IProgressMonitor) computeCompletionProposals} + * or + * {@linkplain #computeContextInformation(ContentAssistInvocationContext, IProgressMonitor) computeContextInformation}. + */ + void sessionStarted(); + + /** + * Returns a list of completion proposals valid at the given invocation context. + * + * @param context the context of the content assist invocation + * @param monitor a progress monitor to report progress. The monitor is private to this + * invocation, i.e. there is no need for the receiver to spawn a sub monitor. + * @return a list of completion proposals (element type: {@link ICompletionProposal}) + */ + List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor); + + /** + * Returns context information objects valid at the given invocation context. + * + * @param context the context of the content assist invocation + * @param monitor a progress monitor to report progress. The monitor is private to this + * invocation, i.e. there is no need for the receiver to spawn a sub monitor. + * @return a list of context information objects (element type: {@link IContextInformation}) + */ + List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor); + + /** + * Returns the reason why this computer was unable to produce any completion proposals or + * context information. + * + * @return an error message ornull
if no error occurred
+ */
+ String getErrorMessage();
+
+ /**
+ * Informs the computer that a content assist session has ended. This call will always be after
+ * any calls to
+ * {@linkplain #computeCompletionProposals(ContentAssistInvocationContext, IProgressMonitor) computeCompletionProposals}
+ * and
+ * {@linkplain #computeContextInformation(ContentAssistInvocationContext, IProgressMonitor) computeContextInformation}.
+ */
+ void sessionEnded();
+}