| /******************************************************************************* |
| * Copyright (c) 2005, 2016 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 |
| * Paul Fullbright <paul.fullbright@oracle.com> - content assist category enablement - http://bugs.eclipse.org/345213 |
| * Marcel Bruch <bruch@cs.tu-darmstadt.de> - [content assist] Allow to re-sort proposals - https://bugs.eclipse.org/bugs/show_bug.cgi?id=350991 |
| * Lars Vogel <lars.vogel@gmail.com> - convert to foreach loop - https://bugs.eclipse.org/bugs/show_bug.cgi?id=406478 |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.ui.text.java; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| |
| 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.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.InvalidRegistryObjectException; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| 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.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.ICompletionListenerExtension; |
| 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.ui.PlatformUI; |
| import org.eclipse.ui.dialogs.PreferencesUtil; |
| import org.eclipse.ui.keys.IBindingService; |
| |
| import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; |
| |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| |
| import org.eclipse.jdt.ui.PreferenceConstants; |
| import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.JavaUIMessages; |
| import org.eclipse.jdt.internal.ui.dialogs.OptionalMessageDialog; |
| |
| |
| /** |
| * A content assist processor that aggregates the proposals of the |
| * {@link org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer}s contributed via the |
| * <code>org.eclipse.jdt.ui.javaCompletionProposalComputer</code> extension point. |
| * <p> |
| * Subclasses may extend: |
| * <ul> |
| * <li><code>createContext</code> to provide the context object passed to the computers</li> |
| * <li><code>createProgressMonitor</code> to change the way progress is reported</li> |
| * <li><code>filterAndSort</code> to add sorting and filtering</li> |
| * <li><code>getContextInformationValidator</code> to add context validation (needed if any |
| * contexts are provided)</li> |
| * <li><code>getErrorMessage</code> to change error reporting</li> |
| * </ul> |
| * </p> |
| * |
| * @since 3.2 |
| */ |
| public class ContentAssistProcessor implements IContentAssistProcessor { |
| |
| |
| /** |
| * The completion listener class for this processor. |
| * |
| * @since 3.4 |
| */ |
| private final class CompletionListener implements ICompletionListener, ICompletionListenerExtension { |
| /* |
| * @see org.eclipse.jface.text.contentassist.ICompletionListener#assistSessionStarted(org.eclipse.jface.text.contentassist.ContentAssistEvent) |
| */ |
| @Override |
| public void assistSessionStarted(ContentAssistEvent event) { |
| if (event.processor != ContentAssistProcessor.this) |
| return; |
| |
| fIterationGesture= getIterationGesture(); |
| KeySequence binding= getIterationBinding(); |
| |
| // This may show the warning dialog if all categories are disabled |
| setCategoryIteration(); |
| for (CompletionProposalCategory cat : getCategoriesToNotify()) { |
| cat.sessionStarted(); |
| } |
| |
| fRepetition= 0; |
| if (event.assistant instanceof IContentAssistantExtension2) { |
| IContentAssistantExtension2 extension= (IContentAssistantExtension2) event.assistant; |
| |
| if (fCategoryIteration.size() == 1) { |
| extension.setRepeatedInvocationMode(false); |
| extension.setShowEmptyList(false); |
| } else { |
| extension.setRepeatedInvocationMode(true); |
| extension.setStatusLineVisible(true); |
| extension.setStatusMessage(createIterationMessage()); |
| extension.setShowEmptyList(true); |
| if (extension instanceof IContentAssistantExtension3) { |
| IContentAssistantExtension3 ext3= (IContentAssistantExtension3) extension; |
| ((ContentAssistant) ext3).setRepeatedInvocationTrigger(binding); |
| } |
| } |
| |
| } |
| } |
| |
| /** |
| * Returns the categories that need to be notified when a session starts and ends. |
| * |
| * @return the current categories |
| * @since 3.8.1 |
| */ |
| private Set<CompletionProposalCategory> getCategoriesToNotify() { |
| Set<CompletionProposalCategory> currentCategories= new HashSet<>(fCategories.size()); |
| |
| // Currently enabled categories for this session |
| if (fCategoryIteration != null) { |
| Iterator<List<CompletionProposalCategory>> it= fCategoryIteration.iterator(); |
| while (it.hasNext()) |
| currentCategories.addAll(it.next()); |
| } |
| |
| // Backwards compatibility: notify all categories which have no enablement expression |
| for (CompletionProposalCategory cat : fCategories) { |
| if (cat.getEnablementExpression() == null) |
| currentCategories.add(cat); |
| } |
| |
| return currentCategories; |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.contentassist.ICompletionListener#assistSessionEnded(org.eclipse.jface.text.contentassist.ContentAssistEvent) |
| */ |
| @Override |
| public void assistSessionEnded(ContentAssistEvent event) { |
| if (event.processor != ContentAssistProcessor.this) |
| return; |
| |
| for (CompletionProposalCategory cat : getCategoriesToNotify()) { |
| cat.sessionEnded(); |
| } |
| |
| fSelectedProposal= null; |
| fCategoryIteration= null; |
| fRepetition= -1; |
| fIterationGesture= null; |
| if (event.assistant instanceof IContentAssistantExtension2) { |
| IContentAssistantExtension2 extension= (IContentAssistantExtension2) event.assistant; |
| extension.setShowEmptyList(false); |
| extension.setRepeatedInvocationMode(false); |
| extension.setStatusLineVisible(false); |
| if (extension instanceof IContentAssistantExtension3) { |
| IContentAssistantExtension3 ext3= (IContentAssistantExtension3) extension; |
| ((ContentAssistant) ext3).setRepeatedInvocationTrigger(null); |
| } |
| } |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.contentassist.ICompletionListener#selectionChanged(org.eclipse.jface.text.contentassist.ICompletionProposal, boolean) |
| */ |
| @Override |
| public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) { |
| fSelectedProposal= proposal; |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.contentassist.ICompletionListenerExtension#assistSessionRestarted(org.eclipse.jface.text.contentassist.ContentAssistEvent) |
| * @since 3.4 |
| */ |
| @Override |
| public void assistSessionRestarted(ContentAssistEvent event) { |
| fRepetition= 0; |
| } |
| } |
| |
| /** |
| * Dialog settings key for the "all categories are disabled" warning dialog. See |
| * {@link OptionalMessageDialog}. |
| * |
| * @since 3.3 |
| */ |
| private static final String PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY= "EmptyDefaultAssistCategory"; //$NON-NLS-1$ |
| |
| private static final Comparator<CompletionProposalCategory> ORDER_COMPARATOR= new Comparator<CompletionProposalCategory>() { |
| |
| @Override |
| public int compare(CompletionProposalCategory d1, CompletionProposalCategory d2) { |
| return d1.getSortOrder() - d2.getSortOrder(); |
| } |
| |
| }; |
| |
| private final List<CompletionProposalCategory> fCategories; |
| private final String fPartition; |
| private final ContentAssistant fAssistant; |
| private ICompletionProposal fSelectedProposal; |
| |
| private char[] fCompletionAutoActivationCharacters; |
| |
| /* cycling stuff */ |
| private int fRepetition= -1; |
| private List<List<CompletionProposalCategory>> fCategoryIteration= null; |
| private String fIterationGesture= null; |
| private int fNumberOfComputedResults= 0; |
| private String fErrorMessage; |
| |
| /** |
| * The completion proposal registry. |
| * |
| * @since 3.4 |
| */ |
| private CompletionProposalComputerRegistry fComputerRegistry; |
| |
| /** |
| * Flag indicating whether any completion engine associated with this processor requests |
| * resorting of its proposals after filtering is triggered. Filtering is, e.g., triggered when a |
| * user continues typing with an open completion window. |
| * |
| * @since 3.8 |
| */ |
| private boolean fNeedsSortingAfterFiltering; |
| |
| |
| public ContentAssistProcessor(ContentAssistant assistant, String partition) { |
| Assert.isNotNull(partition); |
| Assert.isNotNull(assistant); |
| fPartition= partition; |
| fComputerRegistry= CompletionProposalComputerRegistry.getDefault(); |
| fCategories= fComputerRegistry.getProposalCategories(); |
| fAssistant= assistant; |
| fAssistant.addCompletionListener(new CompletionListener()); |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer, int) |
| */ |
| @Override |
| public final ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { |
| long start= JavaPlugin.DEBUG_RESULT_COLLECTOR ? System.currentTimeMillis() : 0; |
| |
| clearState(); |
| |
| IProgressMonitor monitor= createProgressMonitor(); |
| monitor.beginTask(JavaTextMessages.ContentAssistProcessor_computing_proposals, fCategories.size() + 1); |
| |
| ContentAssistInvocationContext context= createContext(viewer, offset); |
| long setup= JavaPlugin.DEBUG_RESULT_COLLECTOR ? System.currentTimeMillis() : 0; |
| |
| monitor.subTask(JavaTextMessages.ContentAssistProcessor_collecting_proposals); |
| List<ICompletionProposal> proposals= collectProposals(viewer, offset, monitor, context); |
| long collect= JavaPlugin.DEBUG_RESULT_COLLECTOR ? System.currentTimeMillis() : 0; |
| |
| monitor.subTask(JavaTextMessages.ContentAssistProcessor_sorting_proposals); |
| if (fNeedsSortingAfterFiltering) |
| setContentAssistSorter(); |
| else |
| proposals= sortProposals(proposals, monitor, context); |
| fNumberOfComputedResults= proposals.size(); |
| long filter= JavaPlugin.DEBUG_RESULT_COLLECTOR ? System.currentTimeMillis() : 0; |
| |
| ICompletionProposal[] result= proposals.toArray(new ICompletionProposal[proposals.size()]); |
| monitor.done(); |
| |
| if (JavaPlugin.DEBUG_RESULT_COLLECTOR) { |
| System.err.println("Code Assist Stats (" + result.length + " proposals)"); //$NON-NLS-1$ //$NON-NLS-2$ |
| System.err.println("Code Assist (setup):\t" + (setup - start) ); //$NON-NLS-1$ |
| System.err.println("Code Assist (collect):\t" + (collect - setup) ); //$NON-NLS-1$ |
| System.err.println("Code Assist (sort):\t" + (filter - collect) ); //$NON-NLS-1$ |
| } |
| |
| return result; |
| } |
| |
| private void clearState() { |
| fErrorMessage=null; |
| fNumberOfComputedResults= 0; |
| } |
| |
| /** |
| * Collects the proposals. |
| * |
| * @param viewer the text viewer |
| * @param offset the offset |
| * @param monitor the progress monitor |
| * @param context the code assist invocation context |
| * @return the list of proposals |
| */ |
| private List<ICompletionProposal> collectProposals(ITextViewer viewer, int offset, IProgressMonitor monitor, ContentAssistInvocationContext context) { |
| boolean needsSortingAfterFiltering= false; |
| List<ICompletionProposal> proposals= new ArrayList<>(); |
| List<CompletionProposalCategory> providers= getCategories(); |
| for (CompletionProposalCategory cat : providers) { |
| List<ICompletionProposal> computed= cat.computeCompletionProposals(context, fPartition, new SubProgressMonitor(monitor, 1)); |
| proposals.addAll(computed); |
| needsSortingAfterFiltering= needsSortingAfterFiltering || (cat.isSortingAfterFilteringNeeded() && !computed.isEmpty()); |
| if (fErrorMessage == null) |
| fErrorMessage= cat.getErrorMessage(); |
| } |
| if (fNeedsSortingAfterFiltering && !needsSortingAfterFiltering) |
| fAssistant.setSorter(null); |
| fNeedsSortingAfterFiltering= needsSortingAfterFiltering; |
| return proposals; |
| } |
| |
| /** |
| * Filters and sorts the proposals. The passed list may be modified |
| * and returned, or a new list may be created and returned. |
| * |
| * @param proposals the list of collected proposals (element type: |
| * {@link ICompletionProposal}) |
| * @param monitor a progress monitor |
| * @param context TODO |
| * @return the list of filtered and sorted proposals, ready for |
| * display (element type: {@link ICompletionProposal}) |
| */ |
| protected List<ICompletionProposal> sortProposals(List<ICompletionProposal> proposals, IProgressMonitor monitor, ContentAssistInvocationContext context) { |
| return proposals; |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer, int) |
| */ |
| @Override |
| public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { |
| clearState(); |
| |
| IProgressMonitor monitor= createProgressMonitor(); |
| monitor.beginTask(JavaTextMessages.ContentAssistProcessor_computing_contexts, fCategories.size() + 1); |
| |
| monitor.subTask(JavaTextMessages.ContentAssistProcessor_collecting_contexts); |
| List<IContextInformation> proposals= collectContextInformation(viewer, offset, monitor); |
| |
| monitor.subTask(JavaTextMessages.ContentAssistProcessor_sorting_contexts); |
| List<IContextInformation> filtered= filterAndSortContextInformation(proposals, monitor); |
| fNumberOfComputedResults= filtered.size(); |
| |
| IContextInformation[] result= filtered.toArray(new IContextInformation[filtered.size()]); |
| monitor.done(); |
| return result; |
| } |
| |
| private List<IContextInformation> collectContextInformation(ITextViewer viewer, int offset, IProgressMonitor monitor) { |
| List<IContextInformation> proposals= new ArrayList<>(); |
| ContentAssistInvocationContext context= createContext(viewer, offset); |
| |
| List<CompletionProposalCategory> providers= getCategories(); |
| for (CompletionProposalCategory cat : providers) { |
| List<IContextInformation> computed= cat.computeContextInformation(context, fPartition, new SubProgressMonitor(monitor, 1)); |
| proposals.addAll(computed); |
| if (fErrorMessage == null) |
| fErrorMessage= cat.getErrorMessage(); |
| } |
| |
| return proposals; |
| } |
| |
| /** |
| * Filters and sorts the context information objects. The passed |
| * list may be modified and returned, or a new list may be created |
| * and returned. |
| * |
| * @param contexts the list of collected proposals (element type: |
| * {@link IContextInformation}) |
| * @param monitor a progress monitor |
| * @return the list of filtered and sorted proposals, ready for |
| * display (element type: {@link IContextInformation}) |
| */ |
| protected List<IContextInformation> filterAndSortContextInformation(List<IContextInformation> contexts, IProgressMonitor monitor) { |
| return contexts; |
| } |
| |
| /** |
| * Sets this processor's set of characters triggering the activation of the |
| * completion proposal computation. |
| * |
| * @param activationSet the activation set |
| */ |
| public final void setCompletionProposalAutoActivationCharacters(char[] activationSet) { |
| fCompletionAutoActivationCharacters= activationSet; |
| } |
| |
| |
| /* |
| * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters() |
| */ |
| @Override |
| public final char[] getCompletionProposalAutoActivationCharacters() { |
| return fCompletionAutoActivationCharacters; |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters() |
| */ |
| @Override |
| public char[] getContextInformationAutoActivationCharacters() { |
| return null; |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage() |
| */ |
| @Override |
| public String getErrorMessage() { |
| if (fErrorMessage != null) |
| return fErrorMessage; |
| if (fNumberOfComputedResults > 0) |
| return null; |
| return JavaUIMessages.JavaEditor_codeassist_noCompletions; |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator() |
| */ |
| @Override |
| public IContextInformationValidator getContextInformationValidator() { |
| return null; |
| } |
| |
| /** |
| * Creates a progress monitor. |
| * <p> |
| * The default implementation creates a |
| * <code>NullProgressMonitor</code>. |
| * </p> |
| * |
| * @return a progress monitor |
| */ |
| protected IProgressMonitor createProgressMonitor() { |
| return new NullProgressMonitor(); |
| } |
| |
| /** |
| * Creates the context that is passed to the completion proposal |
| * computers. |
| * |
| * @param viewer the viewer that content assist is invoked on |
| * @param offset the content assist offset |
| * @return the context to be passed to the computers |
| */ |
| protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset) { |
| return new ContentAssistInvocationContext(viewer, offset); |
| } |
| |
| private List<CompletionProposalCategory> getCategories() { |
| if (fCategoryIteration == null) |
| return fCategories; |
| |
| int iteration= fRepetition % fCategoryIteration.size(); |
| fAssistant.setStatusMessage(createIterationMessage()); |
| fAssistant.setEmptyMessage(createEmptyMessage()); |
| fRepetition++; |
| |
| // fAssistant.setShowMessage(fRepetition % 2 != 0); |
| |
| return fCategoryIteration.get(iteration); |
| } |
| |
| // This may show the warning dialog if all categories are disabled |
| private void setCategoryIteration() { |
| fCategoryIteration= getCategoryIteration(); |
| } |
| |
| private List<List<CompletionProposalCategory>> getCategoryIteration() { |
| List<List<CompletionProposalCategory>> sequence= new ArrayList<>(); |
| sequence.add(getDefaultCategories()); |
| for (CompletionProposalCategory cat : getSeparateCategories()) { |
| sequence.add(Collections.singletonList(cat)); |
| } |
| return sequence; |
| } |
| |
| private List<CompletionProposalCategory> getDefaultCategories() { |
| // default mix - enable all included computers |
| List<CompletionProposalCategory> included= getDefaultCategoriesUnchecked(); |
| |
| if (fComputerRegistry.hasUninstalledComputers(fPartition, included)) { |
| if (informUserAboutEmptyDefaultCategory()) |
| // preferences were restored - recompute the default categories |
| included= getDefaultCategoriesUnchecked(); |
| fComputerRegistry.resetUnistalledComputers(); |
| } |
| |
| return included; |
| } |
| |
| private List<CompletionProposalCategory> getDefaultCategoriesUnchecked() { |
| List<CompletionProposalCategory> included= new ArrayList<>(); |
| for (CompletionProposalCategory category : fCategories) { |
| if (checkDefaultEnablement(category)) |
| included.add(category); |
| } |
| return included; |
| } |
| |
| /** |
| * Determine whether the category is enabled by default. |
| * |
| * @param category the category to check |
| * @return <code>true</code> if this category is enabled by default, <code>false</code> |
| * otherwise |
| * @since 3.8 |
| */ |
| protected boolean checkDefaultEnablement(CompletionProposalCategory category) { |
| return category.isIncluded() && category.hasComputers(fPartition); |
| } |
| |
| /** |
| * Informs the user about the fact that there are no enabled categories in the default content |
| * assist set and shows a link to the preferences. |
| * |
| * @return <code>true</code> if the default should be restored |
| * @since 3.3 |
| */ |
| private boolean informUserAboutEmptyDefaultCategory() { |
| if (OptionalMessageDialog.isDialogEnabled(PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY)) { |
| final Shell shell= JavaPlugin.getActiveWorkbenchShell(); |
| String title= JavaTextMessages.ContentAssistProcessor_all_disabled_title; |
| String message= JavaTextMessages.ContentAssistProcessor_all_disabled_message; |
| // see PreferencePage#createControl for the 'defaults' label |
| final String restoreButtonLabel= JFaceResources.getString("defaults"); //$NON-NLS-1$ |
| final String linkMessage= Messages.format(JavaTextMessages.ContentAssistProcessor_all_disabled_preference_link, LegacyActionTools.removeMnemonics(restoreButtonLabel)); |
| final int restoreId= IDialogConstants.CLIENT_ID + 10; |
| final int settingsId= IDialogConstants.CLIENT_ID + 11; |
| final OptionalMessageDialog dialog= new OptionalMessageDialog(PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY, shell, title, null /* default image */, message, MessageDialog.WARNING, new String[] { restoreButtonLabel, IDialogConstants.CLOSE_LABEL }, 1) { |
| /* |
| * @see org.eclipse.jdt.internal.ui.dialogs.OptionalMessageDialog#createCustomArea(org.eclipse.swt.widgets.Composite) |
| */ |
| @Override |
| protected Control createCustomArea(Composite composite) { |
| // wrap link and checkbox in one composite without space |
| Composite parent= new Composite(composite, SWT.NONE); |
| GridLayout layout= new GridLayout(); |
| layout.marginHeight= 0; |
| layout.marginWidth= 0; |
| layout.verticalSpacing= 0; |
| parent.setLayout(layout); |
| |
| Composite linkComposite= new Composite(parent, SWT.NONE); |
| layout= new GridLayout(); |
| layout.marginHeight= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); |
| layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); |
| layout.horizontalSpacing= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); |
| linkComposite.setLayout(layout); |
| |
| Link link= new Link(linkComposite, SWT.NONE); |
| link.setText(linkMessage); |
| link.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| setReturnCode(settingsId); |
| close(); |
| } |
| }); |
| GridData gridData= new GridData(SWT.FILL, SWT.BEGINNING, true, false); |
| gridData.widthHint= this.getMinimumMessageWidth(); |
| link.setLayoutData(gridData); |
| |
| // create checkbox and "don't show this message" prompt |
| super.createCustomArea(parent); |
| |
| return parent; |
| } |
| |
| /* |
| * @see org.eclipse.jface.dialogs.MessageDialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) |
| */ |
| @Override |
| protected void createButtonsForButtonBar(Composite parent) { |
| Button[] buttons= new Button[2]; |
| buttons[0]= createButton(parent, restoreId, restoreButtonLabel, false); |
| buttons[1]= createButton(parent, IDialogConstants.CLOSE_ID, IDialogConstants.CLOSE_LABEL, true); |
| setButtons(buttons); |
| } |
| }; |
| int returnValue= dialog.open(); |
| if (restoreId == returnValue || settingsId == returnValue) { |
| if (restoreId == returnValue) { |
| IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); |
| store.setToDefault(PreferenceConstants.CODEASSIST_CATEGORY_ORDER); |
| store.setToDefault(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES); |
| } |
| if (settingsId == returnValue) |
| PreferencesUtil.createPreferenceDialogOn(shell, "org.eclipse.jdt.ui.preferences.CodeAssistPreferenceAdvanced", null, null).open(); //$NON-NLS-1$ |
| fComputerRegistry.reload(); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private List<CompletionProposalCategory> getSeparateCategories() { |
| ArrayList<CompletionProposalCategory> sorted= new ArrayList<>(); |
| for (CompletionProposalCategory category : fCategories) { |
| if (checkSeparateEnablement(category)) |
| sorted.add(category); |
| } |
| Collections.sort(sorted, ORDER_COMPARATOR); |
| return sorted; |
| } |
| |
| /** |
| * Determine whether the category is enabled for separate use. |
| * |
| * @param category the category to check |
| * @return <code>true</code> if this category is enabled for separate use, <code>false</code> |
| * otherwise |
| * @since 3.8 |
| */ |
| protected boolean checkSeparateEnablement(CompletionProposalCategory category) { |
| return category.isSeparateCommand() && category.hasComputers(fPartition); |
| } |
| |
| private String createEmptyMessage() { |
| return Messages.format(JavaTextMessages.ContentAssistProcessor_empty_message, new String[]{getCategoryLabel(fRepetition)}); |
| } |
| |
| private String createIterationMessage() { |
| return Messages.format(JavaTextMessages.ContentAssistProcessor_toggle_affordance_update_message, new String[]{ getCategoryLabel(fRepetition), fIterationGesture, getCategoryLabel(fRepetition + 1) }); |
| } |
| |
| private String getCategoryLabel(int repetition) { |
| int iteration= repetition % fCategoryIteration.size(); |
| if (iteration == 0) |
| return JavaTextMessages.ContentAssistProcessor_defaultProposalCategory; |
| return toString(fCategoryIteration.get(iteration).get(0)); |
| } |
| |
| private String toString(CompletionProposalCategory category) { |
| return category.getDisplayName(); |
| } |
| |
| private String getIterationGesture() { |
| TriggerSequence binding= getIterationBinding(); |
| return binding != null ? |
| Messages.format(JavaTextMessages.ContentAssistProcessor_toggle_affordance_press_gesture, new Object[] { binding.format() }) |
| : JavaTextMessages.ContentAssistProcessor_toggle_affordance_click_gesture; |
| } |
| |
| private KeySequence getIterationBinding() { |
| final IBindingService bindingSvc= PlatformUI.getWorkbench().getAdapter(IBindingService.class); |
| TriggerSequence binding= bindingSvc.getBestActiveBindingFor(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); |
| if (binding instanceof KeySequence) |
| return (KeySequence) binding; |
| return null; |
| } |
| |
| /** |
| * Sets the current proposal sorter into the content assistant. |
| * |
| * @since 3.8 |
| * @see ProposalSorterRegistry#getCurrentSorter() the sorter used if <code>true</code> |
| */ |
| private void setContentAssistSorter() { |
| ProposalSorterHandle currentSorter= ProposalSorterRegistry.getDefault().getCurrentSorter(); |
| try { |
| fAssistant.setSorter(currentSorter.getSorter()); |
| } catch (InvalidRegistryObjectException x) { |
| JavaPlugin.log(currentSorter.createExceptionStatus(x)); |
| } catch (CoreException x) { |
| JavaPlugin.log(currentSorter.createExceptionStatus(x)); |
| } catch (RuntimeException x) { |
| JavaPlugin.log(currentSorter.createExceptionStatus(x)); |
| } |
| } |
| |
| /** |
| * Returns the proposal selected in the proposal selector. |
| * |
| * @return the selected proposal or <code>null</code> if none |
| * @since 3.12 |
| */ |
| public ICompletionProposal getSelectedProposal() { |
| return fSelectedProposal; |
| } |
| |
| } |