Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/META-INF/MANIFEST.MF,v retrieving revision 1.91 diff -u -r1.91 MANIFEST.MF --- META-INF/MANIFEST.MF 28 Jul 2011 19:53:25 -0000 1.91 +++ META-INF/MANIFEST.MF 11 Aug 2011 19:11:59 -0000 @@ -66,6 +66,11 @@ org.eclipse.jdt.internal.ui.packageview;x-internal:=true, org.eclipse.jdt.internal.ui.preferences;x-friends:="org.eclipse.jdt.apt.ui", org.eclipse.jdt.internal.ui.preferences.cleanup;x-internal:=true, + org.eclipse.jdt.internal.ui.preferences.codeassist.advanced;x-internal:=true, + org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;x-internal:=true, + org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model;x-internal:=true, + org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets;x-internal:=true, + org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util;x-internal:=true, org.eclipse.jdt.internal.ui.preferences.formatter;x-internal:=true, org.eclipse.jdt.internal.ui.propertiesfileeditor;x-internal:=true, org.eclipse.jdt.internal.ui.refactoring;x-internal:=true, Index: ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditorMessages.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditorMessages.java,v retrieving revision 1.42 diff -u -r1.42 JavaEditorMessages.java --- ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditorMessages.java 28 Jul 2011 17:39:58 -0000 1.42 +++ ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditorMessages.java 11 Aug 2011 19:12:00 -0000 @@ -8,7 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Andre Soereng - [syntax highlighting] highlight numbers - https://bugs.eclipse.org/bugs/show_bug.cgi?id=63573 - * Bj�rn Michael - [syntax highlighting] Syntax coloring for abstract classes - https://bugs.eclipse.org/331311 + * Bj�rn Michael - [syntax highlighting] Syntax coloring for abstract classes - https://bugs.eclipse.org/331311 *******************************************************************************/ package org.eclipse.jdt.internal.ui.javaeditor; Index: ui/org/eclipse/jdt/internal/ui/javaeditor/SpecificContentAssistExecutor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/SpecificContentAssistExecutor.java,v retrieving revision 1.8 diff -u -r1.8 SpecificContentAssistExecutor.java --- ui/org/eclipse/jdt/internal/ui/javaeditor/SpecificContentAssistExecutor.java 27 Apr 2011 07:48:36 -0000 1.8 +++ ui/org/eclipse/jdt/internal/ui/javaeditor/SpecificContentAssistExecutor.java 11 Aug 2011 19:12:00 -0000 @@ -7,11 +7,15 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Thomas Schlosser - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876 *******************************************************************************/ package org.eclipse.jdt.internal.ui.javaeditor; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.Iterator; +import java.util.Set; import org.eclipse.core.runtime.Assert; @@ -24,8 +28,9 @@ import org.eclipse.jdt.internal.ui.text.java.CompletionProposalComputerRegistry; /** - * A content assist executor can invoke content assist for a specific proposal category on an editor. - * + * A content assist executor can invoke content assist for a specific proposal category on an + * editor. + * * @since 3.2 */ public final class SpecificContentAssistExecutor { @@ -34,7 +39,7 @@ /** * Creates a new executor. - * + * * @param registry the computer registry to use for the enablement of proposal categories */ public SpecificContentAssistExecutor(CompletionProposalComputerRegistry registry) { @@ -45,21 +50,18 @@ /** * 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= it.next(); - inclusionState[i]= cat.isIncluded(); - cat.setIncluded(cat.getId().equals(categoryId)); - separateState[i]= cat.isSeparateCommand(); - cat.setSeparateCommand(false); + ArrayList> categoriesState= new ArrayList>(categories.size()); + for (CompletionProposalCategory cat : categories) { + categoriesState.add(new HashSet(cat.getProposalListIndices())); + cat.clearProposalListIndices(); + if (cat.getId().equals(categoryId)) + cat.addProposalListIndex(Integer.valueOf(0)); } try { @@ -67,11 +69,11 @@ if (target != null && target.canDoOperation(ISourceViewer.CONTENTASSIST_PROPOSALS)) target.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS); } finally { - i= 0; + int i= 0; for (Iterator it= categories.iterator(); it.hasNext(); i++) { CompletionProposalCategory cat= it.next(); - cat.setIncluded(inclusionState[i]); - cat.setSeparateCommand(separateState[i]); + cat.clearProposalListIndices(); + cat.addAllProposalListIndices(categoriesState.get(i)); } } } Index: ui/org/eclipse/jdt/internal/ui/preferences/CodeAssistAdvancedConfigurationBlock.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/CodeAssistAdvancedConfigurationBlock.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/CodeAssistAdvancedConfigurationBlock.java --- ui/org/eclipse/jdt/internal/ui/preferences/CodeAssistAdvancedConfigurationBlock.java 1 Mar 2011 11:50:45 -0000 1.14 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,784 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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 - *******************************************************************************/ -package org.eclipse.jdt.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.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.core.commands.Command; -import org.eclipse.core.commands.CommandManager; -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.commands.contexts.ContextManager; - -import org.eclipse.core.runtime.Assert; - -import org.eclipse.jface.bindings.BindingManager; -import org.eclipse.jface.bindings.Scheme; -import org.eclipse.jface.bindings.TriggerSequence; -import org.eclipse.jface.layout.PixelConverter; -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.jdt.core.JavaCore; - -import org.eclipse.jdt.internal.corext.util.Messages; - -import org.eclipse.jdt.ui.PreferenceConstants; - -import org.eclipse.jdt.internal.ui.JavaPlugin; -import org.eclipse.jdt.internal.ui.dialogs.StatusInfo; -import org.eclipse.jdt.internal.ui.text.java.CompletionProposalCategory; -import org.eclipse.jdt.internal.ui.text.java.CompletionProposalComputerRegistry; -import org.eclipse.jdt.internal.ui.util.SWTUtil; -import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener; - - -/** - * - * @since 3.2 - */ -final class CodeAssistAdvancedConfigurationBlock extends OptionsConfigurationBlock { - - private static final Key PREF_EXCLUDED_CATEGORIES= getJDTUIKey(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES); - private static final Key PREF_CATEGORY_ORDER= getJDTUIKey(PreferenceConstants.CODEASSIST_CATEGORY_ORDER); - private static final Key PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC= getJDTCoreKey(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC); - - private static Key[] getAllKeys() { - return new Key[] { - PREF_EXCLUDED_CATEGORIES, - PREF_CATEGORY_ORDER, - PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC - }; - } - - 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) - */ - @Override - 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(ModelElement o) { - return o.getRank(); - } - - public int compare(ModelElement o1, ModelElement o2) { - return getRank(o1) - getRank(o2); - } - }; - - private final class PreferenceModel { - private static final int LIMIT= 65535; - 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= 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) { - ModelElement 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) { - ModelElement 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= 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= 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.jdt.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.jdt.internal.ui.preferences.OptionsConfigurationBlock#createContents(org.eclipse.swt.widgets.Composite) - */ - @Override - 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); - layout.marginWidth= 0; - layout.marginHeight= 0; - composite.setLayout(layout); - - - createDefaultLabel(composite, columns); - createDefaultViewer(composite, columns); - createKeysLink(composite, columns); - - createFiller(composite, columns); - - createSeparateLabel(composite, columns); - createSeparateSection(composite); - - createFiller(composite, columns); - - createParameterTimeoutControl(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() { - @Override - 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() { - @Override - 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() { - @Override - public void widgetSelected(SelectionEvent e) { - int index= getSelectionIndex(); - if (index != -1) { - 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() { - @Override - public void widgetSelected(SelectionEvent e) { - int index= getSelectionIndex(); - if (index != -1) { - fModel.elements.get(index).moveDown(); - fSeparateViewer.refresh(); - handleTableSelection(); - } - } - }); - fDownButton.setLayoutData(new GridData()); - SWTUtil.setButtonDimensionHint(fDownButton); - } - - private void createParameterTimeoutControl(Composite composite, int h_span) { - Composite timeoutComposite= new Composite(composite, SWT.NONE); - GridLayout layout= new GridLayout(4, false); - layout.marginWidth= 0; - layout.marginHeight= 0; - timeoutComposite.setLayout(layout); - GridData gd= new GridData(GridData.FILL, GridData.FILL, true, false, h_span, 1); - timeoutComposite.setLayoutData(gd); - - PixelConverter pixelConverter= new PixelConverter(composite); - String str= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout; - addTextField(timeoutComposite, str, PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, 0, pixelConverter.convertWidthInCharsToPixels(7)); - - } - - 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.jdt.internal.ui.preferences.OptionsConfigurationBlock#updateControls() - */ - @Override - 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= 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.jdt.internal.ui.preferences.OptionsConfigurationBlock#processChanges(org.eclipse.ui.preferences.IWorkbenchPreferenceContainer) - */ - @Override - protected boolean processChanges(IWorkbenchPreferenceContainer container) { - for (Iterator it= fModel.elements.iterator(); it.hasNext();) { - ModelElement item= it.next(); - item.update(); - } - - return super.processChanges(container); - } - - /* - * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock.Key, java.lang.String, java.lang.String) - */ - @Override - protected void validateSettings(Key changedKey, String oldValue, String newValue) { - if (changedKey == PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC) { - final StatusInfo status= new StatusInfo(); - if (newValue.length() == 0) - status.setError(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_emptyInput); - else { - try { - int number= Integer.parseInt(newValue); - int min= 0; - int max= 5000; - if (number < min || number > max) { - String msgFormat= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_invalidRange; - String msg= Messages.format(msgFormat, new Object[] {new Integer(min), new Integer(max)}); - status.setError(msg); - } - } catch (NumberFormatException ex) { - String msgFormat= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_invalidInput; - String msg= Messages.format(msgFormat, newValue); - status.setError(msg); - } - } - fContext.statusChanged(status); - } - } - - /* - * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#getFullBuildDialogStrings(boolean) - */ - @Override - protected String[] getFullBuildDialogStrings(boolean workspaceSettings) { - // no builds triggered by our settings - return null; - } - - /* - * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#dispose() - */ - @Override - public void dispose() { - for (Iterator it= fImages.values().iterator(); it.hasNext();) { - 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 BindingManager fgLocalBindingManager; - static { - fgLocalBindingManager= new BindingManager(new ContextManager(), new CommandManager()); - final IBindingService bindingService= (IBindingService)PlatformUI.getWorkbench().getService(IBindingService.class); - final Scheme[] definedSchemes= bindingService.getDefinedSchemes(); - if (definedSchemes != null) { - try { - for (int i = 0; i < definedSchemes.length; i++) { - final Scheme scheme= definedSchemes[i]; - final Scheme copy= fgLocalBindingManager.getScheme(scheme.getId()); - copy.define(scheme.getName(), scheme.getDescription(), scheme.getParentId()); - } - } catch (final NotDefinedException e) { - JavaPlugin.log(e); - } - } - fgLocalBindingManager.setLocale(bindingService.getLocale()); - fgLocalBindingManager.setPlatform(bindingService.getPlatform()); - } - - private static String getKeyboardShortcut(ParameterizedCommand command) { - IBindingService bindingService= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class); - fgLocalBindingManager.setBindings(bindingService.getBindings()); - try { - Scheme activeScheme= bindingService.getActiveScheme(); - if (activeScheme != null) - fgLocalBindingManager.setActiveScheme(activeScheme); - } catch (NotDefinedException e) { - JavaPlugin.log(e); - } - - TriggerSequence[] bindings= fgLocalBindingManager.getActiveBindingsDisregardingContextFor(command); - if (bindings.length > 0) - return bindings[0].format(); - return null; - } - - private Image getImage(ImageDescriptor imgDesc) { - if (imgDesc == null) - return null; - - Image img= fImages.get(imgDesc); - if (img == null) { - img= imgDesc.createImage(false); - fImages.put(imgDesc, img); - } - return img; - } - -} Index: ui/org/eclipse/jdt/internal/ui/preferences/CodeAssistAdvancedPreferencePage.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/CodeAssistAdvancedPreferencePage.java,v retrieving revision 1.6 diff -u -r1.6 CodeAssistAdvancedPreferencePage.java --- ui/org/eclipse/jdt/internal/ui/preferences/CodeAssistAdvancedPreferencePage.java 27 Apr 2011 07:51:28 -0000 1.6 +++ ui/org/eclipse/jdt/internal/ui/preferences/CodeAssistAdvancedPreferencePage.java 11 Aug 2011 19:12:00 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Thomas Schlosser - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876 *******************************************************************************/ package org.eclipse.jdt.internal.ui.preferences; @@ -19,6 +20,7 @@ import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; import org.eclipse.jdt.internal.ui.IJavaHelpContextIds; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.CodeAssistAdvancedConfigurationBlock; public final class CodeAssistAdvancedPreferencePage extends PropertyAndPreferencePage { Index: ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.java,v retrieving revision 1.144 diff -u -r1.144 PreferencesMessages.java --- ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.java 28 Jul 2011 17:39:58 -0000 1.144 +++ ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.java 11 Aug 2011 19:12:00 -0000 @@ -11,6 +11,7 @@ * Sebastian Davids, sdavids@gmx.de - 187316 [preferences] Mark Occurences Pref Page; Link to * Benjamin Muskalla - [preferences] Add preference for new compiler warning: MissingSynchronizedModifierInInheritedMethod - https://bugs.eclipse.org/bugs/show_bug.cgi?id=245240 * Guven Demir - [package explorer] Alternative package name shortening: abbreviation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=299514 + * Thomas Schlosser - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876 *******************************************************************************/ package org.eclipse.jdt.internal.ui.preferences; @@ -41,16 +42,13 @@ public static String ClasspathVariablesPreferencePage_savechanges_message; public static String CleanUpPreferencePage_Description; public static String CleanUpPreferencePage_Title; - public static String CodeAssistAdvancedConfigurationBlock_default_table_category_column_title; - public static String CodeAssistAdvancedConfigurationBlock_default_table_description; - public static String CodeAssistAdvancedConfigurationBlock_default_table_keybinding_column_title; + public static String CodeAssistAdvancedConfigurationBlock_provided_table_category_column_title; + public static String CodeAssistAdvancedConfigurationBlock_provided_table_description; + public static String CodeAssistAdvancedConfigurationBlock_provided_table_keybinding_column_title; public static String CodeAssistAdvancedConfigurationBlock_key_binding_hint; + public static String CodeAssistAdvancedConfigurationBlock_proposal_list_table_title; public static String CodeAssistAdvancedConfigurationBlock_page_description; - public static String CodeAssistAdvancedConfigurationBlock_separate_table_category_column_title; - public static String CodeAssistAdvancedConfigurationBlock_separate_table_description; public static String CodeAssistAdvancedConfigurationBlock_no_shortcut; - public static String CodeAssistAdvancedConfigurationBlock_Up; - public static String CodeAssistAdvancedConfigurationBlock_Down; public static String CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout; public static String CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_emptyInput; public static String CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_invalidInput; Index: ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.properties,v retrieving revision 1.531 diff -u -r1.531 PreferencesMessages.properties --- ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.properties 28 Jul 2011 17:39:58 -0000 1.531 +++ ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.properties 11 Aug 2011 19:12:01 -0000 @@ -11,6 +11,7 @@ # Sebastian Davids, sdavids@gmx.de - 187316 [preferences] Mark Occurrences Pref Page; Link to # Benjamin Muskalla - [preferences] Add preference for new compiler warning: MissingSynchronizedModifierInInheritedMethod - https://bugs.eclipse.org/bugs/show_bug.cgi?id=245240 # Guven Demir - [package explorer] Alternative package name shortening: abbreviation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=299514 +# Thomas Schlosser - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876 ############################################################################### BuildPathsPropertyPage_error_message=An error occurred while setting the build path. @@ -849,15 +850,12 @@ CodeAssistAdvancedConfigurationBlock_page_description=Configure the behavior of the content assist ({0}) command. # stand-in text if there is no keyboard shortcut in above statement CodeAssistAdvancedConfigurationBlock_no_shortcut=no shortcut -CodeAssistAdvancedConfigurationBlock_default_table_description=&Select the proposal kinds contained in the 'default' content assist list: -CodeAssistAdvancedConfigurationBlock_default_table_category_column_title=Default Proposal Kinds -CodeAssistAdvancedConfigurationBlock_default_table_keybinding_column_title=Key Binding +CodeAssistAdvancedConfigurationBlock_provided_table_description=Drag proposal kinds to lists on the right to configure which proposals you want to have on each position while repeatedly invoking content assist. +CodeAssistAdvancedConfigurationBlock_provided_table_category_column_title=Proposal Kinds +CodeAssistAdvancedConfigurationBlock_provided_table_keybinding_column_title=Key Binding # do not translate the href argument (org.eclipse.ui.preferencePages.Keys) CodeAssistAdvancedConfigurationBlock_key_binding_hint=Individual key bindings can be assigned to each proposal kind on the 'Keys' preference page. -CodeAssistAdvancedConfigurationBlock_separate_table_description=&Content assist cycling: Select the proposal kinds that are cycled through when repeatedly invoking content assist: -CodeAssistAdvancedConfigurationBlock_separate_table_category_column_title=Separate Proposal Kinds -CodeAssistAdvancedConfigurationBlock_Up=&Up -CodeAssistAdvancedConfigurationBlock_Down=D&own +CodeAssistAdvancedConfigurationBlock_proposal_list_table_title={0}. Proposal List CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout=&Timeout for fetching a parameter name from attached Javadoc (ms): CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_emptyInput=Empty input. Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/CodeAssistAdvancedConfigurationBlock.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/CodeAssistAdvancedConfigurationBlock.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/CodeAssistAdvancedConfigurationBlock.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/CodeAssistAdvancedConfigurationBlock.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,423 @@ +/******************************************************************************* + * Copyright (c) 2005, 2011 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 + * Thomas Schlosser - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876 + *******************************************************************************/ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced; + +import java.util.Observable; +import java.util.Observer; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.Transfer; +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.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.core.commands.Command; +import org.eclipse.core.commands.ParameterizedCommand; + +import org.eclipse.core.runtime.Assert; + +import org.eclipse.jface.layout.PixelConverter; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; + +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.dialogs.PreferencesUtil; +import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; + +import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; + +import org.eclipse.jdt.core.JavaCore; + +import org.eclipse.jdt.internal.corext.util.Messages; + +import org.eclipse.jdt.ui.PreferenceConstants; + +import org.eclipse.jdt.internal.ui.dialogs.StatusInfo; +import org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock; +import org.eclipse.jdt.internal.ui.preferences.PreferencesMessages; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DragProvidedCategoriesListener; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DragState; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DropIntoProvidedListener; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListCategoryTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProvidedCategoryTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ImageHandler; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.KeyboardBindings; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ModelElement; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.ProposalListSection; +import org.eclipse.jdt.internal.ui.text.java.CompletionProposalComputerRegistry; +import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener; + + +/** + * + * @since 3.2 + */ +public final class CodeAssistAdvancedConfigurationBlock extends OptionsConfigurationBlock implements Observer { + + protected static final Key PREF_PROPOSAL_LISTS= getJDTUIKey(PreferenceConstants.CODEASSIST_PROPOSAL_LISTS); + + private static final Key PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC= getJDTCoreKey(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC); + + private static Key[] getAllKeys() { + return new Key[] { + PREF_PROPOSAL_LISTS, + PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC + }; + } + + private static final int NUMBER_OF_PAGE_COLUMNS= 2; + + private final class ProvidedTableLabelProvider 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; + } + } + } + + private final PreferenceModel fModel; + + private final ImageHandler fImageHandler; + + private TableViewer fProvidedViewer; + + private ProposalListSection fProposalListSection; + + public CodeAssistAdvancedConfigurationBlock(IStatusChangeListener statusListener, IWorkbenchPreferenceContainer container) { + super(statusListener, null, getAllKeys(), container); + fImageHandler= new ImageHandler(); + fModel= new PreferenceModel(CompletionProposalComputerRegistry.getDefault(), fImageHandler); + } + + /* + * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#createContents(org.eclipse.swt.widgets.Composite) + */ + @Override + public Control createContents(Composite parent) { + Composite composite= createWrappingComposite(parent); + + createPageDescription(composite); + + createProvidedSection(composite); + fProposalListSection= new ProposalListSection(composite, fModel, fImageHandler); + + createFiller(composite); + + createParameterTimeoutControl(composite); + + updateControls(); + selectFirstProvidedCategory(); + + addToObservable(); + + return composite; + } + + private Composite createWrappingComposite(Composite parent) { + Composite composite= new Composite(parent, SWT.NONE); + GridLayout layout= new GridLayout(NUMBER_OF_PAGE_COLUMNS, false); + layout.marginWidth= 0; + layout.marginHeight= 0; + composite.setLayout(layout); + return composite; + } + + private void createPageDescription(Composite composite) { + 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= KeyboardBindings.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, NUMBER_OF_PAGE_COLUMNS, 1); + gd.widthHint= width; + label.setLayoutData(gd); + } + + private void createProvidedSection(Composite composite) { + Composite providedContainer= new Composite(composite, SWT.NONE); + GridLayout layout= new GridLayout(); + layout.marginWidth= 0; + layout.marginHeight= 0; + providedContainer.setLayout(layout); + providedContainer.setLayoutData(new GridData(GridData.FILL_BOTH)); + + createProvidedViewer(providedContainer); + createProvidedLabel(providedContainer); + createKeysLink(providedContainer); + } + + private void createProvidedViewer(Composite composite) { + fProvidedViewer= new TableViewer(composite, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL); + Table table= fProvidedViewer.getTable(); + table.setHeaderVisible(true); + table.setLinesVisible(false); + GridData gridData= new GridData(SWT.FILL, SWT.FILL, true, true); + gridData.heightHint= 0; + table.setLayoutData(gridData); + + TableColumn nameColumn= new TableColumn(table, SWT.NONE); + nameColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_provided_table_category_column_title); + nameColumn.setResizable(false); + TableColumn keyColumn= new TableColumn(table, SWT.NONE); + keyColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_provided_table_keybinding_column_title); + keyColumn.setResizable(false); + + fProvidedViewer.setContentProvider(new ArrayContentProvider()); + ProvidedTableLabelProvider labelProvider= new ProvidedTableLabelProvider(); + fProvidedViewer.setLabelProvider(labelProvider); + fProvidedViewer.setInput(fModel.elements); + fProvidedViewer.setComparator(new ModelElement.ModelElementViewerComparator()); // sort alphabetically + + final int ICON_WIDTH= 16; + 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_WIDTH); + minKeyWidth= Math.max(minKeyWidth, computeWidth(table, labelProvider.getColumnText(fModel.elements.get(i), 1))); + } + nameColumn.setWidth(minNameWidth); + keyColumn.setWidth(minKeyWidth); + + // add drag support for provided categories + Transfer[] transferTypes= new Transfer[] { ProvidedCategoryTransfer.getInstance() }; + DragProvidedCategoriesListener dragListener= new DragProvidedCategoriesListener(fProvidedViewer); + DragState.addToObservable(dragListener); + fProvidedViewer.addDragSupport(ProposalTransfer.ALL_DRAG_OPERATIONS, transferTypes, dragListener); + + // add drop support for proposal lists and proposal list categories + transferTypes= new Transfer[] { ProposalListTransfer.getInstance(), ProposalListCategoryTransfer.getInstance() }; + DropIntoProvidedListener dropListener= new DropIntoProvidedListener(fModel); + dropListener.addUpdateObserver(this); + fProvidedViewer.addDropSupport(ProposalTransfer.ALL_DRAG_OPERATIONS, transferTypes, dropListener); + } + + private void createProvidedLabel(Composite composite) { + PixelConverter pixelConverter= new PixelConverter(composite); + int width= pixelConverter.convertWidthInCharsToPixels(40); + + Label label= new Label(composite, SWT.NONE | SWT.WRAP); + label.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_provided_table_description); + GridData gd= new GridData(GridData.FILL, GridData.FILL, true, false); + gd.widthHint= width; + label.setLayoutData(gd); + } + + private void createKeysLink(Composite composite) { + Link link= new Link(composite, SWT.NONE | SWT.WRAP); + link.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_key_binding_hint); + link.addSelectionListener(new SelectionAdapter() { + @Override + 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); + gd.widthHint= width; + link.setLayoutData(gd); + } + + private void createFiller(Composite composite) { + Label filler= new Label(composite, SWT.NONE); + filler.setVisible(false); + filler.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, NUMBER_OF_PAGE_COLUMNS, 1)); + } + + private void createParameterTimeoutControl(Composite composite) { + Composite timeoutComposite= new Composite(composite, SWT.NONE); + GridLayout layout= new GridLayout(4, false); + layout.marginWidth= 0; + layout.marginHeight= 0; + timeoutComposite.setLayout(layout); + GridData gd= new GridData(GridData.FILL, GridData.FILL, true, false, NUMBER_OF_PAGE_COLUMNS, 1); + timeoutComposite.setLayoutData(gd); + + PixelConverter pixelConverter= new PixelConverter(composite); + String str= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout; + addTextField(timeoutComposite, str, PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, 0, pixelConverter.convertWidthInCharsToPixels(7)); + } + + private void selectFirstProvidedCategory() { + if (fModel.elements.size() > 0) + fProvidedViewer.getTable().select(0); + } + + private void addToObservable() { + fModel.addObserver(this); + fProposalListSection.addUpdateObserver(this); + } + + /* + * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#settingsUpdated() + */ + @Override + protected void settingsUpdated() { + updatePreferenceModel(); + } + + /* + * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#updateControls() + */ + @Override + protected void updateControls() { + super.updateControls(); + fProvidedViewer.refresh(); + fProposalListSection.updateControls(); + } + + /* + * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#processChanges(org.eclipse.ui.preferences.IWorkbenchPreferenceContainer) + */ + @Override + protected boolean processChanges(IWorkbenchPreferenceContainer container) { + updatePreferenceModel(); + return super.processChanges(container); + } + + /* + * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock.Key, java.lang.String, java.lang.String) + */ + @Override + protected void validateSettings(Key changedKey, String oldValue, String newValue) { + if (changedKey == PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC) { + final StatusInfo status= new StatusInfo(); + if (newValue.length() == 0) + status.setError(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_emptyInput); + else { + try { + int number= Integer.parseInt(newValue); + int min= 0; + int max= 5000; + if (number < min || number > max) { + String msgFormat= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_invalidRange; + String msg= Messages.format(msgFormat, new Object[] { new Integer(min), new Integer(max) }); + status.setError(msg); + } + } catch (NumberFormatException ex) { + String msgFormat= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_invalidInput; + String msg= Messages.format(msgFormat, newValue); + status.setError(msg); + } + } + fContext.statusChanged(status); + } + } + + /* + * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#getFullBuildDialogStrings(boolean) + */ + @Override + protected String[] getFullBuildDialogStrings(boolean workspaceSettings) { + // no builds triggered by our settings + return null; + } + + /* + * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#dispose() + */ + @Override + public void dispose() { + fImageHandler.dispose(); + super.dispose(); + } + + protected 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(); + } + } + + public void update(Observable o, Object arg) { + if (arg == null) { + updateControls(); + } else { + String newValue= (String) arg; + updatePreferenceModel(newValue); + } + } + + private void updatePreferenceModel(String newValue) { + String oldValue= setProposalListsPrefsValue(newValue); + validateProposalListsPrefsSettings(oldValue, newValue); + updatePreferenceModel(); + } + + private void updatePreferenceModel() { + if (fModel != null) + fModel.updatePreferenceModel(getProposalListsPrefsValue()); + } + + protected String setProposalListsPrefsValue(String value) { + return setValue(CodeAssistAdvancedConfigurationBlock.PREF_PROPOSAL_LISTS, value); + } + + protected String getProposalListsPrefsValue() { + return getValue(CodeAssistAdvancedConfigurationBlock.PREF_PROPOSAL_LISTS); + } + + protected void validateProposalListsPrefsSettings(String oldValue, String newValue) { + validateSettings(CodeAssistAdvancedConfigurationBlock.PREF_PROPOSAL_LISTS, oldValue, newValue); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/AutoscrollDropTargetAdapter.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/AutoscrollDropTargetAdapter.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/AutoscrollDropTargetAdapter.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/AutoscrollDropTargetAdapter.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import java.util.Observable; +import java.util.Observer; +import java.util.Vector; + +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.DropTargetListener; +import org.eclipse.swt.graphics.Point; + +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util.AutoscrollObservable; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util.AutoscrollObserver; + +/** + * + * @since 3.8 + */ +public class AutoscrollDropTargetAdapter extends Observable implements DropTargetListener, AutoscrollObservable { + + private Vector fDragOverObservers; + + public AutoscrollDropTargetAdapter() { + this.fDragOverObservers= new Vector(); + } + + public void dragEnter(DropTargetEvent event) { + } + + public void dragLeave(DropTargetEvent event) { + } + + public void dragOperationChanged(DropTargetEvent event) { + } + + public void dragOver(DropTargetEvent event) { + notifyAutoscrollObservers(new Point(event.x, event.y)); + } + + public void drop(DropTargetEvent event) { + } + + public void dropAccept(DropTargetEvent event) { + } + + public synchronized void addUpdateObserver(Observer o) { + super.addObserver(o); + } + + protected void notifyUpdateObservers() { + setChanged(); + notifyObservers(); + } + + public synchronized void addAutoscrollObserver(AutoscrollObserver o) { + if (o == null) + throw new NullPointerException(); + if (!fDragOverObservers.contains(o)) { + fDragOverObservers.addElement(o); + } + } + + protected synchronized void notifyAutoscrollObservers(Point p) { + for (AutoscrollObserver o : fDragOverObservers) + o.autoScroll(p); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/AutoscrollDropTargetListener.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/AutoscrollDropTargetListener.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/AutoscrollDropTargetListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/AutoscrollDropTargetListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + + +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTargetEvent; + +/** + * + * @since 3.8 + */ +public class AutoscrollDropTargetListener extends AutoscrollDropTargetAdapter { + + @Override + public void dragEnter(DropTargetEvent event) { + event.detail= DND.DROP_NONE; + } + + @Override + public void dragOperationChanged(DropTargetEvent event) { + event.detail= DND.DROP_NONE; + } + + @Override + public void drop(DropTargetEvent event) { + event.detail= DND.DROP_NONE; + } + + @Override + public void dropAccept(DropTargetEvent event) { + event.detail= DND.DROP_NONE; + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/BaseDropTargetAdapter.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/BaseDropTargetAdapter.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/BaseDropTargetAdapter.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/BaseDropTargetAdapter.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + + +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.TransferData; + +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel; + +/** + * + * @since 3.8 + */ +public abstract class BaseDropTargetAdapter extends AutoscrollDropTargetAdapter { + + protected final PreferenceModel fModel; + + public BaseDropTargetAdapter(PreferenceModel model) { + this.fModel= model; + } + + @Override + public void dragEnter(DropTargetEvent event) { + event.detail= this.getCompatibleOperation(event.detail, event.operations, event.currentDataType); + } + + @Override + public void dragOperationChanged(DropTargetEvent event) { + event.detail= this.getCompatibleOperation(event.detail, event.operations, event.currentDataType); + } + + @Override + public void dragOver(DropTargetEvent event) { + super.dragOver(event); + event.feedback= DND.FEEDBACK_NONE; + } + + @Override + public void drop(DropTargetEvent event) { + if (!isValidProposalTransferTypeArray(event.data)) { + event.detail= DND.DROP_NONE; + return; + } + ProposalTransferType[] data= (ProposalTransferType[]) event.data; + boolean successfulTransfer= dropProposalTransfers(data, event.detail); + if (successfulTransfer) + notifyUpdateObservers(); + else + event.detail= DND.DROP_NONE; + } + + private boolean isValidProposalTransferTypeArray(Object data) { + if (data == null || !(data instanceof ProposalTransferType[])) + return false; + return true; + } + + protected abstract boolean dropProposalTransfers(ProposalTransferType[] data, int detail); + + protected final boolean isProvidedListCategory(ProposalTransferType data) { + return data.getListIndex() == null && fModel.isValidCategoryId(data.getCategoryId()); + } + + protected final boolean isProposalList(ProposalTransferType data) { + return data.getListIndex() != null && data.getCategoryId() == null; + } + + protected final boolean isProposalListCategory(ProposalTransferType data) { + return data.getListIndex() != null && fModel.isValidCategoryId(data.getCategoryId()); + } + + protected int getCompatibleOperation(int operation, int supportedOperations, TransferData currentDataType) { + int result= ProvidedCategoryTransfer.getInstance().getCompatibleOperation(operation, supportedOperations, currentDataType); + if (result != -1) + return result; + result= ProposalListTransfer.getInstance().getCompatibleOperation(operation, supportedOperations, currentDataType); + if (result != -1) + return result; + result= ProposalListCategoryTransfer.getInstance().getCompatibleOperation(operation, supportedOperations, currentDataType); + if (result != -1) + return result; + return DND.DROP_NONE; + } + +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragCategoriesListener.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragCategoriesListener.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragCategoriesListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragCategoriesListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import java.util.Iterator; +import java.util.Observable; + +import org.eclipse.swt.dnd.DragSourceEvent; +import org.eclipse.swt.dnd.DragSourceListener; +import org.eclipse.swt.dnd.TransferData; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TableViewer; + +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ModelElement; + +/** + * + * @since 3.8 + */ +public abstract class DragCategoriesListener extends Observable implements DragSourceListener { + private final TableViewer fViewer; + + public DragCategoriesListener(TableViewer viewer) { + this.fViewer= viewer; + } + + public void dragSetData(DragSourceEvent event) { + if (isSupportedDataType(event.dataType)) { + IStructuredSelection selection= (IStructuredSelection) fViewer.getSelection(); + if (selection != null && !selection.isEmpty()) + event.data= getTransferData(selection); + } + } + + protected abstract boolean isSupportedDataType(TransferData dataType); + + private ProposalTransferType[] getTransferData(IStructuredSelection selection) { + ProposalTransferType[] transferData= new ProposalTransferType[selection.size()]; + int i= 0; + for (Iterator meIt= selection.iterator(); meIt.hasNext();) { + ModelElement me= meIt.next(); + if (me != null) + transferData[i++]= createProposalTransferElement(me); + } + return transferData; + } + + protected abstract ProposalTransferType createProposalTransferElement(ModelElement me); + + public void dragStart(DragSourceEvent event) { + if (fViewer.getSelection() == null || fViewer.getSelection().isEmpty()) + event.doit= false; + else { + setChanged(); + notifyObservers(Boolean.TRUE); + } + } + + public void dragFinished(DragSourceEvent event) { + setChanged(); + notifyObservers(Boolean.FALSE); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProposalListCategoriesListener.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProposalListCategoriesListener.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProposalListCategoriesListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProposalListCategoriesListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import org.eclipse.swt.dnd.TransferData; + +import org.eclipse.jface.viewers.TableViewer; + +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ModelElement; + +/** + * + * @since 3.8 + */ +public final class DragProposalListCategoriesListener extends DragCategoriesListener { + private final Integer fListIndex; + + public DragProposalListCategoriesListener(TableViewer viewer, int listIndex) { + super(viewer); + this.fListIndex= Integer.valueOf(listIndex); + } + + @Override + protected boolean isSupportedDataType(TransferData dataType) { + return ProposalListCategoryTransfer.getInstance().isSupportedType(dataType); + } + + @Override + protected ProposalTransferType createProposalTransferElement(ModelElement me) { + return new ProposalTransferType(me.getId(), fListIndex); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProposalListListener.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProposalListListener.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProposalListListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProposalListListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import java.util.Observable; + +import org.eclipse.swt.dnd.DragSourceEvent; +import org.eclipse.swt.dnd.DragSourceListener; + +/** + * + * @since 3.8 + */ +public final class DragProposalListListener extends Observable implements DragSourceListener { + private final Integer fListIndex; + + public DragProposalListListener(int listIndex) { + this.fListIndex= Integer.valueOf(listIndex); + } + + public void dragSetData(DragSourceEvent event) { + if (ProposalListTransfer.getInstance().isSupportedType(event.dataType)) { + event.data= new ProposalTransferType[] { new ProposalTransferType(fListIndex) }; + } + } + + public void dragStart(DragSourceEvent event) { + setChanged(); + notifyObservers(Boolean.TRUE); + } + + public void dragFinished(DragSourceEvent event) { + setChanged(); + notifyObservers(Boolean.FALSE); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProvidedCategoriesListener.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProvidedCategoriesListener.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProvidedCategoriesListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProvidedCategoriesListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import org.eclipse.swt.dnd.TransferData; + +import org.eclipse.jface.viewers.TableViewer; + +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ModelElement; + +/** + * + * @since 3.8 + */ +public final class DragProvidedCategoriesListener extends DragCategoriesListener { + + public DragProvidedCategoriesListener(TableViewer viewer) { + super(viewer); + } + + @Override + protected boolean isSupportedDataType(TransferData dataType) { + return ProvidedCategoryTransfer.getInstance().isSupportedType(dataType); + } + + @Override + protected ProposalTransferType createProposalTransferElement(ModelElement me) { + return new ProposalTransferType(me.getId()); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragState.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragState.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragState.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragState.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import java.util.Observable; +import java.util.Observer; + +/** + * + * @since 3.8 + */ +public class DragState implements Observer { + + private boolean dragged; + + private static DragState instance= new DragState(); + + private DragState() { + } + + public static DragState getInstance() { + return instance; + } + + public void update(Observable o, Object arg) { + if (arg != null && arg instanceof Boolean) + dragged= (((Boolean) arg).booleanValue()); + } + + public static boolean isDragged() { + return getInstance().dragged; + } + + public static boolean isNotDragged() { + return !getInstance().dragged; + } + + public static void addToObservable(Observable o) { + o.addObserver(getInstance()); + } + +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropHighlightListener.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropHighlightListener.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropHighlightListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropHighlightListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import java.util.Vector; + +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTargetEvent; + +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util.HighlightObservable; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util.HighlightObserver; + +/** + * + * @since 3.8 + */ +public abstract class DropHighlightListener extends BaseDropTargetAdapter implements HighlightObservable { + + private Vector fHighlightObservers; + + public DropHighlightListener(PreferenceModel model) { + super(model); + this.fHighlightObservers= new Vector(); + } + + @Override + public void dragLeave(DropTargetEvent event) { + notifyHighlightObservers(false); + } + + @Override + public void dragOperationChanged(DropTargetEvent event) { + super.dragOperationChanged(event); + if (event.detail == DND.DROP_NONE) + notifyHighlightObservers(false); + } + + @Override + public void dragOver(DropTargetEvent event) { + super.dragOver(event); + if (event.detail != DND.DROP_NONE) + notifyHighlightObservers(true); + } + + @Override + public void dropAccept(DropTargetEvent event) { + if (!(ProvidedCategoryTransfer.getInstance().isSupportedType(event.currentDataType) || + ProposalListCategoryTransfer.getInstance().isSupportedType(event.currentDataType) || ProposalListTransfer.getInstance().isSupportedType(event.currentDataType))) + event.detail= DND.DROP_NONE; + } + + public synchronized void addHighlightObserver(HighlightObserver o) { + if (o == null) + throw new NullPointerException(); + if (!fHighlightObservers.contains(o)) { + fHighlightObservers.addElement(o); + } + } + + protected synchronized void notifyHighlightObservers(boolean highlight) { + for (HighlightObserver o : fHighlightObservers) + o.highlight(highlight); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropIntoProposalListListener.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropIntoProposalListListener.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropIntoProposalListListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropIntoProposalListListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import org.eclipse.swt.dnd.DND; + +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel; + +/** + * + * @since 3.8 + */ +public final class DropIntoProposalListListener extends DropHighlightListener { + + private final int fListIndex; + + public DropIntoProposalListListener(int listIndex, PreferenceModel model) { + super(model); + this.fListIndex= listIndex; + } + + @Override + protected boolean dropProposalTransfers(ProposalTransferType[] data, int detail) { + boolean successfulTransfer= false; + for (ProposalTransferType ptt : data) + successfulTransfer|= drop(ptt, detail); + return successfulTransfer; + } + + private boolean drop(ProposalTransferType data, int detail) { + if (data == null || isSourceEqualTarget(data.getListIndex())) + return false; + + if (isProvidedListCategory(data)) + return dropProvidedListCategory(data, detail); + if (isProposalList(data)) + return dropProposalList(data.getListIndex(), detail); + if (isProposalListCategory(data)) + return dropProposalListCategory(data, data.getListIndex(), detail); + + return false; + } + + private boolean isSourceEqualTarget(Integer sourceListIndex) { + return sourceListIndex != null && sourceListIndex.intValue() == fListIndex; + } + + private boolean dropProvidedListCategory(ProposalTransferType data, int detail) { + switch (detail) { + case DND.DROP_COPY: + copyElementToList(data.getCategoryId()); + break; + default: + return false; + } + return true; + } + + private boolean dropProposalList(Integer sourceListIndex, int detail) { + switch (detail) { + case DND.DROP_COPY: + copyAllElementsToList(sourceListIndex.intValue()); + break; + case DND.DROP_MOVE: + moveAllElementsToList(sourceListIndex.intValue()); + break; + default: + return false; + } + return true; + } + + private boolean dropProposalListCategory(ProposalTransferType data, Integer sourceListIndex, int detail) { + switch (detail) { + case DND.DROP_COPY: + copyElementToList(data.getCategoryId()); + break; + case DND.DROP_MOVE: + moveElementToList(data.getCategoryId(), sourceListIndex.intValue()); + break; + default: + return false; + } + return true; + } + + private void copyAllElementsToList(int sourceListIndex) { + fModel.mergeLists(sourceListIndex, fListIndex, false); + } + + private void moveAllElementsToList(int sourceListIndex) { + fModel.mergeLists(sourceListIndex, fListIndex, true); + } + + private void copyElementToList(String categoryId) { + fModel.getElement(categoryId).setInProposalList(fListIndex); + } + + private void moveElementToList(String categoryId, int sourceListIndex) { + fModel.getElement(categoryId).moveToProposalList(sourceListIndex, fListIndex); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropIntoProvidedListener.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropIntoProvidedListener.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropIntoProvidedListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropIntoProvidedListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.TransferData; + +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel; + +/** + * + * @since 3.8 + */ +public final class DropIntoProvidedListener extends BaseDropTargetAdapter { + + public DropIntoProvidedListener(PreferenceModel model) { + super(model); + } + + @Override + protected boolean dropProposalTransfers(ProposalTransferType[] data, int detail) { + boolean successfulTransfer= false; + for (ProposalTransferType ptt : data) + successfulTransfer|= drop(ptt); + return successfulTransfer; + } + + private boolean drop(ProposalTransferType data) { + if (data == null) + return false; + + if (isProposalList(data)) + return dropProposalList(data.getListIndex()); + if (isProposalListCategory(data)) + return dropProposalListCategory(data, data.getListIndex()); + + return false; + } + + private boolean dropProposalList(Integer sourceListIndex) { + fModel.removeList(sourceListIndex.intValue()); + return true; + } + + private boolean dropProposalListCategory(ProposalTransferType data, Integer sourceListIndex) { + fModel.getElement(data.getCategoryId()).removeInProposalList(sourceListIndex.intValue()); + return true; + } + + @Override + public void dropAccept(DropTargetEvent event) { + if (!(ProposalListCategoryTransfer.getInstance().isSupportedType(event.currentDataType) || ProposalListTransfer.getInstance().isSupportedType(event.currentDataType))) + event.detail= DND.DROP_NONE; + } + + @Override + protected int getCompatibleOperation(int detail, int operations, TransferData currentDataType) { + int operation= super.getCompatibleOperation(detail, operations, currentDataType); + if (operation != DND.DROP_MOVE) + return DND.DROP_NONE; + return operation; + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropNewProposalListListener.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropNewProposalListListener.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropNewProposalListListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropNewProposalListListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.swt.dnd.DND; + +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel; + +/** + * + * @since 3.8 + */ +public final class DropNewProposalListListener extends DropHighlightListener { + + private final int fListIndex; + + private final class RemoveCategoryEntry implements Comparable { + final String fCategoryId; + + final Integer fIndex; + + private RemoveCategoryEntry(String categoryId, Integer index) { + this.fCategoryId= categoryId; + this.fIndex= index; + } + + public int compareTo(RemoveCategoryEntry o) { + return o.fIndex.compareTo(this.fIndex); // reverse order + } + } + + public DropNewProposalListListener(int listIndex, PreferenceModel model) { + super(model); + this.fListIndex= listIndex; + } + + @Override + protected boolean dropProposalTransfers(ProposalTransferType[] data, int detail) { + if (data == null || data.length == 0) + return false; + + if (isProvidedListCategory(data[0])) + return dropProvidedListCategories(data, detail); + if (isProposalList(data[0])) + return dropProposalList(data[0].getListIndex(), detail); + if (isProposalListCategory(data[0])) + return dropProposalListCategories(data, detail); + + return false; + } + + private boolean dropProvidedListCategories(ProposalTransferType[] data, int detail) { + switch (detail) { + case DND.DROP_COPY: + copyCategoriesToNewList(getCategoryIds(data)); + break; + default: + return false; + } + return true; + } + + private boolean dropProposalList(Integer sourceListIndex, int detail) { + int sourceIndex= sourceListIndex.intValue(); + switch (detail) { + case DND.DROP_COPY: + copyCategoriesToNewList(getCategoryIdsFromModel(sourceIndex)); + break; + case DND.DROP_MOVE: + if (isSourceUnequalTarget(sourceIndex)) + moveList(sourceIndex); + else + return false; + break; + default: + return false; + } + return true; + } + + private boolean dropProposalListCategories(ProposalTransferType[] data, int detail) { + switch (detail) { + case DND.DROP_MOVE: + copyCategoriesToNewList(getCategoryIds(data)); + removeCategories(data); + break; + case DND.DROP_COPY: + copyCategoriesToNewList(getCategoryIds(data)); + break; + default: + return false; + } + return true; + } + + private void copyCategoriesToNewList(List categoryIds) { + fModel.addNewList(fListIndex, categoryIds); + } + + private boolean isSourceUnequalTarget(int sourceIndex) { + return sourceIndex != fListIndex && sourceIndex + 1 != fListIndex; + } + + private void moveList(int sourceIndex) { + fModel.moveList(sourceIndex, fListIndex); + } + + private List getCategoryIds(ProposalTransferType[] data) { + List ids= new ArrayList(data.length); + for (ProposalTransferType ptt : data) + ids.add(ptt.getCategoryId()); + return ids; + } + + private List getCategoryIdsFromModel(int listIndex) { + return fModel.getCategoryIds(listIndex); + } + + private void removeCategories(ProposalTransferType[] data) { + removeCategories(getSortedRemoveCategories(data)); + } + + private List getSortedRemoveCategories(ProposalTransferType[] data) { + List indices= new ArrayList(data.length); + for (ProposalTransferType ptt : data) { + if (ptt.getListIndex() == null) + continue; + int sourceIndex= ptt.getListIndex().intValue(); + int removeIndex= fListIndex > sourceIndex ? sourceIndex : sourceIndex + 1; + indices.add(new RemoveCategoryEntry(ptt.getCategoryId(), Integer.valueOf(removeIndex))); + } + Collections.sort(indices); + return indices; + } + + private void removeCategories(List categories) { + for (RemoveCategoryEntry cat : categories) + removeCategory(cat); + } + + private void removeCategory(RemoveCategoryEntry category) { + fModel.getElement(category.fCategoryId).removeInProposalList(category.fIndex.intValue()); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalListCategoryTransfer.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalListCategoryTransfer.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalListCategoryTransfer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalListCategoryTransfer.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import org.eclipse.swt.dnd.DND; + +/** + * + * @since 3.8 + */ +public final class ProposalListCategoryTransfer extends ProposalTransfer { + private static final String TRANSFER_NAME= "ProposalListCategoryTransfer"; //$NON-NLS-1$ + + private static final ProposalListCategoryTransfer instance= new ProposalListCategoryTransfer(); + + private ProposalListCategoryTransfer() { + super(TRANSFER_NAME); + } + + public static ProposalListCategoryTransfer getInstance() { + return instance; + } + + @Override + public int getDefaultOperation(int supportedOperations) { + if ((supportedOperations & DND.DROP_MOVE) != 0) + return DND.DROP_MOVE; + else if ((supportedOperations & DND.DROP_COPY) != 0) + return DND.DROP_COPY; + return DND.DROP_NONE; + } + + @Override + public boolean isSupportedOperation(int operation) { + return operation == DND.DROP_COPY || operation == DND.DROP_MOVE; + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalListTransfer.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalListTransfer.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalListTransfer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalListTransfer.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import org.eclipse.swt.dnd.DND; + +/** + * + * @since 3.8 + */ +public final class ProposalListTransfer extends ProposalTransfer { + private static final String TRANSFER_NAME= "ProposalListTransfer"; //$NON-NLS-1$ + + private static final ProposalListTransfer instance= new ProposalListTransfer(); + + private ProposalListTransfer() { + super(TRANSFER_NAME); + } + + public static ProposalListTransfer getInstance() { + return instance; + } + + @Override + public int getDefaultOperation(int supportedOperations) { + if ((supportedOperations & DND.DROP_MOVE) != 0) + return DND.DROP_MOVE; + else if ((supportedOperations & DND.DROP_COPY) != 0) + return DND.DROP_COPY; + return DND.DROP_NONE; + } + + @Override + public boolean isSupportedOperation(int operation) { + return operation == DND.DROP_COPY || operation == DND.DROP_MOVE; + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalTransfer.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalTransfer.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalTransfer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalTransfer.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.dnd.ByteArrayTransfer; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.TransferData; + +/** + * + * @since 3.8 + */ +public abstract class ProposalTransfer extends ByteArrayTransfer { + public static final int ALL_DRAG_OPERATIONS= DND.DROP_COPY | DND.DROP_DEFAULT | DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_TARGET_MOVE; + + private final String fTransferName; + + private final int fTransferId; + + protected ProposalTransfer(String transferName) { + this.fTransferName= transferName; + this.fTransferId= registerType(transferName); + } + + public abstract int getDefaultOperation(int supportedOperations); + + public abstract boolean isSupportedOperation(int operation); + + @Override + public void javaToNative(Object object, TransferData transferData) { + if (!checkProposalTransferType(object) || !isSupportedType(transferData)) + DND.error(DND.ERROR_INVALID_DATA); + ProposalTransferType[] props= (ProposalTransferType[]) object; + ByteArrayOutputStream out= new ByteArrayOutputStream(); + DataOutputStream writeOut= new DataOutputStream(out); + try { + for (int i= 0, length= props.length; i < length; i++) { + if (props[i].getCategoryId() != null) { + byte[] buffer= props[i].getCategoryId().getBytes(); + writeOut.writeInt(buffer.length); + writeOut.write(buffer); + } else + writeOut.writeInt(0); + Integer index= props[i].getListIndex(); + writeOut.writeInt(index == null ? -1 : index.intValue()); + } + byte[] buffer= out.toByteArray(); + super.javaToNative(buffer, transferData); + } catch (IOException e) { + } finally { + try { + writeOut.close(); + } catch (IOException e) { + } + } + } + + @Override + public Object nativeToJava(TransferData transferData) { + if (isSupportedType(transferData)) { + byte[] buffer= (byte[]) super.nativeToJava(transferData); + if (buffer == null) + return null; + + List props= new ArrayList(); + ByteArrayInputStream in= new ByteArrayInputStream(buffer); + DataInputStream readIn= new DataInputStream(in); + try { + while (readIn.available() > 0) { + ProposalTransferType proposal= new ProposalTransferType(); + int size= readIn.readInt(); + if (size == 0) + proposal.setCategoryId(null); + else { + byte[] id= new byte[size]; + readIn.read(id); + proposal.setCategoryId(new String(id)); + } + int index= readIn.readInt(); + proposal.setListIndex(index < 0 ? null : Integer.valueOf(index)); + props.add(proposal); + } + } catch (IOException ex) { + return null; + } finally { + try { + readIn.close(); + } catch (IOException e) { + return null; + } + } + return props.toArray(new ProposalTransferType[0]); + } + return null; + } + + @Override + protected int[] getTypeIds() { + return new int[] { fTransferId }; + } + + @Override + protected String[] getTypeNames() { + return new String[] { fTransferName }; + } + + @Override + protected boolean validate(Object object) { + return checkProposalTransferType(object); + } + + public int getCompatibleOperation(int operation, int supportedOperations, TransferData currentDataType) { + if (this.isSupportedType(currentDataType)) { + if (operation == DND.DROP_DEFAULT) + return this.getDefaultOperation(supportedOperations); + if (this.isSupportedOperation(operation) && (supportedOperations & operation) != 0) + return operation; + return DND.DROP_NONE; + } + return -1; + } + + private boolean checkProposalTransferType(Object object) { + if (object == null || !(object instanceof ProposalTransferType[]) || ((ProposalTransferType[]) object).length == 0) + return false; + ProposalTransferType[] cats= (ProposalTransferType[]) object; + for (ProposalTransferType category : cats) + if (category == null || ((category.getCategoryId() == null || category.getCategoryId().length() == 0) && category.getListIndex() == null)) + return false; + return true; + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalTransferType.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalTransferType.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalTransferType.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalTransferType.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +/** + * + * @since 3.8 + */ +public final class ProposalTransferType { + private Integer fListIndex; + + private String fCategoryId; + + public ProposalTransferType() { + } + + public ProposalTransferType(String categoryId) { + this.fCategoryId= categoryId; + } + + public ProposalTransferType(Integer listIndex) { + this.fListIndex= listIndex; + } + + public ProposalTransferType(String categoryId, Integer listIndex) { + this.fCategoryId= categoryId; + this.fListIndex= listIndex; + } + + public Integer getListIndex() { + return fListIndex; + } + + public void setListIndex(Integer listIndex) { + fListIndex= listIndex; + } + + public String getCategoryId() { + return fCategoryId; + } + + public void setCategoryId(String categoryId) { + fCategoryId= categoryId; + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProvidedCategoryTransfer.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProvidedCategoryTransfer.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProvidedCategoryTransfer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProvidedCategoryTransfer.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd; + +import org.eclipse.swt.dnd.DND; + +/** + * + * @since 3.8 + */ +public final class ProvidedCategoryTransfer extends ProposalTransfer { + private static final String TRANSFER_NAME= "ProvidedCategoryTransfer"; //$NON-NLS-1$ + + private static final ProvidedCategoryTransfer instance= new ProvidedCategoryTransfer(); + + private ProvidedCategoryTransfer() { + super(TRANSFER_NAME); + } + + public static ProvidedCategoryTransfer getInstance() { + return instance; + } + + @Override + public int getDefaultOperation(int supportedOperations) { + if ((supportedOperations & DND.DROP_COPY) != 0) + return DND.DROP_COPY; + return DND.DROP_NONE; + } + + @Override + public boolean isSupportedOperation(int operation) { + return operation == DND.DROP_COPY; + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/ImageHandler.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/ImageHandler.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/ImageHandler.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/ImageHandler.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.swt.graphics.Image; + +import org.eclipse.jface.resource.ImageDescriptor; + +/** + * + * @since 3.8 + */ +public class ImageHandler { + + private final Map fImages= new HashMap(); + + public Image getImage(ImageDescriptor imgDesc) { + if (imgDesc == null) + return null; + + Image img= fImages.get(imgDesc); + if (img == null) { + img= imgDesc.createImage(false); + fImages.put(imgDesc, img); + } + return img; + } + + public void dispose() { + for (Iterator it= fImages.values().iterator(); it.hasNext();) { + Image image= it.next(); + image.dispose(); + } + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/KeyboardBindings.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/KeyboardBindings.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/KeyboardBindings.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/KeyboardBindings.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model; + +import org.eclipse.core.commands.CommandManager; +import org.eclipse.core.commands.ParameterizedCommand; +import org.eclipse.core.commands.common.NotDefinedException; +import org.eclipse.core.commands.contexts.ContextManager; + +import org.eclipse.jface.bindings.BindingManager; +import org.eclipse.jface.bindings.Scheme; +import org.eclipse.jface.bindings.TriggerSequence; + +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.keys.IBindingService; + +import org.eclipse.jdt.internal.ui.JavaPlugin; + +/** + * + * @since 3.8 + */ +public class KeyboardBindings { + private static BindingManager fgLocalBindingManager; + static { + fgLocalBindingManager= new BindingManager(new ContextManager(), new CommandManager()); + final IBindingService bindingService= (IBindingService) PlatformUI.getWorkbench().getService(IBindingService.class); + final Scheme[] definedSchemes= bindingService.getDefinedSchemes(); + if (definedSchemes != null) { + try { + for (int i= 0; i < definedSchemes.length; i++) { + final Scheme scheme= definedSchemes[i]; + final Scheme copy= fgLocalBindingManager.getScheme(scheme.getId()); + copy.define(scheme.getName(), scheme.getDescription(), scheme.getParentId()); + } + } catch (final NotDefinedException e) { + JavaPlugin.log(e); + } + } + fgLocalBindingManager.setLocale(bindingService.getLocale()); + fgLocalBindingManager.setPlatform(bindingService.getPlatform()); + } + + public static String getKeyboardShortcut(ParameterizedCommand command) { + IBindingService bindingService= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class); + fgLocalBindingManager.setBindings(bindingService.getBindings()); + try { + Scheme activeScheme= bindingService.getActiveScheme(); + if (activeScheme != null) + fgLocalBindingManager.setActiveScheme(activeScheme); + } catch (NotDefinedException e) { + JavaPlugin.log(e); + } + + TriggerSequence[] bindings= fgLocalBindingManager.getActiveBindingsDisregardingContextFor(command); + if (bindings.length > 0) + return bindings[0].format(); + return null; + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/ModelElement.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/ModelElement.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/ModelElement.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/ModelElement.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model; + +import java.util.Comparator; +import java.util.Set; + +import org.eclipse.swt.graphics.Image; + +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.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; + +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; + +import org.eclipse.jdt.internal.ui.text.java.CompletionProposalCategory; + +/** + * + * @since 3.8 + */ +public final class ModelElement { + + public static final class ModelElementComparator implements Comparator { + public int compare(ModelElement o1, ModelElement o2) { + return o1.getName().compareTo(o2.getName()); + } + } + + public static final class ModelElementViewerComparator extends ViewerComparator { + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + ModelElement m1= (ModelElement) e1; + ModelElement m2= (ModelElement) e2; + return new ModelElementComparator().compare(m1, m2); + } + } + + private final ImageHandler fImageHandler; + + private final CompletionProposalCategory fCategory; + + private final Command fCommand; + + private final IParameter fParam; + + private final PreferenceModel fPreferenceModel; + + ModelElement(CompletionProposalCategory category, PreferenceModel model, ImageHandler imageHandler) { + fCategory= category; + ICommandService commandSvc= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class); + fCommand= commandSvc.getCommand("org.eclipse.jdt.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; + fImageHandler= imageHandler; + } + + public Image getImage() { + return fImageHandler.getImage(fCategory.getImageDescriptor()); + } + + public String getName() { + return fCategory.getDisplayName(); + } + + public String getKeybindingAsString() { + final Parameterization[] params= { new Parameterization(fParam, fCategory.getId()) }; + final ParameterizedCommand pCmd= new ParameterizedCommand(fCommand, params); + String key= KeyboardBindings.getKeyboardShortcut(pCmd); + return key; + } + + public Set getProposalListIndices() { + return fCategory.getProposalListIndices(); + } + + public boolean isInProposalList(int index) { + return getProposalListIndices().contains(Integer.valueOf(index)); + } + + public void setInProposalList(int index) { + if (!isInProposalList(index)) + fPreferenceModel.changeSingleCategory(this, Integer.valueOf(index), null); + } + + public void moveToProposalList(int sourceIndex, int targetIndex) { + if (!isInProposalList(targetIndex) || isInProposalList(sourceIndex)) + fPreferenceModel.changeSingleCategory(this, Integer.valueOf(targetIndex), Integer.valueOf(sourceIndex)); + } + + public void removeInProposalList(int index) { + if (isInProposalList(index)) + fPreferenceModel.changeSingleCategory(this, null, Integer.valueOf(index)); + } + + public String getId() { + return fCategory.getId(); + } + + void updateIndices(Set indices) { + fCategory.clearProposalListIndices(); + fCategory.addAllProposalListIndices(indices); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/PreferenceModel.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/PreferenceModel.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/PreferenceModel.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/PreferenceModel.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,231 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Observable; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeMap; + +import org.eclipse.jdt.internal.ui.text.java.CompletionProposalCategory; +import org.eclipse.jdt.internal.ui.text.java.CompletionProposalComputerRegistry; + +/** + * + * @since 3.8 + */ +public final class PreferenceModel extends Observable { + 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. + */ + public final List elements; + + public PreferenceModel(CompletionProposalComputerRegistry registry, ImageHandler imageHandler) { + List categories= registry.getProposalCategories(); + fElements= new ArrayList(); + for (CompletionProposalCategory category : categories) + if (category.hasComputers()) + fElements.add(new ModelElement(category, this, imageHandler)); + elements= Collections.unmodifiableList(fElements); + } + + public void changeSingleCategory(ModelElement changed, Integer addIndex, Integer removeIndex) { + int initialBufferSize= 50 * fElements.size(); + Map proposalListsCategories= new TreeMap(); + for (ModelElement item : fElements) { + Set indices= new HashSet(item.getProposalListIndices()); + if (changed == item) { + if (addIndex != null) + indices.add(addIndex); + if (removeIndex != null) + indices.remove(removeIndex); + } + for (Integer index : indices) { + StringBuffer buf= proposalListsCategories.get(index); + if (buf == null) { + buf= new StringBuffer(initialBufferSize); + proposalListsCategories.put(index, buf); + } + buf.append(item.getId()); + buf.append(COLON); + } + } + writeProposalListsPreferences(proposalListsCategories, initialBufferSize); + } + + public void removeList(int listIndex) { + int initialBufferSize= 50 * fElements.size(); + Map proposalListsCategories= new TreeMap(); + for (ModelElement item : fElements) { + for (int index : item.getProposalListIndices()) { + if (listIndex == index) + continue; + else if (index > listIndex) + index--; + StringBuffer buf= proposalListsCategories.get(Integer.valueOf(index)); + if (buf == null) { + buf= new StringBuffer(initialBufferSize); + proposalListsCategories.put(Integer.valueOf(index), buf); + } + buf.append(item.getId()); + buf.append(COLON); + } + } + writeProposalListsPreferences(proposalListsCategories, initialBufferSize); + } + + public void addNewList(int listIndex, List categoryIds) { + int initialBufferSize= 50 * fElements.size(); + Map proposalListsCategories= new TreeMap(); + for (ModelElement item : fElements) { + for (int index : item.getProposalListIndices()) { + if (index >= listIndex) + index++; + StringBuffer buf= proposalListsCategories.get(Integer.valueOf(index)); + if (buf == null) { + buf= new StringBuffer(initialBufferSize); + proposalListsCategories.put(Integer.valueOf(index), buf); + } + buf.append(item.getId()); + buf.append(COLON); + } + } + if (categoryIds != null && !categoryIds.isEmpty()) { + // add categories to new list + StringBuffer newListBuf= new StringBuffer(initialBufferSize); + proposalListsCategories.put(Integer.valueOf(listIndex), newListBuf); + for (String catId : categoryIds) { + newListBuf.append(catId); + newListBuf.append(COLON); + } + } + writeProposalListsPreferences(proposalListsCategories, initialBufferSize); + } + + public void moveList(int listIndex, int targetIndex) { + int initialBufferSize= 50 * fElements.size(); + Map proposalListsCategories= new TreeMap(); + for (ModelElement item : fElements) { + for (int index : item.getProposalListIndices()) { + if (index > listIndex && index < targetIndex) + index--; + else if (index >= targetIndex && index < listIndex) + index++; + else if (index == listIndex) + index= listIndex < targetIndex ? targetIndex - 1 : targetIndex; + StringBuffer buf= proposalListsCategories.get(Integer.valueOf(index)); + if (buf == null) { + buf= new StringBuffer(initialBufferSize); + proposalListsCategories.put(Integer.valueOf(index), buf); + } + buf.append(item.getId()); + buf.append(COLON); + } + } + writeProposalListsPreferences(proposalListsCategories, initialBufferSize); + } + + public void mergeLists(int sourceIndex, int targetIndex, boolean removeSource) { + int initialBufferSize= 50 * fElements.size(); + Map proposalListsCategories= new TreeMap(); + for (ModelElement item : fElements) { + Set indices= new HashSet(item.getProposalListIndices()); + if (indices.contains(Integer.valueOf(sourceIndex))) { + if (removeSource) + indices.remove(Integer.valueOf(sourceIndex)); + indices.add(Integer.valueOf(targetIndex)); + } + for (Integer index : indices) { + StringBuffer buf= proposalListsCategories.get(index); + if (buf == null) { + buf= new StringBuffer(initialBufferSize); + proposalListsCategories.put(index, buf); + } + buf.append(item.getId()); + buf.append(COLON); + } + } + writeProposalListsPreferences(proposalListsCategories, initialBufferSize); + } + + private void writeProposalListsPreferences(Map proposalListsCategories, int initialBufferSize) { + StringBuffer buf= new StringBuffer(initialBufferSize * proposalListsCategories.size()); + for (StringBuffer proposalList : proposalListsCategories.values()) { + buf.append(proposalList); + buf.append(SEPARATOR); + } + String newValue= buf.toString(); + setChanged(); + notifyObservers(newValue); + } + + public void updatePreferenceModel(String newValue) { + Map> newConfig= new HashMap>(); + StringTokenizer tok= new StringTokenizer(newValue, SEPARATOR); + for (int listIndex= 0; tok.hasMoreTokens(); listIndex++) { + StringTokenizer inner= new StringTokenizer(tok.nextToken(), COLON); + if (inner.countTokens() == 0) + listIndex--; + while (inner.hasMoreTokens()) { + String categoryId= inner.nextToken(); + Set indices= newConfig.get(categoryId); + if (indices == null) { + indices= new HashSet(); + newConfig.put(categoryId, indices); + } + indices.add(Integer.valueOf(listIndex)); + } + } + for (ModelElement elem : fElements) + elem.updateIndices(newConfig.get(elem.getId())); + } + + public ModelElement getElement(String id) { + for (ModelElement el : fElements) + if (el.getId().equals(id)) + return el; + return null; + } + + public List getElements(int index) { + List result= new ArrayList(); + for (ModelElement el : fElements) + if (el.getProposalListIndices() != null && el.getProposalListIndices().contains(Integer.valueOf(index))) + result.add(el); + return result; + } + + public List getCategoryIds(int index) { + List result= new ArrayList(); + for (ModelElement el : fElements) + if (el.getProposalListIndices() != null && el.getProposalListIndices().contains(Integer.valueOf(index))) + result.add(el.getId()); + return result; + } + + public boolean isValidCategoryId(String id) { + if (id != null) + return getElement(id) != null; + return false; + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/NewListDropSection.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/NewListDropSection.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/NewListDropSection.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/NewListDropSection.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets; + +import java.util.Observer; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DropTarget; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; + +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DropNewProposalListListener; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListCategoryTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProvidedCategoryTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util.HighlightObserver; + +/** + * + * @since 3.8 + */ +public final class NewListDropSection implements HighlightObserver { + private static final Color SELECTED_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION); + + private static final Color UNSELECTED_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); + + private final PreferenceModel fModel; + + private final ProposalListSection fProposalListSection; + + private DropNewProposalListListener fDropListener; + + private Composite fPaddingComposite; + + private Composite fHighlightComposite; + + public NewListDropSection(Composite wrappingComposite, int listIndex, PreferenceModel model, ProposalListSection proposalListSection) { + this.fModel= model; + this.fProposalListSection= proposalListSection; + + createPaddingComposite(wrappingComposite); + createHighlightComposite(); + + addDropSupport(listIndex); + } + + public void activateLastPositionSpaceBehavior(boolean last) { + GridData gd= new GridData(GridData.FILL, GridData.FILL, true, last); + gd.heightHint= 10; + fPaddingComposite.setLayoutData(gd); + } + + public void dispose() { + fPaddingComposite.dispose(); + fHighlightComposite.dispose(); + } + + public void highlight(boolean selected) { + if (selected) + fHighlightComposite.setBackground(SELECTED_COLOR); + else + fHighlightComposite.setBackground(UNSELECTED_COLOR); + fHighlightComposite.update(); + } + + public void addUpdateObserver(Observer o) { + fDropListener.addUpdateObserver(o); + } + + private void createPaddingComposite(Composite wrappingComposite) { + fPaddingComposite= new Composite(wrappingComposite, SWT.NONE); + GridData gd= new GridData(GridData.FILL, GridData.BEGINNING, true, false); + gd.heightHint= 10; + fPaddingComposite.setLayoutData(gd); + GridLayout layout= new GridLayout(); + layout.marginHeight= 0; + layout.verticalSpacing= 0; + layout.marginWidth= 0; + fPaddingComposite.setLayout(layout); + } + + private void createHighlightComposite() { + fHighlightComposite= new Composite(fPaddingComposite, SWT.NONE); + GridData gd= new GridData(SWT.FILL, SWT.BEGINNING, true, true); + gd.heightHint= 2; + gd.verticalIndent= 4; + fHighlightComposite.setLayoutData(gd); + } + + private void addDropSupport(int listIndex) { + Transfer[] transferTypes= new Transfer[] { ProvidedCategoryTransfer.getInstance(), ProposalListCategoryTransfer.getInstance(), ProposalListTransfer.getInstance() }; + DropTarget dropTarget= new DropTarget(fPaddingComposite, ProposalTransfer.ALL_DRAG_OPERATIONS); + dropTarget.setTransfer(transferTypes); + fDropListener= new DropNewProposalListListener(listIndex, fModel); + fProposalListSection.addToAutoscrollObserver(fDropListener); + fDropListener.addHighlightObserver(this); + dropTarget.addDropListener(fDropListener); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalList.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalList.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalList.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalList.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,500 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Observable; +import java.util.Observer; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DropTarget; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; + +import org.eclipse.core.runtime.Assert; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; + +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DragProposalListCategoriesListener; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DragState; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DropIntoProposalListListener; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListCategoryTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProvidedCategoryTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ImageHandler; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ModelElement; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util.HighlightObserver; + +/** + * + * @since 3.8 + */ +public final class ProposalList extends Observable implements HighlightObserver { + + private static final ImageDescriptor REMOVE_PROPOSAL_LIST_ICON_DESCRIPTOR= AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.jdt.ui", "$nl$/icons/full/elcl16/remove_proposal_list.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + + private static final ImageDescriptor REMOVE_PROPOSAL_LIST_OVER_ICON_DESCRIPTOR= AbstractUIPlugin.imageDescriptorFromPlugin( + "org.eclipse.jdt.ui", "$nl$/icons/full/elcl16/remove_proposal_list_over.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + + private static final Color SELECTED_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION); + + private static final Color UNSELECTED_BORDER_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_GRAY); + + private final class ProposalListTableLabelProvider 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 class ProposalListContentProvider implements IStructuredContentProvider { + private final int fListIndex; + + public ProposalListContentProvider(int listIndex) { + this.fListIndex= listIndex; + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + public Object[] getElements(Object inputElement) { + return fModel.getElements(fListIndex).toArray(); + } + } + + private class RemoveIconPaintListener implements Listener { + final Rectangle iconRect= new Rectangle(0, 0, 0, 0); + + public void handleEvent(Event event) { + Table tab= ((Table) event.widget); + Point tabLoc= getTableLocation(tab); + Point absMouseLoc= getAbsoluteMouseLocation(tab.getDisplay()); + Point relMouseLoc= getRelativeMouseLocation(absMouseLoc, tabLoc); + if (DragState.isNotDragged() && isMouseOverScrolledComposite(absMouseLoc) && isMouseOverCurrentRow(tab, relMouseLoc, (TableItem) event.item)) { + updateIconRectangle(tab, event.height, event.y); + drawIcon(event.gc, relMouseLoc); + } + } + + private Point getTableLocation(Table tab) { + return tab.toDisplay(tab.getClientArea().x, tab.getClientArea().y); + } + + private Point getAbsoluteMouseLocation(Display disp) { + return disp.getCursorLocation(); + } + + private Point getRelativeMouseLocation(Point mouseLoc, Point tabLoc) { + return new Point(mouseLoc.x - tabLoc.x, mouseLoc.y - tabLoc.y); + } + + private boolean isMouseOverScrolledComposite(Point absMouseLoc) { + return fProposalListSection.isPointInScrolledComposite(absMouseLoc); + } + + private boolean isMouseOverCurrentRow(Table tab, Point mouseLoc, TableItem currentItem) { + return tab.getClientArea().contains(mouseLoc) && currentItem == getItem(tab, mouseLoc); + } + + private void updateIconRectangle(Table tab, int eventHeight, int eventY) { + ImageData imgData= fRemoveProposalListImage.getImageData(); + + int x= calculateNewX(tab, imgData); + int y= calculateNewY(imgData, eventHeight, eventY); + int width= calculateNewWidth(imgData); + int height= calculateNewHeight(imgData); + + updateRectangle(iconRect, x, y, width, height); + } + + private void drawIcon(GC gc, Point mouseLoc) { + gc.setClipping(iconRect); + if (iconRect.contains(mouseLoc)) + gc.drawImage(fRemoveProposalListOverImage, iconRect.x, iconRect.y); + else + gc.drawImage(fRemoveProposalListImage, iconRect.x, iconRect.y); + } + + private int calculateNewX(Table tab, ImageData imgData) { + return tab.getClientArea().width - imgData.width; + } + + private int calculateNewY(ImageData imgData, int eventHeight, int eventY) { + int offset= Math.max(0, (eventHeight - imgData.height) / 2); + return eventY + offset; + } + + private int calculateNewWidth(ImageData imgData) { + return imgData.width; + } + + private int calculateNewHeight(ImageData imgData) { + return imgData.height; + } + + private void updateRectangle(Rectangle rect, int x, int y, int width, int height) { + rect.x= x; + rect.y= y; + rect.width= width; + rect.height= height; + } + } + + private final PreferenceModel fModel; + + private final ProposalListSection fProposalListSection; + + private final Image fRemoveProposalListImage; + + private final Image fRemoveProposalListOverImage; + + private Composite fTableContainer; + + private final ProposalListHeader fHeader; + + private TableViewer fTableViewer; + + private final NewListDropSection fNewListDropSection; + + private DropIntoProposalListListener fDropListener; + + private boolean fHighlighted; + + public ProposalList(Composite parent, int listIndex, ProposalListSection proposalListSection, PreferenceModel model, ImageHandler imageHandler) { + this.fModel= model; + this.fProposalListSection= proposalListSection; + + this.fRemoveProposalListImage= imageHandler.getImage(REMOVE_PROPOSAL_LIST_ICON_DESCRIPTOR); + this.fRemoveProposalListOverImage= imageHandler.getImage(REMOVE_PROPOSAL_LIST_OVER_ICON_DESCRIPTOR); + + createTableContainer(parent); + this.fHeader= new ProposalListHeader(fTableContainer, listIndex, fModel, imageHandler); + createTable(listIndex); + + this.fNewListDropSection= new NewListDropSection(parent, listIndex + 1, fModel, fProposalListSection); + + addDropSupportToTableContainer(listIndex); + addRemoveIconVisibility(); + addBorderPainterToTableContainer(); + } + + public List getContent() { + return (List) fTableViewer.getInput(); + } + + public void clearContent() { + fTableViewer.setInput(null); + } + + public void addContent(ModelElement element) { + List content= getContent(); + if (content == null) + content= new ArrayList(); + content.add(element); + setContent(content); + } + + public void setContent(List elements) { + fTableViewer.setInput(elements); + } + + public void activateLastListSpaceBehavior(boolean last) { + fNewListDropSection.activateLastPositionSpaceBehavior(last); + } + + public void dispose() { + fTableContainer.dispose(); + fHeader.dispose(); + fTableViewer.getTable().dispose(); + fNewListDropSection.dispose(); + } + + public void highlight(boolean highlight) { + if (fHighlighted == highlight) + return; + fHighlighted= highlight; + fTableContainer.redraw(); + + fHeader.highlight(highlight); + } + + @Override + public synchronized void addObserver(Observer o) { + super.addObserver(o); + fDropListener.addUpdateObserver(o); + fHeader.addObserver(o); + fNewListDropSection.addUpdateObserver(o); + } + + + public TableViewer getTableViewer() { + return fTableViewer; + } + + private void createTableContainer(Composite parent) { + fTableContainer= new Composite(parent, SWT.NONE); + fTableContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + GridLayout layout= new GridLayout(); + layout.marginHeight= 1; + layout.marginWidth= 1; + layout.verticalSpacing= 0; + layout.horizontalSpacing= 0; + fTableContainer.setLayout(layout); + } + + private void createTable(int listIndex) { + createInitialTableViewer(); + TableColumn nameColumn= addFirstTableColumn(); + + ITableLabelProvider labelProvider= setTableProviderAndComparator(listIndex); + adjustFirstTableColumnWidth(nameColumn, labelProvider); + + addDragSupportToTable(listIndex); + addFocusOutListenerToTable(); + addProposalListCategoryRemoveIconCreatorToTable(listIndex); + } + + private void addDropSupportToTableContainer(int listIndex) { + Transfer[] transferTypes= new Transfer[] { ProvidedCategoryTransfer.getInstance(), ProposalListCategoryTransfer.getInstance(), ProposalListTransfer.getInstance() }; + DropTarget dropTarget= new DropTarget(fTableContainer, ProposalTransfer.ALL_DRAG_OPERATIONS); + dropTarget.setTransfer(transferTypes); + fDropListener= new DropIntoProposalListListener(listIndex, fModel); + fProposalListSection.addToAutoscrollObserver(fDropListener); + fDropListener.addHighlightObserver(this); + dropTarget.addDropListener(fDropListener); + } + + private void addRemoveIconVisibility() { + Listener l= new Listener() { + public void handleEvent(Event e) { + fHeader.showRemoveIcon(); + } + }; + this.addListener(SWT.MouseEnter, l); + this.addListener(SWT.MouseMove, l); + this.addListener(SWT.MouseExit, new Listener() { + public void handleEvent(Event e) { + fHeader.hideRemoveIcon(); + } + }); + } + + private void addBorderPainterToTableContainer() { + fTableContainer.addPaintListener(new PaintListener() { + public void paintControl(PaintEvent e) { + if (fHighlighted) + e.gc.setBackground(SELECTED_COLOR); + else + e.gc.setBackground(UNSELECTED_BORDER_COLOR); + Rectangle rect= fTableContainer.getClientArea(); + e.gc.fillRectangle(rect); + } + }); + } + + private void createInitialTableViewer() { + fTableViewer= new TableViewer(fTableContainer, SWT.MULTI | SWT.NO_SCROLL); + final Table table= fTableViewer.getTable(); + table.setHeaderVisible(false); + table.setLinesVisible(false); + table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + } + + private TableColumn addFirstTableColumn() { + TableColumn nameColumn= new TableColumn(fTableViewer.getTable(), SWT.NONE); + nameColumn.setResizable(false); + return nameColumn; + } + + private void adjustFirstTableColumnWidth(TableColumn column, ITableLabelProvider labelProvider) { + final int ICON_WIDTH= 16; + final int HEADER_MARGIN= 20; + int minNameWidth= computeWidth(fTableViewer.getTable(), column.getText()) + HEADER_MARGIN; + for (int i= 0; i < fModel.elements.size(); i++) + minNameWidth= Math.max(minNameWidth, computeWidth(fTableViewer.getTable(), labelProvider.getColumnText(fModel.elements.get(i), 0)) + 2 * ICON_WIDTH); + column.setWidth(minNameWidth); + } + + private ITableLabelProvider setTableProviderAndComparator(int listIndex) { + fTableViewer.setContentProvider(new ProposalListContentProvider(listIndex)); + fTableViewer.setComparator(new ModelElement.ModelElementViewerComparator()); + ITableLabelProvider labelProvider= new ProposalListTableLabelProvider(); + fTableViewer.setLabelProvider(labelProvider); + return labelProvider; + } + + private void addDragSupportToTable(int listIndex) { + Transfer[] transferTypes= new Transfer[] { ProposalListCategoryTransfer.getInstance() }; + DragProposalListCategoriesListener dragListener= new DragProposalListCategoriesListener(fTableViewer, listIndex); + DragState.addToObservable(dragListener); + fTableViewer.addDragSupport(ProposalTransfer.ALL_DRAG_OPERATIONS, transferTypes, dragListener); + } + + private void addFocusOutListenerToTable() { + final Table table= fTableViewer.getTable(); + table.addListener(SWT.FocusOut, new Listener() { + public void handleEvent(Event event) { + table.deselectAll(); + } + }); + } + + private void addListener(int eventType, Listener listener) { + fTableContainer.addListener(eventType, listener); + fHeader.addListener(eventType, listener); + fTableViewer.getTable().addListener(eventType, listener); + } + + private void addProposalListCategoryRemoveIconCreatorToTable(int listIndex) { + Rectangle iconRect= addRemoveIconToTableItemsPainter(); + addRemoveIconRedrawListenerToTable(iconRect); + addRemoveCategoryOnClickListenerToTable(iconRect, listIndex); + } + + private Rectangle addRemoveIconToTableItemsPainter() { + RemoveIconPaintListener paintListener= new RemoveIconPaintListener(); + fTableViewer.getTable().addListener(SWT.PaintItem, paintListener); + return paintListener.iconRect; + } + + private void addRemoveIconRedrawListenerToTable(final Rectangle iconRect) { + final Table table= fTableViewer.getTable(); + Listener mouseOverTableListener= new Listener() { + TableItem lastItem; + + boolean lastOverImg; + + public void handleEvent(Event e) { + TableItem item= getItem(table, new Point(e.x, e.y)); + boolean overImg= iconRect.contains(e.x, e.y); + if (lastItem != item || lastOverImg != overImg) { + lastItem= item; + lastOverImg= overImg; + table.redraw(); + } + } + }; + table.addListener(SWT.MouseEnter, mouseOverTableListener); + table.addListener(SWT.MouseMove, mouseOverTableListener); + table.addListener(SWT.MouseExit, mouseOverTableListener); + } + + private void addRemoveCategoryOnClickListenerToTable(final Rectangle iconRect, final int listIndex) { + final Table table= fTableViewer.getTable(); + table.addMouseListener(new MouseListener() { + public void mouseUp(MouseEvent e) { + if (isSingleClick(e.count) && isUpOverIcon(e.x, e.y)) { + int elemIndex= table.indexOf(getItem(table, new Point(e.x, e.y))); + List categories= fModel.getElements(listIndex); + Collections.sort(categories, new ModelElement.ModelElementComparator()); + categories.get(elemIndex).removeInProposalList(listIndex); + setChanged(); + notifyObservers(); + } + } + + public void mouseDown(MouseEvent e) { + } + + public void mouseDoubleClick(MouseEvent e) { + } + + private boolean isSingleClick(int count) { + return count == 1; + } + + private boolean isUpOverIcon(int x, int y) { + return iconRect.contains(x, y); + } + }); + } + + private TableItem getItem(Table tab, Point p) { + for (int index= 0; index < tab.getItemCount(); index++) { + if (getItemBounds(tab, index).contains(p)) + return tab.getItem(index); + } + return null; + } + + private Rectangle getItemBounds(Table tab, int itemIndex) { + Rectangle tableBounds= tab.getBounds(); + int height= tab.getItemHeight(); + int width= tableBounds.width; + int x= tableBounds.x; + int y= itemIndex * height; + return new Rectangle(x, y, width, height); + } + + 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(); + } + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalListHeader.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalListHeader.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalListHeader.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalListHeader.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets; + +import java.util.Observable; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DragSource; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; + +import org.eclipse.jface.resource.ImageDescriptor; + +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import org.eclipse.jdt.internal.corext.util.Messages; + +import org.eclipse.jdt.internal.ui.preferences.PreferencesMessages; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DragProposalListListener; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DragState; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ImageHandler; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel; + +/** + * + * @since 3.8 + */ +public final class ProposalListHeader extends Observable { + + private static final ImageDescriptor REMOVE_PROPOSAL_LIST_ICON_DESCRIPTOR= AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.jdt.ui", "$nl$/icons/full/elcl16/remove_proposal_list.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + + private static final ImageDescriptor REMOVE_PROPOSAL_LIST_OVER_ICON_DESCRIPTOR= AbstractUIPlugin.imageDescriptorFromPlugin( + "org.eclipse.jdt.ui", "$nl$/icons/full/elcl16/remove_proposal_list_over.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + + private static final Color SELECTED_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION); + + private static final Color SELECTED_TEXT_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT); + + private static final Color UNSELECTED_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); + + private static final Color UNSELECTED_TEXT_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_FOREGROUND); + + private final PreferenceModel fModel; + + private final Image fRemoveProposalListImage; + + private final Image fRemoveProposalListOverImage; + + private Composite fPaddingComposite; + + private Label fTitle; + + private Label fRemoveLabel; + + public ProposalListHeader(Composite tableContainer, int listIndex, PreferenceModel model, ImageHandler imageHandler) { + this.fModel= model; + + this.fRemoveProposalListImage= imageHandler.getImage(REMOVE_PROPOSAL_LIST_ICON_DESCRIPTOR); + this.fRemoveProposalListOverImage= imageHandler.getImage(REMOVE_PROPOSAL_LIST_OVER_ICON_DESCRIPTOR); + + createPaddingComposite(tableContainer); + createTitle(listIndex); + createRemoveIcon(listIndex); + updateHeaderHeight(); + + addListDragSupport(fPaddingComposite, listIndex); + addListDragSupport(fTitle, listIndex); + } + + public void dispose() { + fPaddingComposite.dispose(); + fTitle.dispose(); + fRemoveLabel.dispose(); + } + + public void highlight(boolean highlight) { + Color backgroundColor= highlight ? SELECTED_COLOR : UNSELECTED_COLOR; + Color foregroundColor= highlight ? SELECTED_TEXT_COLOR : UNSELECTED_TEXT_COLOR; + fPaddingComposite.setBackground(backgroundColor); + fTitle.setBackground(backgroundColor); + fTitle.setForeground(foregroundColor); + fRemoveLabel.setBackground(backgroundColor); + } + + public void showRemoveIcon() { + fRemoveLabel.setVisible(true); + } + + public void hideRemoveIcon() { + fRemoveLabel.setVisible(false); + } + + public void addListener(int eventType, Listener listener) { + fPaddingComposite.addListener(eventType, listener); + fTitle.addListener(eventType, listener); + fRemoveLabel.addListener(eventType, listener); + } + + private void createPaddingComposite(Composite tableContainer) { + fPaddingComposite= new Composite(tableContainer, SWT.NONE); + GridLayout layout= new GridLayout(2, false); + layout.marginHeight= 0; + layout.verticalSpacing= 0; + fPaddingComposite.setLayout(layout); + } + + private void createTitle(int listIndex) { + fTitle= new Label(fPaddingComposite, SWT.NONE); + fTitle.setText(getProposalListTitle(listIndex)); + fTitle.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true)); + } + + private void updateHeaderHeight() { + GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true); + gd.heightHint= getHeaderHeight(); + fPaddingComposite.setLayoutData(gd); + } + + private void createRemoveIcon(int listIndex) { + fRemoveLabel= createRemoveLabel(); + addMouseOverRemoveIconListener(); + addRemoveListOnClickListener(listIndex); + } + + private void addListDragSupport(Control control, int listIndex) { + DragProposalListListener tableDragSourceListener= new DragProposalListListener(listIndex); + Transfer[] transferTypes= new Transfer[] { ProposalListTransfer.getInstance() }; + DragSource dragSource= new DragSource(control, ProposalTransfer.ALL_DRAG_OPERATIONS); + dragSource.setTransfer(transferTypes); + DragState.addToObservable(tableDragSourceListener); + dragSource.addDragListener(tableDragSourceListener); + } + + private String getProposalListTitle(int index) { + return Messages.format(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_proposal_list_table_title, Integer.valueOf(index + 1)); + } + + private int getHeaderHeight() { + return fTitle.computeSize(SWT.DEFAULT, SWT.DEFAULT).y + 8; + } + + private Label createRemoveLabel() { + final Label removeLabel= new Label(fPaddingComposite, SWT.NONE); + removeLabel.setVisible(false); + removeLabel.setImage(fRemoveProposalListImage); + GridData gd= new GridData(SWT.RIGHT, SWT.CENTER, true, true); + gd.widthHint= fRemoveProposalListImage.getImageData().width; + gd.minimumWidth= gd.widthHint; + removeLabel.setLayoutData(gd); + return removeLabel; + } + + private void addMouseOverRemoveIconListener() { + fRemoveLabel.addListener(SWT.MouseEnter, new Listener() { + public void handleEvent(Event e) { + fRemoveLabel.setImage(fRemoveProposalListOverImage); + } + }); + fRemoveLabel.addListener(SWT.MouseExit, new Listener() { + public void handleEvent(Event e) { + fRemoveLabel.setImage(fRemoveProposalListImage); + } + }); + } + + private void addRemoveListOnClickListener(final int listIndex) { + fRemoveLabel.addMouseListener(new MouseListener() { + public void mouseUp(MouseEvent e) { + if (isSingleClick(e.count) && isUpOverIcon(e.x, e.y)) { + fModel.removeList(listIndex); + setChanged(); + notifyObservers(); + } + } + + public void mouseDown(MouseEvent e) { + } + + public void mouseDoubleClick(MouseEvent e) { + } + + private boolean isSingleClick(int count) { + return count == 1; + } + + private boolean isUpOverIcon(int x, int y) { + return x >= 0 && x < fRemoveLabel.getBounds().width && y >= 0 && y < fRemoveLabel.getBounds().height; + } + }); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalListSection.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalListSection.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalListSection.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalListSection.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,222 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Observable; +import java.util.Observer; +import java.util.Set; +import java.util.Vector; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.dnd.DropTarget; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Listener; + +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.AutoscrollDropTargetListener; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListCategoryTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProvidedCategoryTransfer; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ImageHandler; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ModelElement; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util.AutoscrollEngine; +import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util.AutoscrollObservable; + +/** + * + * @since 3.8 + */ +public final class ProposalListSection { + private final PreferenceModel fModel; + + private final Vector fUpdateObservers; + + private final ImageHandler fImageHandler; + + private final List fProposalLists= new ArrayList(); + + private ScrolledComposite fScrolledComposite; + + private AutoscrollEngine fAutoScrollEngine; + + private Composite fInnerWrappingComposite; + + private NewListDropSection fFirstNewListDropSection; + + public ProposalListSection(Composite parent, PreferenceModel model, ImageHandler imageHandler) { + this.fModel= model; + this.fUpdateObservers= new Vector(); + this.fImageHandler= imageHandler; + + createOuterScrolledComposite(parent); + createInnerProposalListWrappingComposite(); + + createAutoScrollEnginge(); + addDropAutoScroll(); + + addOuterSizeUpdater(); + + createFirstNewListDropSection(); + } + + public void updateControls() { + clearOldListState(); + Set filledLists= updateListStates(); + makeSureFirstListExists(); + adjustAndCleanUp(filledLists); + reLayoutInnerComposite(); + } + + public void addUpdateObserver(Observer observer) { + fUpdateObservers.add(observer); + fFirstNewListDropSection.addUpdateObserver(observer); + for (Observable o : fProposalLists) { + o.addObserver(observer); + } + } + + public void addToAutoscrollObserver(AutoscrollObservable o) { + o.addAutoscrollObserver(fAutoScrollEngine); + } + + public void addListener(int eventType, Listener listener) { + fScrolledComposite.addListener(eventType, listener); + fInnerWrappingComposite.addListener(eventType, listener); + } + + public boolean isPointInScrolledComposite(Point p) { + Point relativePoint= fScrolledComposite.toControl(p); + return fScrolledComposite.getClientArea().contains(relativePoint); + } + + private void createOuterScrolledComposite(Composite parent) { + fScrolledComposite= new ScrolledComposite(parent, SWT.V_SCROLL | SWT.BORDER); + fScrolledComposite.setAlwaysShowScrollBars(true); + fScrolledComposite.setExpandHorizontal(true); + fScrolledComposite.setExpandVertical(true); + GridData gridData= new GridData(GridData.FILL, GridData.FILL, true, true); + gridData.heightHint= 0; + fScrolledComposite.setLayoutData(gridData); + } + + private void createAutoScrollEnginge() { + fAutoScrollEngine= new AutoscrollEngine(fScrolledComposite); + } + + private void addDropAutoScroll() { + Transfer[] transferTypes= new Transfer[] { ProvidedCategoryTransfer.getInstance(), ProposalListCategoryTransfer.getInstance(), ProposalListTransfer.getInstance() }; + DropTarget dropTarget= new DropTarget(fScrolledComposite, ProposalTransfer.ALL_DRAG_OPERATIONS); + dropTarget.setTransfer(transferTypes); + AutoscrollDropTargetListener dropListener= new AutoscrollDropTargetListener(); + dropListener.addAutoscrollObserver(fAutoScrollEngine); + dropTarget.addDropListener(dropListener); + } + + private void createInnerProposalListWrappingComposite() { + fInnerWrappingComposite= new Composite(fScrolledComposite, SWT.NONE); + fScrolledComposite.setContent(fInnerWrappingComposite); + GridLayout layout= new GridLayout(); + layout.marginHeight= 0; + layout.verticalSpacing= 0; + fInnerWrappingComposite.setLayout(layout); + } + + private void addOuterSizeUpdater() { + fInnerWrappingComposite.addControlListener(new ControlListener() { + public void controlResized(ControlEvent e) { + fInnerWrappingComposite.update(); + fScrolledComposite.setMinSize(fInnerWrappingComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + fScrolledComposite.layout(true, true); + } + + public void controlMoved(ControlEvent e) { + } + }); + } + + private void createFirstNewListDropSection() { + fFirstNewListDropSection= new NewListDropSection(fInnerWrappingComposite, 0, fModel, this); + } + + private void clearOldListState() { + for (ProposalList list : fProposalLists) + list.clearContent(); + } + + private Set updateListStates() { + Set filledLists= new HashSet(); + for (ModelElement element : fModel.elements) { + Set indices= element.getProposalListIndices(); + if (indices != null) { + filledLists.addAll(indices); + addElementToLists(element, indices); + } + } + return filledLists; + } + + private void makeSureFirstListExists() { + if (fProposalLists.size() == 0) + makeSureListExists(0); + } + + private void adjustAndCleanUp(Set filledLists) { + boolean last= true; + for (int i= fProposalLists.size() - 1; i >= 0; i--) + if (i > 0 && !filledLists.contains(Integer.valueOf(i))) { + fProposalLists.get(i).dispose(); + fProposalLists.remove(i); + } else { + fProposalLists.get(i).activateLastListSpaceBehavior(last); + last= false; + } + } + + private void reLayoutInnerComposite() { + fInnerWrappingComposite.pack(true); + fInnerWrappingComposite.layout(false); + } + + private void addElementToLists(ModelElement element, Set indices) { + for (int index : indices) { + makeSureListExists(index); + addElementToList(element, index); + } + } + + private void makeSureListExists(int listIndex) { + while (fProposalLists.size() < listIndex + 1) { + ProposalList proposalList= new ProposalList(fInnerWrappingComposite, fProposalLists.size(), this, fModel, fImageHandler); + addAllUpdateObservers(proposalList); + fProposalLists.add(proposalList); + } + } + + private void addElementToList(ModelElement element, int listIndex) { + fProposalLists.get(listIndex).addContent(element); + } + + private void addAllUpdateObservers(Observable o) { + for (Observer observer : fUpdateObservers) + o.addObserver(observer); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/AutoscrollEngine.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/AutoscrollEngine.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/AutoscrollEngine.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/AutoscrollEngine.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util; + +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Control; + +/** + * + * @since 3.8 + */ +public class AutoscrollEngine implements AutoscrollObserver { + private final ScrolledComposite fScrolledComposite; + + private final int fScrollDetectRange; + + private final int fScrollOffset; + + public AutoscrollEngine(ScrolledComposite scrolledComposite) { + this(scrolledComposite, 15, 5); + } + + public AutoscrollEngine(ScrolledComposite scrolledComposite, int scrollDetectRange, int scrollOffset) { + fScrolledComposite= scrolledComposite; + fScrollDetectRange= scrollDetectRange; + fScrollOffset= scrollOffset; + } + + public void autoScroll(Point mouseLocation) { + assert mouseLocation != null : "Mouse location can't be NULL"; //$NON-NLS-1$ + + Point scrolledCompPosition= getScrolledCompositePosition(); + Rectangle scrollArea= getScrollArea(); + Point origin= getScrolledOrigin(); + Rectangle childrenBounds= getChildrenBounds(); + + if (isMouseInTopDetectRange(scrolledCompPosition, mouseLocation)) + updateOriginTopDetected(origin); + if (isMouseInBottomDetectRange(scrolledCompPosition, mouseLocation, scrollArea)) + updateOriginBottomDetected(origin, scrollArea, childrenBounds); + + setUpdatedOrigin(origin); + } + + private Rectangle getScrollArea() { + return fScrolledComposite.getClientArea(); + } + + private Point getScrolledCompositePosition() { + return fScrolledComposite.toDisplay(1, 1); + } + + private Point getScrolledOrigin() { + return fScrolledComposite.getOrigin(); + } + + private Rectangle getChildrenBounds() { + Control[] children= fScrolledComposite.getChildren(); + if (children == null || children.length == 0) + return new Rectangle(0, 0, 0, 0); + Rectangle childrenBounds= children[0].getBounds(); + for (Control c : children) + childrenBounds.union(c.getBounds()); + return childrenBounds; + } + + private boolean isMouseInTopDetectRange(Point scrolledCompositePosition, Point mouseLocation) { + return scrolledCompositePosition.y + fScrollDetectRange > mouseLocation.y; + } + + private boolean isMouseInBottomDetectRange(Point scrolledCompositePosition, Point mouseLocation, Rectangle scrollArea) { + return scrolledCompositePosition.y + scrollArea.height - fScrollDetectRange < mouseLocation.y; + } + + private void updateOriginTopDetected(Point origin) { + origin.y= Math.max(0, origin.y - fScrollOffset); + } + + private void updateOriginBottomDetected(Point origin, Rectangle scrollArea, Rectangle childrenBounds) { + origin.y= Math.min(childrenBounds.height - scrollArea.height, origin.y + fScrollOffset); + } + + private void setUpdatedOrigin(Point origin) { + fScrolledComposite.setOrigin(origin); + } +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/AutoscrollObservable.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/AutoscrollObservable.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/AutoscrollObservable.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/AutoscrollObservable.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util; + +/** + * + * @since 3.8 + */ +public interface AutoscrollObservable { + public void addAutoscrollObserver(AutoscrollObserver o); +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/AutoscrollObserver.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/AutoscrollObserver.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/AutoscrollObserver.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/AutoscrollObserver.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util; + +import org.eclipse.swt.graphics.Point; + +/** + * + * @since 3.8 + */ +public interface AutoscrollObserver { + public void autoScroll(Point mouseLocation); +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/HighlightObservable.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/HighlightObservable.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/HighlightObservable.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/HighlightObservable.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util; + +/** + * + * @since 3.8 + */ +public interface HighlightObservable { + public void addHighlightObserver(HighlightObserver o); +} Index: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/HighlightObserver.java =================================================================== RCS file: ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/HighlightObserver.java diff -N ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/HighlightObserver.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/util/HighlightObserver.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2011 Thomas Schlosser. + * 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: + * Thomas Schlosser - initial API and implementation. + */ +package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.util; + +/** + * + * @since 3.8 + */ +public interface HighlightObserver { + public void highlight(boolean highlight); +} Index: ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java,v retrieving revision 1.19 diff -u -r1.19 CompletionProposalCategory.java --- ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java 1 Mar 2011 11:50:36 -0000 1.19 +++ ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java 11 Aug 2011 19:12:02 -0000 @@ -7,13 +7,18 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Thomas Schlosser - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876 *******************************************************************************/ package org.eclipse.jdt.internal.ui.text.java; import java.net.URL; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; import org.osgi.framework.Bundle; @@ -55,12 +60,11 @@ /** The image descriptor for this category, or null if none specified. */ private final ImageDescriptor fImage; - private boolean fIsSeparateCommand= true; + private final Set fProposalListIndices = new HashSet(); + private final Set fPublicProposalListIndices= Collections.unmodifiableSet(fProposalListIndices); private boolean fIsEnabled= true; - private boolean fIsIncluded= true; private final CompletionProposalComputerRegistry fRegistry; - private int fSortOrder= 0xffff - 1; private String fLastError= null; CompletionProposalCategory(IConfigurationElement element, CompletionProposalComputerRegistry registry) throws CoreException { @@ -158,35 +162,54 @@ } /** - * Sets the separate command state of the category. - * - * @param enabled the new enabled state. + * Adds the given proposal list index to the proposal list indices of this category. + * + * @param listIndex the index of the proposal list. */ - public void setSeparateCommand(boolean enabled) { - fIsSeparateCommand= enabled; + public void addProposalListIndex(Integer listIndex) { + fProposalListIndices.add(listIndex); } /** - * Returns the enablement state of the category. - * - * @return the enablement state of the category + * Adds all given proposal list indices to the proposal list indices of this category. + * + * @param listIndices the indices of the proposal lists. */ - public boolean isSeparateCommand() { - return fIsSeparateCommand; + public void addAllProposalListIndices(Collection listIndices) { + if (listIndices == null) + return; + fProposalListIndices.addAll(listIndices); } /** - * @param included the included + * Removes all given proposal list indices from the proposal list indices of this category. + * + * @param listIndices the indices of the proposal lists. */ - public void setIncluded(boolean included) { - fIsIncluded= included; + public void removeAllProposalListIndices(Collection listIndices) { + if (listIndices == null) + return; + fProposalListIndices.removeAll(listIndices); } /** - * @return included + * Clears the list of proposal list indices of this category. + * */ - public boolean isIncluded() { - return fIsIncluded; + public void clearProposalListIndices() { + fProposalListIndices.clear(); + } + + /** + * Returns the indices of the proposal lists of this category. + *

+ * The returned set is read-only. + *

+ * + * @return the indices of the proposal lists of this category + */ + public Set getProposalListIndices() { + return fPublicProposalListIndices; } public boolean isEnabled() { @@ -233,20 +256,6 @@ } /** - * @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 IJavaCompletionProposalComputer}, it is disabled. @@ -288,7 +297,7 @@ List descriptors= new ArrayList(fRegistry.getProposalComputerDescriptors(partition)); for (Iterator it= descriptors.iterator(); it.hasNext();) { CompletionProposalComputerDescriptor desc= it.next(); - if (desc.getCategory() == this && (isIncluded() || isSeparateCommand())) + if (desc.getCategory() == this && !fProposalListIndices.isEmpty()) result.addAll(desc.computeContextInformation(context, monitor)); if (fLastError == null) fLastError= desc.getErrorMessage(); Index: ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerRegistry.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerRegistry.java,v retrieving revision 1.23 diff -u -r1.23 CompletionProposalComputerRegistry.java --- ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerRegistry.java 1 Mar 2011 11:50:36 -0000 1.23 +++ ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerRegistry.java 11 Aug 2011 19:12:03 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Thomas Schlosser - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876 *******************************************************************************/ package org.eclipse.jdt.internal.ui.text.java; @@ -21,6 +22,8 @@ import java.util.Map; import java.util.Set; import java.util.StringTokenizer; +import java.util.TreeMap; +import java.util.Map.Entry; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; @@ -330,25 +333,28 @@ private List getCategories(List elements) { IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); - String preference= store.getString(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES); - Set disabled= new HashSet(); - StringTokenizer tok= new StringTokenizer(preference, "\0"); //$NON-NLS-1$ - while (tok.hasMoreTokens()) - disabled.add(tok.nextToken()); - Map ordered= new HashMap(); - preference= store.getString(PreferenceConstants.CODEASSIST_CATEGORY_ORDER); - tok= new StringTokenizer(preference, "\0"); //$NON-NLS-1$ - while (tok.hasMoreTokens()) { + String preference= store.getString(PreferenceConstants.CODEASSIST_PROPOSAL_LISTS); + Map> proposalLists= new HashMap>(); + StringTokenizer tok= new StringTokenizer(preference, "\0"); //$NON-NLS-1$ + for (int i= 0; tok.hasMoreTokens(); i++) { StringTokenizer inner= new StringTokenizer(tok.nextToken(), ":"); //$NON-NLS-1$ - String id= inner.nextToken(); - int rank= Integer.parseInt(inner.nextToken()); - ordered.put(id, new Integer(rank)); + if (inner.countTokens() == 0) + i--; + while (inner.hasMoreTokens()) { + String categoryId= inner.nextToken(); + Set set= proposalLists.get(categoryId); + if (set == null) { + set= new HashSet(); + proposalLists.put(categoryId, set); + } + set.add(Integer.valueOf(i)); + } } CompletionProposalCategory allProposals= null; CompletionProposalCategory typeProposals= null; CompletionProposalCategory allButTypeProposals= null; - + List categories= new ArrayList(); for (Iterator iter= elements.iterator(); iter.hasNext();) { IConfigurationElement element= iter.next(); @@ -358,17 +364,8 @@ CompletionProposalCategory category= new CompletionProposalCategory(element, this); categories.add(category); - category.setIncluded(!disabled.contains(category.getId())); - Integer rank= ordered.get(category.getId()); - if (rank != null) { - int r= rank.intValue(); - boolean separate= r < 0xffff; - if (!separate) - r= r - 0xffff; - category.setSeparateCommand(separate); - category.setSortOrder(r); - } - + category.addAllProposalListIndices(proposalLists.get(category.getId())); + String id= category.getId(); if ("org.eclipse.jdt.ui.javaAllProposalCategory".equals(id)) //$NON-NLS-1$ allProposals= category; @@ -383,7 +380,7 @@ * some other reason. Do not include the extension in the list and inform the user * about it. */ - Object[] args= {element.toString()}; + Object[] args= { element.toString() }; String message= Messages.format(JavaTextMessages.CompletionProposalComputerRegistry_invalid_message, args); IStatus status= new Status(IStatus.WARNING, JavaPlugin.getPluginId(), IStatus.OK, message, x); informUser(status); @@ -391,35 +388,47 @@ informUser(x.getStatus()); } } - preventDuplicateCategories(store, disabled, allProposals, typeProposals, allButTypeProposals); + preventDuplicateCategories(store, proposalLists, allProposals, typeProposals, allButTypeProposals, categories.size()); return categories; } - private void preventDuplicateCategories(IPreferenceStore store, Set disabled, CompletionProposalCategory allProposals, CompletionProposalCategory typeProposals, - CompletionProposalCategory allButTypeProposals) { + private void preventDuplicateCategories(IPreferenceStore store, Map> proposalLists, CompletionProposalCategory allProposals, CompletionProposalCategory typeProposals, + CompletionProposalCategory allButTypeProposals, int numberOfCategories) { boolean adjusted= false; - if (allProposals == null || !allProposals.isIncluded()) + if (allProposals == null || allProposals.getProposalListIndices().isEmpty()) return; - if (allButTypeProposals != null && allButTypeProposals.isIncluded()) { - allButTypeProposals.setIncluded(false); - disabled.add(allButTypeProposals.getId()); + if (allButTypeProposals != null && !allButTypeProposals.getProposalListIndices().isEmpty()) { + allButTypeProposals.removeAllProposalListIndices(allProposals.getProposalListIndices()); + proposalLists.put(allButTypeProposals.getId(), allButTypeProposals.getProposalListIndices()); adjusted= true; } - if (typeProposals != null && typeProposals.isIncluded()) { - typeProposals.setIncluded(false); - disabled.add(typeProposals.getId()); + if (typeProposals != null && !typeProposals.getProposalListIndices().isEmpty()) { + typeProposals.removeAllProposalListIndices(allProposals.getProposalListIndices()); + proposalLists.put(typeProposals.getId(), typeProposals.getProposalListIndices()); adjusted= true; } if (adjusted) { - StringBuffer buf= new StringBuffer(50 * disabled.size()); - Iterator iter= disabled.iterator(); - while (iter.hasNext()) { - buf.append(iter.next()); + int initialBufferSize= 50 * numberOfCategories; + Map proposalListsCategories= new TreeMap(); + for (Entry> category : proposalLists.entrySet()) { + for (Integer index : category.getValue()) { + StringBuffer buf= proposalListsCategories.get(index); + if (buf == null) { + buf= new StringBuffer(initialBufferSize); + proposalListsCategories.put(index, buf); + } + buf.append(category.getKey()); + buf.append(':'); + } + } + StringBuffer buf= new StringBuffer(initialBufferSize * proposalListsCategories.size()); + for (StringBuffer proposalList : proposalListsCategories.values()) { + buf.append(proposalList); buf.append('\0'); } - store.putValue(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES, buf.toString()); + store.putValue(PreferenceConstants.CODEASSIST_PROPOSAL_LISTS, buf.toString()); } } Index: ui/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java,v retrieving revision 1.26 diff -u -r1.26 ContentAssistProcessor.java --- ui/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java 1 Mar 2011 11:50:36 -0000 1.26 +++ ui/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java 11 Aug 2011 19:12:03 -0000 @@ -7,14 +7,15 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Thomas Schlosser - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876 *******************************************************************************/ package org.eclipse.jdt.internal.ui.text.java; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.TreeMap; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; @@ -186,14 +187,6 @@ */ private static final String PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY= "EmptyDefaultAssistCategory"; //$NON-NLS-1$ - private static final Comparator ORDER_COMPARATOR= new Comparator() { - - public int compare(CompletionProposalCategory d1, CompletionProposalCategory d2) { - return d1.getSortOrder() - d2.getSortOrder(); - } - - }; - private final List fCategories; private final String fPartition; private final ContentAssistant fAssistant; @@ -444,47 +437,44 @@ } private List> getCategoryIteration() { - List> sequence= new ArrayList>(); - sequence.add(getDefaultCategories()); - for (Iterator it= getSeparateCategories().iterator(); it.hasNext();) { - CompletionProposalCategory cat= it.next(); - sequence.add(Collections.singletonList(cat)); - } - return sequence; - } - - private List getDefaultCategories() { - // default mix - enable all included computers - List included= getDefaultCategoriesUnchecked(); - - if (fComputerRegistry.hasUninstalledComputers(fPartition, included)) { - if (informUserAboutEmptyDefaultCategory()) - // preferences were restored - recompute the default categories - included= getDefaultCategoriesUnchecked(); + List> categories= getProposalCategoriesUnchecked(); + if (fComputerRegistry.hasUninstalledComputers(fPartition, categories.get(0))) { + if (informUserAboutEmptyFirstProposalCategory()) + // preferences were restored - recompute the categories in the first proposal list + categories= getProposalCategoriesUnchecked(); fComputerRegistry.resetUnistalledComputers(); } - - return included; + return categories; } - private List getDefaultCategoriesUnchecked() { - List included= new ArrayList(); - for (Iterator it= fCategories.iterator(); it.hasNext();) { - CompletionProposalCategory category= it.next(); - if (category.isIncluded() && category.hasComputers(fPartition)) - included.add(category); + private List> getProposalCategoriesUnchecked() { + Map> sorted= new TreeMap>(); + for (CompletionProposalCategory category : fCategories) { + if (!category.getProposalListIndices().isEmpty() && category.hasComputers(fPartition)) { + for (Integer index : category.getProposalListIndices()) { + List list= sorted.get(index); + if (list == null) { + list= new ArrayList(); + sorted.put(index, list); + } + list.add(category); + } + } } - return included; + // put at least an empty first list + if (sorted.isEmpty()) + sorted.put(Integer.valueOf(0), new ArrayList()); + return new ArrayList>(sorted.values()); } /** - * 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 true if the default should be restored + * Informs the user about the fact that there are no enabled categories in the first content + * assist proposal list set and shows a link to the preferences. + * + * @return true if the default should be restored * @since 3.3 */ - private boolean informUserAboutEmptyDefaultCategory() { + private boolean informUserAboutEmptyFirstProposalCategory() { if (OptionalMessageDialog.isDialogEnabled(PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY)) { final Shell shell= JavaPlugin.getActiveWorkbenchShell(); String title= JavaTextMessages.ContentAssistProcessor_all_disabled_title; @@ -549,8 +539,7 @@ 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); + store.setToDefault(PreferenceConstants.CODEASSIST_PROPOSAL_LISTS); } if (settingsId == returnValue) PreferencesUtil.createPreferenceDialogOn(shell, "org.eclipse.jdt.ui.preferences.CodeAssistPreferenceAdvanced", null, null).open(); //$NON-NLS-1$ @@ -561,17 +550,6 @@ return false; } - private List getSeparateCategories() { - ArrayList sorted= new ArrayList(); - for (Iterator it= fCategories.iterator(); it.hasNext();) { - CompletionProposalCategory category= it.next(); - if (category.isSeparateCommand() && category.hasComputers(fPartition)) - sorted.add(category); - } - Collections.sort(sorted, ORDER_COMPARATOR); - return sorted; - } - private String createEmptyMessage() { return Messages.format(JavaTextMessages.ContentAssistProcessor_empty_message, new String[]{getCategoryLabel(fRepetition)}); } @@ -582,13 +560,7 @@ 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(); + return Messages.format(JavaTextMessages.ContentAssistProcessor_proposalList, Integer.valueOf(iteration + 1)); } private String getIterationGesture() { Index: ui/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.java,v retrieving revision 1.23 diff -u -r1.23 JavaTextMessages.java --- ui/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.java 16 Nov 2009 17:00:10 -0000 1.23 +++ ui/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.java 11 Aug 2011 19:12:03 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Thomas Schlosser - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876 *******************************************************************************/ package org.eclipse.jdt.internal.ui.text.java; @@ -59,7 +60,7 @@ 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_proposalList; public static String ContentAssistProcessor_toggle_affordance_press_gesture; public static String ContentAssistProcessor_toggle_affordance_click_gesture; public static String ContentAssistProcessor_toggle_affordance_update_message; Index: ui/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.properties,v retrieving revision 1.35 diff -u -r1.35 JavaTextMessages.properties --- ui/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.properties 16 Nov 2009 17:00:10 -0000 1.35 +++ ui/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.properties 11 Aug 2011 19:12:03 -0000 @@ -7,6 +7,7 @@ # # Contributors: # IBM Corporation - initial API and implementation +# Thomas Schlosser - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876 ############################################################################### CompletionProcessor_error_accessing_title=Error Accessing Compilation Unit @@ -57,14 +58,14 @@ 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 +ContentAssistProcessor_proposalList={0}. Proposal List # {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} +ContentAssistProcessor_empty_message= No proposals in {0} ContentAssistHistory_serialize_error=Problems writing content assist history to XML ContentAssistHistory_deserialize_error=Problems reading content assist history from XML Index: ui/org/eclipse/jdt/ui/PreferenceConstants.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/PreferenceConstants.java,v retrieving revision 1.259 diff -u -r1.259 PreferenceConstants.java --- ui/org/eclipse/jdt/ui/PreferenceConstants.java 5 Jan 2011 10:18:40 -0000 1.259 +++ ui/org/eclipse/jdt/ui/PreferenceConstants.java 11 Aug 2011 19:12:04 -0000 @@ -8,12 +8,19 @@ * Contributors: * IBM Corporation - initial API and implementation * Guven Demir - [package explorer] Alternative package name shortening: abbreviation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=299514 + * Thomas Schlosser - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876 *******************************************************************************/ package org.eclipse.jdt.ui; import java.util.Arrays; import java.util.Locale; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map.Entry; +import java.util.Map; +import java.util.Set; import java.util.StringTokenizer; +import java.util.TreeMap; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.RGB; @@ -3174,9 +3181,8 @@ * Value is of type String, a "\0"-separated list of identifiers. *

* - * @see #getExcludedCompletionProposalCategories() - * @see #setExcludedCompletionProposalCategories(String[]) * @since 3.2 + * @deprecated As of 3.8, use {@link #CODEASSIST_PROPOSAL_LISTS} instead */ public static final String CODEASSIST_EXCLUDED_CATEGORIES= "content_assist_disabled_computers"; //$NON-NLS-1$ @@ -3196,8 +3202,25 @@ *

* * @since 3.2 + * @deprecated As of 3.8, use {@link #CODEASSIST_PROPOSAL_LISTS} instead */ public static final String CODEASSIST_CATEGORY_ORDER= "content_assist_category_order"; //$NON-NLS-1$ + + /** + * A named preference that controls which completion proposal category is included in which proposal list. + *

+ * Value is of type String, a "\0"-separated list of "\1"-separated lists with categoryId where + *

    + *
  • categoryId is the String holding the category ID
  • + *
+ * + *

+ * + * @see #getProposalLists() + * @see #setProposalLists(Map) + * @since 3.8 + */ + public static final String CODEASSIST_PROPOSAL_LISTS= "content_assist_proposal_lists"; //$NON-NLS-1$ /** * A named preference that controls whether folding is enabled in the Java editor. @@ -3784,8 +3807,7 @@ store.setDefault(PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES, true); store.setDefault(PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS, false); store.setDefault(PreferenceConstants.CODEASSIST_PREFIX_COMPLETION, false); - store.setDefault(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES, "org.eclipse.jdt.ui.textProposalCategory\0org.eclipse.jdt.ui.javaTypeProposalCategory\0org.eclipse.jdt.ui.javaNoTypeProposalCategory\0"); //$NON-NLS-1$ - store.setDefault(PreferenceConstants.CODEASSIST_CATEGORY_ORDER, "org.eclipse.jdt.ui.spellingProposalCategory:65545\0org.eclipse.jdt.ui.javaTypeProposalCategory:65540\0org.eclipse.jdt.ui.javaNoTypeProposalCategory:65539\0org.eclipse.jdt.ui.textProposalCategory:65541\0org.eclipse.jdt.ui.javaAllProposalCategory:65542\0org.eclipse.jdt.ui.templateProposalCategory:2\0org.eclipse.jdt.ui.swtProposalCategory:3\0"); //$NON-NLS-1$ + store.setDefault(PreferenceConstants.CODEASSIST_PROPOSAL_LISTS, "org.eclipse.jdt.ui.templateProposalCategory:org.eclipse.jdt.ui.swtProposalCategory:org.eclipse.jdt.ui.javaAllProposalCategory:org.eclipse.pde.api.tools.ui.apitools_proposal_category:\0org.eclipse.jdt.ui.templateProposalCategory:\0org.eclipse.jdt.ui.swtProposalCategory:\0org.eclipse.pde.api.tools.ui.apitools_proposal_category:\0"); //$NON-NLS-1$ store.setDefault(PreferenceConstants.CODEASSIST_LRU_HISTORY, ""); //$NON-NLS-1$ store.setDefault(PreferenceConstants.CODEASSIST_SORTER, "org.eclipse.jdt.ui.RelevanceSorter"); //$NON-NLS-1$ store.setDefault(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, ""); //$NON-NLS-1$ @@ -4005,38 +4027,61 @@ } /** - * Returns the completion proposal categories which - * are excluded from the default proposal list. - * - * @return an array with the IDs of the excluded categories - * @see #CODEASSIST_EXCLUDED_CATEGORIES - * @since 3.4 - */ - public static String[] getExcludedCompletionProposalCategories() { - String encodedPreference= getPreference(CODEASSIST_EXCLUDED_CATEGORIES, null); - StringTokenizer tokenizer= new StringTokenizer(encodedPreference, "\0"); //$NON-NLS-1$ - String[] result= new String[tokenizer.countTokens()]; - for (int i= 0; i < result.length; i++) - result[i]= tokenizer.nextToken(); + * Returns the completion proposal categories with their corresponding proposal list indices. + * + * @return a map which maps the category IDs to a set of proposal list indices + * @see #CODEASSIST_PROPOSAL_LISTS + * @since 3.8 + */ + public static Map> getProposalLists() { + String encodedPreference= getPreference(CODEASSIST_PROPOSAL_LISTS, null); + Map> result= new HashMap>(); + StringTokenizer tok= new StringTokenizer(encodedPreference, "\0"); //$NON-NLS-1$ + for (int i= 0; tok.hasMoreTokens(); i++) { + StringTokenizer inner= new StringTokenizer(tok.nextToken(), ":"); //$NON-NLS-1$ + if (inner.countTokens() == 0) + i--; + while (inner.hasMoreTokens()) { + String category= inner.nextToken(); + Set set= result.get(category); + if (set == null) { + set= new HashSet(); + result.put(category, set); + } + set.add(Integer.valueOf(i)); + } + } return result; } /** - * Sets the completion proposal categories which are excluded from the - * default proposal list and reloads the registry. - * - * @param categories the array with the IDs of the excluded categories - * @see #CODEASSIST_EXCLUDED_CATEGORIES - * @since 3.4 - */ - public static void setExcludedCompletionProposalCategories(String[] categories) { - Assert.isLegal(categories != null); - StringBuffer buf= new StringBuffer(50 * categories.length); - for (int i= 0; i < categories.length; i++) { - buf.append(categories[i]); - buf.append('\0'); + * Sets the completion proposal categories for each proposal list and reloads the registry. + * + * @param proposalLists a map which maps the category IDs to a set of proposal list indices + * @see #CODEASSIST_PROPOSAL_LISTS + * @since 3.8 + */ + public static void setProposalLists(Map> proposalLists) { + Assert.isLegal(proposalLists != null); + int initialBufferSize= 250; + Map proposalListsCategories= new TreeMap(); + for (Entry> category : proposalLists.entrySet()) { + for (Integer index : category.getValue()) { + StringBuffer buf= proposalListsCategories.get(index); + if (buf == null) { + buf= new StringBuffer(initialBufferSize); + proposalListsCategories.put(index, buf); + } + buf.append(category.getKey()); + buf.append(":"); //$NON-NLS-1$ + } + } + StringBuffer buf= new StringBuffer(initialBufferSize * proposalListsCategories.size()); + for (StringBuffer proposalList : proposalListsCategories.values()) { + buf.append(proposalList); + buf.append("\0"); //$NON-NLS-1$ } - getPreferenceStore().setValue(CODEASSIST_EXCLUDED_CATEGORIES, buf.toString()); + getPreferenceStore().setValue(CODEASSIST_PROPOSAL_LISTS, buf.toString()); CompletionProposalComputerRegistry.getDefault().reload(); }